refactor PluginsManifest to use conditional requests

This commit is contained in:
Ioannis G 2022-01-11 06:00:14 +02:00
parent de97cd4e52
commit 33fb0ddee6
No known key found for this signature in database
GPG key ID: EAC0E4E5E36AC49E
3 changed files with 29 additions and 51 deletions

View file

@ -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<UserPlugin> UserPlugins { get; private set; } = new List<UserPlugin>();
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<UserPlugin> UserPlugins { get; private set; } = new List<UserPlugin>();
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<List<UserPlugin>>(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<List<UserPlugin>>(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<UserPlugin>();
Log.Exception($"|PluginsManifest.{nameof(UpdateManifestAsync)}|Http request failed", e);
}
finally
{

View file

@ -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<List<Result>> 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;
}
}
}

View file

@ -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<List<Result>> 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<List<Result>> RequestInstallOrUpdate(string searchName, CancellationToken token)
{
if (!PluginsManifest.UserPlugins.Any())
{
await UpdateManifestAsync();
}
await UpdateManifestAsync();
token.ThrowIfCancellationRequested();