From 33fb0ddee668651ef441c557d7354ab0620041b1 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Tue, 11 Jan 2022 06:00:14 +0200 Subject: [PATCH] refactor PluginsManifest to use conditional requests --- .../ExternalPlugins/PluginsManifest.cs | 49 ++++++++++--------- .../Main.cs | 19 ------- .../PluginsManager.cs | 12 ++--- 3 files changed, 29 insertions(+), 51 deletions(-) diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs index a9585f6a4..dc1c0cc21 100644 --- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -1,7 +1,8 @@ -using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Logger; using System; using System.Collections.Generic; +using System.Net; +using System.Net.Http; using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -10,43 +11,45 @@ namespace Flow.Launcher.Core.ExternalPlugins { public static class PluginsManifest { - static PluginsManifest() - { - UpdateTask = UpdateManifestAsync(); - } + private const string manifestFileUrl = "https://raw.githubusercontent.com/Flow-Launcher/Flow.Launcher.PluginsManifest/plugin_api_v2/plugins.json"; - public static List UserPlugins { get; private set; } = new List(); - - public static Task UpdateTask { get; private set; } + private static HttpClient httpClient = new HttpClient(); private static readonly SemaphoreSlim manifestUpdateLock = new(1); - public static Task UpdateManifestAsync() - { - if (manifestUpdateLock.CurrentCount == 0) - { - return UpdateTask; - } + private static string latestEtag = ""; - return UpdateTask = DownloadManifestAsync(); - } + public static List UserPlugins { get; private set; } = new List(); - private static async Task DownloadManifestAsync() + public static async Task UpdateManifestAsync() { try { await manifestUpdateLock.WaitAsync().ConfigureAwait(false); - await using var jsonStream = await Http.GetStreamAsync("https://raw.githubusercontent.com/Flow-Launcher/Flow.Launcher.PluginsManifest/plugin_api_v2/plugins.json") - .ConfigureAwait(false); + var request = new HttpRequestMessage(HttpMethod.Get, manifestFileUrl); + request.Headers.Add("If-None-Match", latestEtag); - UserPlugins = await JsonSerializer.DeserializeAsync>(jsonStream).ConfigureAwait(false); + var response = await httpClient.SendAsync(request).ConfigureAwait(false); + + if (response.StatusCode == HttpStatusCode.OK) + { + Log.Info($"|PluginsManifest.{nameof(UpdateManifestAsync)}|Fetched plugins from manifest repo"); + + var json = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + + UserPlugins = await JsonSerializer.DeserializeAsync>(json).ConfigureAwait(false); + + latestEtag = response.Headers.ETag.Tag; + } + else if (response.StatusCode != HttpStatusCode.NotModified) + { + Log.Warn($"|PluginsManifest.{nameof(UpdateManifestAsync)}|Http response for manifest file was {response.StatusCode}"); + } } catch (Exception e) { - Log.Exception("|PluginManagement.GetManifest|Encountered error trying to download plugins manifest", e); - - UserPlugins = new List(); + Log.Exception($"|PluginsManifest.{nameof(UpdateManifestAsync)}|Http request failed", e); } finally { diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 8aaae95d6..3d3f9307e 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -24,8 +24,6 @@ namespace Flow.Launcher.Plugin.PluginsManager internal PluginsManager pluginManager; - private DateTime lastUpdateTime = DateTime.MinValue; - public Control CreateSettingPanel() { return new PluginsManagerSettings(viewModel); @@ -38,12 +36,6 @@ namespace Flow.Launcher.Plugin.PluginsManager viewModel = new SettingsViewModel(context, Settings); contextMenu = new ContextMenu(Context); pluginManager = new PluginsManager(Context, Settings); - _manifestUpdateTask = pluginManager - .UpdateManifestAsync(true) - .ContinueWith(_ => - { - lastUpdateTime = DateTime.Now; - }, TaskContinuationOptions.OnlyOnRanToCompletion); return Task.CompletedTask; } @@ -53,8 +45,6 @@ namespace Flow.Launcher.Plugin.PluginsManager return contextMenu.LoadContextMenus(selectedResult); } - private Task _manifestUpdateTask = Task.CompletedTask; - public async Task> QueryAsync(Query query, CancellationToken token) { var search = query.Search; @@ -62,14 +52,6 @@ namespace Flow.Launcher.Plugin.PluginsManager if (string.IsNullOrWhiteSpace(search)) return pluginManager.GetDefaultHotKeys(); - if ((DateTime.Now - lastUpdateTime).TotalHours > 12 && _manifestUpdateTask.IsCompleted) // 12 hours - { - _manifestUpdateTask = pluginManager.UpdateManifestAsync().ContinueWith(t => - { - lastUpdateTime = DateTime.Now; - }, TaskContinuationOptions.OnlyOnRanToCompletion); - } - return search switch { //search could be url, no need ToLower() when passed in @@ -100,7 +82,6 @@ namespace Flow.Launcher.Plugin.PluginsManager public async Task ReloadDataAsync() { await pluginManager.UpdateManifestAsync(); - lastUpdateTime = DateTime.Now; } } } \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 53e994d34..aed5f5e2f 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -59,7 +59,7 @@ namespace Flow.Launcher.Plugin.PluginsManager } else { - _downloadManifestTask = PluginsManifest.UpdateTask; + _downloadManifestTask = PluginsManifest.UpdateManifestAsync(); if (!silent) _downloadManifestTask.ContinueWith(_ => Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_update_failed_title"), @@ -181,10 +181,7 @@ namespace Flow.Launcher.Plugin.PluginsManager internal async ValueTask> RequestUpdate(string search, CancellationToken token) { - if (!PluginsManifest.UserPlugins.Any()) - { - await UpdateManifestAsync(); - } + await UpdateManifestAsync(); token.ThrowIfCancellationRequested(); @@ -371,10 +368,7 @@ namespace Flow.Launcher.Plugin.PluginsManager internal async ValueTask> RequestInstallOrUpdate(string searchName, CancellationToken token) { - if (!PluginsManifest.UserPlugins.Any()) - { - await UpdateManifestAsync(); - } + await UpdateManifestAsync(); token.ThrowIfCancellationRequested();