From ce6cedaf4be53d52f2e558055b91e515b92e4c83 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 19 Jul 2019 13:15:45 -0400 Subject: add background fetch for mod compatibility list (#651) --- src/SMAPI.Web/BackgroundService.cs | 92 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/SMAPI.Web/BackgroundService.cs (limited to 'src/SMAPI.Web/BackgroundService.cs') diff --git a/src/SMAPI.Web/BackgroundService.cs b/src/SMAPI.Web/BackgroundService.cs new file mode 100644 index 00000000..2ccfd5f7 --- /dev/null +++ b/src/SMAPI.Web/BackgroundService.cs @@ -0,0 +1,92 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Hangfire; +using Microsoft.Extensions.Hosting; +using StardewModdingAPI.Toolkit; +using StardewModdingAPI.Toolkit.Framework.Clients.Wiki; +using StardewModdingAPI.Web.Framework.Caching.Wiki; + +namespace StardewModdingAPI.Web +{ + /// A hosted service which runs background data updates. + /// Task methods need to be static, since otherwise Hangfire will try to serialise the entire instance. + internal class BackgroundService : IHostedService, IDisposable + { + /********* + ** Fields + *********/ + /// The background task server. + private static BackgroundJobServer JobServer; + + /// The cache in which to store mod metadata. + private static IWikiCacheRepository WikiCache; + + + /********* + ** Public methods + *********/ + /**** + ** Hosted service + ****/ + /// Construct an instance. + /// The cache in which to store mod metadata. + public BackgroundService(IWikiCacheRepository wikiCache) + { + BackgroundService.WikiCache = wikiCache; + } + + /// Start the service. + /// Tracks whether the start process has been aborted. + public Task StartAsync(CancellationToken cancellationToken) + { + this.TryInit(); + + // set startup tasks + BackgroundJob.Enqueue(() => BackgroundService.UpdateWikiAsync()); + + // set recurring tasks + RecurringJob.AddOrUpdate(() => BackgroundService.UpdateWikiAsync(), "*/10 * * * *"); + + return Task.CompletedTask; + } + + /// Triggered when the application host is performing a graceful shutdown. + /// Tracks whether the shutdown process should no longer be graceful. + public async Task StopAsync(CancellationToken cancellationToken) + { + if (BackgroundService.JobServer != null) + await BackgroundService.JobServer.WaitForShutdownAsync(cancellationToken); + } + + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + public void Dispose() + { + BackgroundService.JobServer?.Dispose(); + } + + /**** + ** Tasks + ****/ + /// Update the cached wiki metadata. + public static async Task UpdateWikiAsync() + { + WikiModList wikiCompatList = await new ModToolkit().GetWikiCompatibilityListAsync(); + BackgroundService.WikiCache.SaveWikiData(wikiCompatList.StableVersion, wikiCompatList.BetaVersion, wikiCompatList.Mods, out _, out _); + } + + + /********* + ** Private method + *********/ + /// Initialise the background service if it's not already initialised. + /// The background service is already initialised. + private void TryInit() + { + if (BackgroundService.JobServer != null) + throw new InvalidOperationException("The scheduler service is already started."); + + BackgroundService.JobServer = new BackgroundJobServer(); + } + } +} -- cgit