From 4dc2d74ccfb59150390cfa75d11fa12a7c49507f Mon Sep 17 00:00:00 2001 From: estrogen elf <87099578+BlossomiShymae@users.noreply.github.com> Date: Wed, 18 Jun 2025 16:56:51 -0500 Subject: [PATCH] feat: use file kv-store for posts --- .gitignore | 5 ++ Needlework.Net/App.axaml.cs | 9 +++ Needlework.Net/Needlework.Net.csproj | 1 + Needlework.Net/Program.cs | 9 ++- .../Services/HextechDocsPostService.cs | 56 +++++++++++-------- 5 files changed, 55 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index 104b544..7335b05 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ bld/ [Oo]bj/ [Ll]og/ [Ll]ogs/ +[Dd]ata/ # Visual Studio 2015/2017 cache/options directory .vs/ @@ -482,3 +483,7 @@ $RECYCLE.BIN/ # Vim temporary swap files *.swp + +*.sqlite +*.sqlite-shm +*.sqlite-wal diff --git a/Needlework.Net/App.axaml.cs b/Needlework.Net/App.axaml.cs index ea4277d..7a5bcdf 100644 --- a/Needlework.Net/App.axaml.cs +++ b/Needlework.Net/App.axaml.cs @@ -1,3 +1,4 @@ +using Akavache; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; @@ -9,6 +10,7 @@ using Needlework.Net.ViewModels.MainWindow; using Needlework.Net.ViewModels.Pages; using Needlework.Net.Views.MainWindow; using System; +using System.Reactive.Linq; using System.Reflection; using System.Text.Json; using System.Threading.Tasks; @@ -59,6 +61,13 @@ public partial class App : Application, IEnableLogger DataContext = _serviceProvider.GetRequiredService() }; MainWindow = desktop.MainWindow; + + desktop.ShutdownRequested += (_, _) => + { + var blobCache = _serviceProvider.GetRequiredService(); + blobCache.Flush().Wait(); + blobCache.Dispose(); + }; } base.OnFrameworkInitializationCompleted(); diff --git a/Needlework.Net/Needlework.Net.csproj b/Needlework.Net/Needlework.Net.csproj index 636e0c1..c1c6e5b 100644 --- a/Needlework.Net/Needlework.Net.csproj +++ b/Needlework.Net/Needlework.Net.csproj @@ -17,6 +17,7 @@ + diff --git a/Needlework.Net/Program.cs b/Needlework.Net/Program.cs index 84119d7..1251061 100644 --- a/Needlework.Net/Program.cs +++ b/Needlework.Net/Program.cs @@ -1,4 +1,6 @@ -using Avalonia; +using Akavache; +using Akavache.Sqlite3; +using Avalonia; using Avalonia.Controls.Templates; using Flurl.Http.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -105,6 +107,11 @@ class Program builder.AddSingleton(); builder.AddSingleton(); builder.AddSingleton(); + builder.AddSingleton((_) => + { + Directory.CreateDirectory("Data"); + return new SqlRawPersistentBlobCache("Data/data.sqlite"); + }); builder.AddSingleton(new FlurlClientCache() .Add("GithubClient", "https://api.github.com") .Add("GithubUserContentClient", "https://raw.githubusercontent.com") diff --git a/Needlework.Net/Services/HextechDocsPostService.cs b/Needlework.Net/Services/HextechDocsPostService.cs index 962d815..5955672 100644 --- a/Needlework.Net/Services/HextechDocsPostService.cs +++ b/Needlework.Net/Services/HextechDocsPostService.cs @@ -1,41 +1,49 @@ -using AngleSharp; -using FastCache; +using Akavache; +using AngleSharp; +using Needlework.Net.Extensions; using Needlework.Net.Models; using System; using System.Collections.Generic; +using System.Reactive.Linq; using System.Threading.Tasks; namespace Needlework.Net.Services { - public class HextechDocsPostService + public class HextechDocsPostService : IEnableLogger { private readonly IBrowsingContext _context = BrowsingContext.New(Configuration.Default.WithDefaultLoader()); + private readonly IBlobCache _blobCache; + + public HextechDocsPostService(IBlobCache blobCache) + { + _blobCache = blobCache; + } + public async Task> GetPostsAsync() { - if (Cached>.TryGet(nameof(GetPostsAsync), out var cached)) + return await _blobCache.GetOrFetchObject("HextechDocsPosts", async () => { - return cached; - } - - var document = await _context.OpenAsync("https://hextechdocs.dev/tag/lcu/"); - var elements = document.QuerySelectorAll("article.post-card"); - var posts = new List(); - foreach (var element in elements) - { - var path = element.QuerySelector("a.post-card-content-link")!.GetAttribute("href")!; - var title = element.QuerySelector(".post-card-title")!.TextContent; - var excerpt = element.QuerySelector(".post-card-excerpt > p")!.TextContent; - var post = new HextechDocsPost() + this.Log() + .Debug("Downloading HextechDocs posts..."); + var document = await _context.OpenAsync("https://hextechdocs.dev/tag/lcu/"); + var elements = document.QuerySelectorAll("article.post-card"); + var posts = new List(); + foreach (var element in elements) { - Path = path, - Title = title, - Excerpt = excerpt, - }; - posts.Add(post); - } - - return cached.Save(posts, TimeSpan.FromMinutes(60)); + var path = element.QuerySelector("a.post-card-content-link")!.GetAttribute("href")!; + var title = element.QuerySelector(".post-card-title")!.TextContent; + var excerpt = element.QuerySelector(".post-card-excerpt > p")!.TextContent; + var post = new HextechDocsPost() + { + Path = path, + Title = title, + Excerpt = excerpt, + }; + posts.Add(post); + } + return posts; + }, DateTimeOffset.Now + TimeSpan.FromHours(12)); } } }