Deprecate local database (#1129)

Co-authored-by: Alexandru Macocian <amacocian@microsoft.com>
This commit is contained in:
2025-12-10 15:43:48 +01:00
parent 440ccf4518
commit b211ab9409
28 changed files with 215 additions and 413 deletions
@@ -1,9 +1,9 @@
using Daybreak.API.Interop.GuildWars;
using System.Core.Extensions;
using Daybreak.API.Interop.GuildWars;
using Daybreak.API.Services;
using Daybreak.Shared.Models.Api;
using Microsoft.AspNetCore.Mvc;
using Net.Sdk.Web;
using System.Core.Extensions;
namespace Daybreak.API.Controllers.Rest;
@@ -1,8 +1,8 @@
using Daybreak.API.Services;
using System.Core.Extensions;
using Daybreak.API.Services;
using Daybreak.Shared.Models.Api;
using Microsoft.AspNetCore.Mvc;
using Net.Sdk.Web;
using System.Core.Extensions;
namespace Daybreak.API.Controllers.Rest;
@@ -1,8 +1,8 @@
using Daybreak.API.Services;
using System.Core.Extensions;
using Daybreak.API.Services;
using Daybreak.Shared.Models.Api;
using Microsoft.AspNetCore.Mvc;
using Net.Sdk.Web;
using System.Core.Extensions;
namespace Daybreak.API.Controllers.Rest;
@@ -1,11 +1,11 @@
using Daybreak.API.Models;
using Daybreak.API.Services;
using Daybreak.API.WebSockets;
using Daybreak.Shared.Models.Api;
using System.Buffers;
using System.Buffers;
using System.Core.Extensions;
using System.Extensions.Core;
using System.Net.WebSockets;
using Daybreak.API.Models;
using Daybreak.API.Services;
using Daybreak.API.WebSockets;
using Daybreak.Shared.Models.Api;
namespace Daybreak.API.Controllers.WebSocket.MainPlayer;
+2 -2
View File
@@ -1,6 +1,6 @@
using FluentAssertions;
using System.Text;
using System.Text;
using Daybreak.Shared.Models.Guildwars;
using FluentAssertions;
namespace Daybreak.Tests.Models;
+2 -2
View File
@@ -1,8 +1,8 @@
using Daybreak.Shared.Models.Guildwars;
using System.Core.Extensions;
using System.Core.Extensions;
using System.Extensions;
using System.Reflection;
using System.Text;
using Daybreak.Shared.Models.Guildwars;
namespace Daybreak.Tests.Models;
+8 -8
View File
@@ -1,9 +1,9 @@
using Daybreak.Shared.Models.Guildwars;
using FluentAssertions;
using System.Core.Extensions;
using System.Core.Extensions;
using System.Extensions;
using System.Reflection;
using System.Text;
using Daybreak.Shared.Models.Guildwars;
using FluentAssertions;
namespace Daybreak.Tests.Models;
@@ -45,7 +45,7 @@ public sealed class NpcTests
{
var npcMap = new Dictionary<string, int>();
foreach(var npc in Npc.Npcs)
foreach (var npc in Npc.Npcs)
{
if (!npcMap.TryGetValue(npc.Name.ToLower(), out _))
{
@@ -56,7 +56,7 @@ public sealed class NpcTests
}
var errorMessage = new StringBuilder("Duplicated npc entries: ");
foreach(var tuple in npcMap)
foreach (var tuple in npcMap)
{
if (tuple.Value > 1)
{
@@ -76,19 +76,19 @@ public sealed class NpcTests
{
var npcMap = new Dictionary<Npc, bool>();
var definedNpcsFields = typeof(Npc).GetFields(BindingFlags.Static | BindingFlags.Public).Where(f => f.FieldType == typeof(Npc));
foreach(var field in definedNpcsFields)
foreach (var field in definedNpcsFields)
{
var npc = field.GetValue(default).ThrowIfNull().Cast<Npc>();
npcMap[npc] = false;
}
foreach(var npc in Npc.Npcs)
foreach (var npc in Npc.Npcs)
{
npcMap[npc] = true;
}
var errorMessage = new StringBuilder("Npcs not in list: ");
foreach(var tuple in npcMap)
foreach (var tuple in npcMap)
{
if (tuple.Value is false)
{
+3 -3
View File
@@ -1,9 +1,9 @@
using FluentAssertions;
using System.Core.Extensions;
using System.Extensions;
using System.Reflection;
using System.Text;
using System.Extensions;
using Daybreak.Shared.Models.Guildwars;
using System.Core.Extensions;
using FluentAssertions;
namespace Daybreak.Tests.Models;
+111 -125
View File
@@ -1,131 +1,129 @@
using Daybreak.Services.ApplicationLauncher;
using Daybreak.Services.BuildTemplates;
using Daybreak.Services.Credentials;
using Daybreak.Services.Logging;
using Daybreak.Services.Privilege;
using Daybreak.Services.Screens;
using Daybreak.Services.Shortcuts;
using Daybreak.Services.Updater;
using Daybreak.Views;
using Microsoft.Extensions.Logging;
using Slim;
using System.Extensions;
using Daybreak.Services.Options;
using Microsoft.CorrelationVector;
using System.Logging;
using Daybreak.Services.Updater.PostUpdate;
using System.Configuration;
using System.Core.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Daybreak.Services.Onboarding;
using Daybreak.Services.Menu;
using Daybreak.Services.Experience;
using Daybreak.Services.Metrics;
using Daybreak.Services.Monitoring;
using Daybreak.Services.Downloads;
using Daybreak.Services.ExceptionHandling;
using Daybreak.Services.Startup;
using Daybreak.Services.Startup.Actions;
using Daybreak.Services.GuildWars;
using Daybreak.Configuration.Options;
using System.Configuration;
using Daybreak.Services.UMod;
using Daybreak.Services.Toolbox;
using Daybreak.Services.Themes;
using Daybreak.Services.TradeChat;
using System.Extensions;
using System.Logging;
using System.Net.Http;
using System.Net.WebSockets;
using Daybreak.Services.Notifications;
using Daybreak.Services.InternetChecker;
using Daybreak.Services.Sounds;
using Daybreak.Services.TradeChat.Notifications;
using Daybreak.Services.Mods;
using Daybreak.Services.Registry;
using Daybreak.Services.Events;
using Daybreak.Services.Plugins;
using Daybreak.Services.Toolbox.Utilities;
using Daybreak.Services.Injection;
using Daybreak.Services.ReShade;
using Daybreak.Services.LaunchConfigurations;
using Daybreak.Services.ExecutableManagement;
using Daybreak.Services.DirectSong;
using Daybreak.Services.SevenZip;
using Daybreak.Services.ReShade.Notifications;
using System.Reflection;
using Daybreak.Configuration.Options;
using Daybreak.Services.Api;
using Daybreak.Services.ApplicationArguments;
using Daybreak.Services.ApplicationArguments.ArgumentHandling;
using Daybreak.Services.Toolbox.Notifications;
using Daybreak.Services.ApplicationLauncher;
using Daybreak.Services.BuildTemplates;
using Daybreak.Services.Credentials;
using Daybreak.Services.DirectSong;
using Daybreak.Services.Downloads;
using Daybreak.Services.Events;
using Daybreak.Services.ExceptionHandling;
using Daybreak.Services.ExecutableManagement;
using Daybreak.Services.Experience;
using Daybreak.Services.Graph;
using Daybreak.Services.Graph.Models;
using Daybreak.Services.Guildwars;
using Daybreak.Services.Api;
using Daybreak.Services.GuildWars;
using Daybreak.Services.Injection;
using Daybreak.Services.InternetChecker;
using Daybreak.Services.LaunchConfigurations;
using Daybreak.Services.Logging;
using Daybreak.Services.MDns;
using Daybreak.Services.Menu;
using Daybreak.Services.Metrics;
using Daybreak.Services.Mods;
using Daybreak.Services.Monitoring;
using Daybreak.Services.Notifications;
using Daybreak.Services.Notifications.Handlers;
using Microsoft.Data.Sqlite;
using Daybreak.Shared.Services.Options;
using Daybreak.Shared.Services.Menu;
using Daybreak.Shared.Services.Screens;
using Daybreak.Shared.Services.Logging;
using Daybreak.Shared.Services.Notifications;
using Daybreak.Shared.Services.TradeChat;
using Daybreak.Shared.Services.Themes;
using Daybreak.Shared.Services.Shortcuts;
using Daybreak.Shared.Services.Guildwars;
using Daybreak.Shared.Services.Registry;
using Daybreak.Shared.Services.Credentials;
using Daybreak.Shared.Services.Onboarding;
using Daybreak.Shared.Services.Sounds;
using Daybreak.Shared.Services.BuildTemplates;
using Daybreak.Shared.Services.ExecutableManagement;
using Daybreak.Shared.Services.SevenZip;
using Daybreak.Shared.Services.DirectSong;
using Daybreak.Services.Onboarding;
using Daybreak.Services.Options;
using Daybreak.Services.Plugins;
using Daybreak.Services.Privilege;
using Daybreak.Services.Registry;
using Daybreak.Services.ReShade;
using Daybreak.Services.ReShade.Notifications;
using Daybreak.Services.Screens;
using Daybreak.Services.Screenshots;
using Daybreak.Services.SevenZip;
using Daybreak.Services.Shortcuts;
using Daybreak.Services.Sounds;
using Daybreak.Services.Startup;
using Daybreak.Services.Startup.Actions;
using Daybreak.Services.Telemetry;
using Daybreak.Services.Themes;
using Daybreak.Services.Toolbox;
using Daybreak.Services.Toolbox.Notifications;
using Daybreak.Services.Toolbox.Utilities;
using Daybreak.Services.TradeChat;
using Daybreak.Services.TradeChat.Models;
using Daybreak.Services.TradeChat.Notifications;
using Daybreak.Services.UMod;
using Daybreak.Services.Updater;
using Daybreak.Services.Updater.PostUpdate;
using Daybreak.Services.Wiki;
using Daybreak.Shared.Models;
using Daybreak.Shared.Models.Plugins;
using Daybreak.Shared.Services.Api;
using Daybreak.Shared.Services.ApplicationArguments;
using Daybreak.Shared.Services.ApplicationLauncher;
using Daybreak.Shared.Services.BuildTemplates;
using Daybreak.Shared.Services.Credentials;
using Daybreak.Shared.Services.DirectSong;
using Daybreak.Shared.Services.Downloads;
using Daybreak.Shared.Services.Events;
using Daybreak.Shared.Services.ExecutableManagement;
using Daybreak.Shared.Services.Experience;
using Daybreak.Shared.Services.Guildwars;
using Daybreak.Shared.Services.Injection;
using Daybreak.Shared.Services.InternetChecker;
using Daybreak.Shared.Services.LaunchConfigurations;
using Daybreak.Shared.Services.Logging;
using Daybreak.Shared.Services.MDns;
using Daybreak.Shared.Services.Menu;
using Daybreak.Shared.Services.Metrics;
using Daybreak.Shared.Services.Mods;
using Daybreak.Shared.Services.Navigation;
using Daybreak.Shared.Services.Notifications;
using Daybreak.Shared.Services.Onboarding;
using Daybreak.Shared.Services.Options;
using Daybreak.Shared.Services.Plugins;
using Daybreak.Shared.Services.Privilege;
using Daybreak.Shared.Services.Registry;
using Daybreak.Shared.Services.ReShade;
using Daybreak.Shared.Services.Screens;
using Daybreak.Shared.Services.Screenshots;
using Daybreak.Shared.Services.SevenZip;
using Daybreak.Shared.Services.Shortcuts;
using Daybreak.Shared.Services.Sounds;
using Daybreak.Shared.Services.Startup;
using Daybreak.Shared.Services.Themes;
using Daybreak.Shared.Services.Toolbox;
using Daybreak.Shared.Services.TradeChat;
using Daybreak.Shared.Services.UMod;
using Daybreak.Shared.Services.Updater;
using Daybreak.Shared.Services.Injection;
using Daybreak.Shared.Services.Metrics;
using Daybreak.Shared.Services.Updater.PostUpdate;
using Daybreak.Shared.Services.Mods;
using Daybreak.Shared.Services.Plugins;
using Daybreak.Shared.Services.Experience;
using Daybreak.Shared.Services.ApplicationLauncher;
using Daybreak.Shared.Services.Navigation;
using Daybreak.Shared.Services.Toolbox;
using Daybreak.Shared.Services.Events;
using Daybreak.Shared.Services.Startup;
using Daybreak.Shared.Services.InternetChecker;
using Daybreak.Shared.Services.ReShade;
using Daybreak.Shared.Services.Api;
using Daybreak.Shared.Services.Privilege;
using Daybreak.Shared.Services.Downloads;
using Daybreak.Shared.Models;
using Daybreak.Shared.Services.MDns;
using Daybreak.Services.MDns;
using Daybreak.Shared.Services.Wiki;
using Daybreak.Themes;
using Daybreak.Views;
using Daybreak.Views.Copy;
using Daybreak.Views.Installation;
using Daybreak.Views.Mods;
using Daybreak.Views.Trade;
using Microsoft.CorrelationVector;
using Microsoft.Data.Sqlite;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Fast.Components.FluentUI;
using Microsoft.Identity.Client;
using Microsoft.Identity.Client.Desktop;
using OpenTelemetry.Resources;
using Daybreak.Services.Telemetry;
using System.Reflection;
using Daybreak.Shared.Models.Plugins;
using Slim;
using TrailBlazr.Extensions;
using TrailBlazr.Services;
using Microsoft.Fast.Components.FluentUI;
using Daybreak.Themes;
using Daybreak.Shared.Services.Wiki;
using Daybreak.Services.Wiki;
using Daybreak.Services.Graph.Models;
using Daybreak.Services.Graph;
using Microsoft.Identity.Client;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
using Microsoft.Identity.Client.Desktop;
using System.Net.Http;
using Daybreak.Views.Trade;
using Daybreak.Services.TradeChat.Models;
using Daybreak.Views.Installation;
using Daybreak.Views.Copy;
using Daybreak.Views.Mods;
using Daybreak.Shared.Services.Screenshots;
using Daybreak.Services.Screenshots;
namespace Daybreak.Configuration;
public class ProjectConfiguration : PluginConfigurationBase
{
private const string DbConnectionString = "Data Source=Daybreak.sqlite.db";
public static readonly Version CurrentVersion = Version.Parse(Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? throw new InvalidOperationException("Unable to get current version"));
public override void RegisterResolvers(IServiceManager serviceManager)
@@ -143,18 +141,9 @@ public class ProjectConfiguration : PluginConfigurationBase
// Add FluentUI components
services.AddFluentUIComponents();
services.AddTrailBlazr();
RegisterHttpClients(services);
services.AddScoped(sp =>
{
var connection = new SqliteConnection(DbConnectionString);
connection.Open();
return connection;
});
services.AddScoped(sp => new TradeQuoteDbContext(sp.GetRequiredService<SqliteConnection>()));
services.AddScoped(sp => new NotificationsDbContext(sp.GetRequiredService<SqliteConnection>()));
services.AddScoped(sp => new TradeMessagesDbContext(sp.GetRequiredService<SqliteConnection>()));
services.AddSingleton<IPublicClientApplication>(sp =>
{
var logger = sp.GetRequiredService<ILogger<PublicClientApplication>>();
@@ -166,7 +155,7 @@ public class ProjectConfiguration : PluginConfigurationBase
// Redact logs that contain PII which user can enable to send to the telemetry server
message = "[REDACTED]";
}
var equivalentLogLevel = logLevel switch
{
Microsoft.Identity.Client.LogLevel.Error => LogLevel.Error,
@@ -185,7 +174,7 @@ public class ProjectConfiguration : PluginConfigurationBase
new DaybreakMsalHttpClientProvider(new HttpClient(SetupLoggingAndMetrics<PublicClientApplication>(sp))))
.Build();
});
services.AddSingleton<SwappableLoggerProvider>();
services.AddSingleton<ILogsManager, JsonLogsManager>();
services.AddSingleton<IConsoleLogsWriter, ConsoleLogsWriter>();
@@ -251,7 +240,7 @@ public class ProjectConfiguration : PluginConfigurationBase
services.AddSingleton<ISoundService, SoundService>();
services.AddSingleton<IInternetCheckingService, InternetCheckingService>();
services.AddSingleton<IConnectivityStatus, ConnectivityStatus>();
services.AddSingleton<INotificationStorage, NotificationStorage>();
services.AddSingleton<INotificationStorage, InMemoryNotificationStorage>();
services.AddSingleton<ITradeAlertingService, TradeAlertingService>();
services.AddSingleton<IModsManager, ModsManager>();
services.AddSingleton<IPluginsService, PluginsService>();
@@ -306,7 +295,7 @@ public class ProjectConfiguration : PluginConfigurationBase
viewProducer.RegisterView<LaunchView, LaunchViewModel>(isSingleton: true);
viewProducer.RegisterView<OptionView, OptionViewModel>();
viewProducer.RegisterView<Views.FocusView, FocusViewModel>();
viewProducer.RegisterView<FocusView, FocusViewModel>();
viewProducer.RegisterView<BuildListView, BuildListViewModel>();
viewProducer.RegisterView<BuildRoutingView, BuildRoutingViewModel>();
viewProducer.RegisterView<SingleBuildTemplateView, SingleBuildTemplateViewModel>();
@@ -347,12 +336,9 @@ public class ProjectConfiguration : PluginConfigurationBase
startupActionProducer.ThrowIfNull();
startupActionProducer.RegisterAction<RestoreWindowPositionStartupAction>();
startupActionProducer.RegisterAction<EnsureDatabaseTablesExist>();
startupActionProducer.RegisterAction<RenameInstallerAction>();
startupActionProducer.RegisterAction<UpdateUModAction>();
startupActionProducer.RegisterAction<CredentialsOptionsMigrator>();
startupActionProducer.RegisterAction<CleanupDatabases>();
startupActionProducer.RegisterAction<DeleteOldDatabase>();
startupActionProducer.RegisterAction<UpdateToolboxAction>();
}
-1
View File
@@ -68,7 +68,6 @@
<PackageReference Include="Reloaded.Assembler" />
<PackageReference Include="WpfExtended.SourceGeneration" />
<PackageReference Include="WpfScreenHelper" />
<PackageReference Include="Squealify" />
<PackageReference Include="PeNet" />
<PackageReference Include="Plumsy" />
<PackageReference Include="securifybv.ShellLink" />
+6 -7
View File
@@ -1,4 +1,8 @@
using Daybreak.Configuration;
using System.Core.Extensions;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows;
using Daybreak.Configuration;
using Daybreak.Services.ExceptionHandling;
using Daybreak.Services.Navigation;
using Daybreak.Services.Telemetry;
@@ -23,11 +27,6 @@ using Microsoft.Extensions.Logging;
using Microsoft.Web.WebView2.Core;
using Slim;
using Slim.Integration.ServiceCollection;
using System.Core.Extensions;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows;
using WpfExtended.Blazor.Launch;
//The following lines are needed to expose internal objects to the test project
@@ -157,7 +156,7 @@ public sealed class Launcher : BlazorHybridApplication<App>
var menuServiceProducer = this.ServiceProvider.GetRequiredService<IMenuServiceProducer>();
var themeProducer = this.ServiceProvider.GetRequiredService<IThemeProducer>();
await this.Dispatcher.InvokeAsync(() =>
await this.Dispatcher.InvokeAsync(() =>
{
// Hide the main window until the application is fully loaded. Main window will be shown by the RestoreWindowPositionStartupAction
var mainWindow = this.ServiceProvider.GetRequiredService<BlazorHostWindow>();
@@ -1,6 +1,5 @@
using PeNet;
using PeNet.Header.Pe;
using System;
namespace Daybreak.Services.Guildwars.Utils;
/// <summary>
@@ -1,6 +1,6 @@
using Daybreak.Shared.Models.Notifications;
using System.Windows;
using Daybreak.Shared.Models.Notifications;
using Daybreak.Shared.Models.Notifications.Handling;
using System.Windows;
namespace Daybreak.Services.Notifications.Handlers;
@@ -1,11 +1,15 @@
using Daybreak.Shared.Models.Guildwars;
using System.Core.Extensions;
using Daybreak.Shared.Models.Guildwars;
using Daybreak.Shared.Models.Notifications;
using Daybreak.Shared.Models.Notifications.Handling;
using Daybreak.Views;
using TrailBlazr.Services;
namespace Daybreak.Services.Notifications.Handlers;
public sealed class NavigateToCalendarViewHandler() : INotificationHandler
public sealed class NavigateToCalendarViewHandler(IViewManager viewManager) : INotificationHandler
{
//private readonly IViewManager viewManager = viewManager.ThrowIfNull();
private readonly IViewManager viewManager = viewManager.ThrowIfNull();
public void OpenNotification(Notification notification)
{
@@ -16,6 +20,6 @@ public sealed class NavigateToCalendarViewHandler() : INotificationHandler
return;
}
//this.viewManager.ShowView<EventCalendarView>();
this.viewManager.ShowView<EventCalendarView>();
}
}
@@ -0,0 +1,46 @@
using System.Extensions;
using Daybreak.Services.Notifications.Models;
namespace Daybreak.Services.Notifications;
public sealed class InMemoryNotificationStorage : INotificationStorage
{
private readonly SemaphoreSlim semaphore = new(1, 1);
private readonly List<NotificationDTO> notifications = [];
public async ValueTask<IEnumerable<NotificationDTO>> GetNotifications(CancellationToken cancellationToken)
{
using var ctx = await this.semaphore.Acquire(cancellationToken);
return [.. this.notifications];
}
public async ValueTask<IEnumerable<NotificationDTO>> GetPendingNotifications(CancellationToken cancellationToken)
{
using var ctx = await this.semaphore.Acquire(cancellationToken);
return [.. this.notifications.Where(dto => !dto.Closed)];
}
public ValueTask OpenNotification(NotificationDTO notificationDTO, CancellationToken cancellationToken)
{
notificationDTO.Closed = true;
return ValueTask.CompletedTask;
}
public async ValueTask RemoveAllNotifications(CancellationToken cancellationToken)
{
using var ctx = await this.semaphore.Acquire(cancellationToken);
this.notifications.Clear();
}
public async ValueTask RemoveNotification(NotificationDTO notificationDTO, CancellationToken cancellationToken)
{
using var ctx = await this.semaphore.Acquire(cancellationToken);
this.notifications.Remove(notificationDTO);
}
public async ValueTask StoreNotification(NotificationDTO notification, CancellationToken cancellationToken)
{
using var ctx = await this.semaphore.Acquire(cancellationToken);
this.notifications.Add(notification);
}
}
@@ -1,11 +1,7 @@
using Squealify;
namespace Daybreak.Services.Notifications.Models;
namespace Daybreak.Services.Notifications.Models;
[Table("notifications")]
public partial class NotificationDTO
{
[PrimaryKey]
public required string Id { get; init; } = string.Empty;
public int Level { get; init; }
public long ExpirationTime { get; set; }
@@ -1,105 +0,0 @@
using Daybreak.Services.Notifications.Models;
using Microsoft.Extensions.Logging;
using System.Core.Extensions;
using System.Extensions.Core;
namespace Daybreak.Services.Notifications;
internal sealed class NotificationStorage(
NotificationsDbContext liteCollection,
ILogger<NotificationStorage> logger) : INotificationStorage
{
private List<NotificationDTO>? notificationsCache;
private readonly NotificationsDbContext liteCollection = liteCollection.ThrowIfNull();
private readonly ILogger<NotificationStorage> logger = logger.ThrowIfNull();
public async ValueTask<IEnumerable<NotificationDTO>> GetPendingNotifications(CancellationToken cancellationToken)
{
try
{
this.notificationsCache ??= await this.liteCollection.FindAll(cancellationToken).ToListAsync(cancellationToken);
return this.notificationsCache
.Where(dto => dto.Closed == false && dto.ExpirationTime < DateTimeOffset.Now.ToUnixTimeMilliseconds());
}
catch (Exception ex)
{
this.logger.CreateScopedLogger().LogError(ex, "Failed to get pending notifications");
throw;
}
}
public async ValueTask<IEnumerable<NotificationDTO>> GetNotifications(CancellationToken cancellationToken)
{
try
{
this.notificationsCache ??= await this.liteCollection.FindAll(cancellationToken).ToListAsync(cancellationToken);
return this.notificationsCache;
}
catch (Exception ex)
{
this.logger.CreateScopedLogger().LogError(ex, "Failed to get notifications");
throw;
}
}
public async ValueTask StoreNotification(NotificationDTO notification, CancellationToken cancellationToken)
{
notification.ThrowIfNull();
try
{
await this.liteCollection.Insert(notification, cancellationToken);
this.notificationsCache ??= await this.liteCollection.FindAll(cancellationToken).ToListAsync(cancellationToken);
this.notificationsCache.Add(notification);
}
catch (Exception ex)
{
this.logger.CreateScopedLogger().LogError(ex, "Failed to store notification");
throw;
}
}
public async ValueTask OpenNotification(NotificationDTO notificationDTO, CancellationToken cancellationToken)
{
notificationDTO.ThrowIfNull();
try
{
notificationDTO.Closed = true;
await this.liteCollection.Update(notificationDTO, cancellationToken);
this.notificationsCache = await this.liteCollection.FindAll(cancellationToken).ToListAsync(cancellationToken);
}
catch (Exception ex)
{
this.logger.CreateScopedLogger().LogError(ex, "Failed to open notification");
throw;
}
}
public async ValueTask RemoveNotification(NotificationDTO notificationDTO, CancellationToken cancellationToken)
{
try
{
await this.liteCollection.Delete(notificationDTO.Id, cancellationToken);
this.notificationsCache ??= await this.liteCollection.FindAll(cancellationToken).ToListAsync(cancellationToken);
this.notificationsCache.Remove(notificationDTO);
}
catch (Exception ex)
{
this.logger.CreateScopedLogger().LogError(ex, "Failed to remove notification");
throw;
}
}
public async ValueTask RemoveAllNotifications(CancellationToken cancellationToken)
{
try
{
await this.liteCollection.DeleteAll(cancellationToken);
this.notificationsCache = default;
}
catch (Exception ex)
{
this.logger.CreateScopedLogger().LogError(ex, "Failed to remove all notifications");
throw;
}
}
}
@@ -1,7 +0,0 @@
using Squealify;
using System.Data.Common;
namespace Daybreak.Services.Notifications;
public sealed class NotificationsDbContext(DbConnection connection) : NotificationDTOTableContextBase(connection)
{
}
@@ -1,52 +0,0 @@
using Daybreak.Services.Notifications;
using Daybreak.Services.TradeChat;
using Daybreak.Shared.Models;
using Microsoft.Extensions.Logging;
using System.Core.Extensions;
using System.Extensions;
using System.Extensions.Core;
namespace Daybreak.Services.Startup.Actions;
internal sealed class CleanupDatabases(
TradeQuoteDbContext quotesCollection,
NotificationsDbContext notificationsCollection,
TradeMessagesDbContext traderMessagesCollection,
ILogger<CleanupDatabases> logger) : StartupActionBase
{
private readonly TradeQuoteDbContext quotesCollection = quotesCollection.ThrowIfNull();
private readonly NotificationsDbContext notificationsCollection = notificationsCollection.ThrowIfNull();
private readonly TradeMessagesDbContext traderMessagesCollection = traderMessagesCollection.ThrowIfNull();
private readonly ILogger<CleanupDatabases> logger = logger.ThrowIfNull();
public override async Task ExecuteOnStartupAsync(CancellationToken cancellationToken)
{
var scopedLogger = this.logger.CreateScopedLogger();
var notifications = await this.notificationsCollection.FindAll(cancellationToken).ToListAsync(cancellationToken);
if (notifications.Count > 1000)
{
await this.notificationsCollection.DeleteAll(cancellationToken);
scopedLogger.LogDebug("Cleared notifications database");
}
var allQuotes = await this.quotesCollection.FindAll(cancellationToken).ToListAsync(cancellationToken);
if (allQuotes.Count > 20000)
{
// Delete the oldest 2000 entries in the db. We probably won't need them anymore
var quotes = await this.quotesCollection.FindAll(cancellationToken).OrderBy(q => q.TimeStamp).Take(2000).ToListAsync(cancellationToken);
foreach (var quote in quotes)
{
await this.quotesCollection.Delete(quote.Id, cancellationToken);
}
await this.quotesCollection.DeleteAll(cancellationToken);
scopedLogger.LogDebug("Cleared quotes database");
}
var traderMessages = await this.traderMessagesCollection.FindAll(cancellationToken).ToListAsync(cancellationToken);
if (traderMessages.Count > 1000)
{
await this.traderMessagesCollection.DeleteAll(cancellationToken);
scopedLogger.LogDebug("Cleared trader messages database");
}
}
}
@@ -1,16 +0,0 @@
using Daybreak.Shared.Models;
using Daybreak.Shared.Utils;
using System.IO;
namespace Daybreak.Services.Startup.Actions;
internal sealed class DeleteOldDatabase : StartupActionBase
{
public override void ExecuteOnStartup()
{
var oldDbPath = PathUtils.GetAbsolutePathFromRoot("daybreak.db");
if (File.Exists(oldDbPath))
{
File.Delete(oldDbPath);
}
}
}
@@ -1,22 +0,0 @@
using Daybreak.Services.Notifications;
using Daybreak.Services.TradeChat;
using Daybreak.Shared.Models;
namespace Daybreak.Services.Startup.Actions;
public sealed class EnsureDatabaseTablesExist(
TradeQuoteDbContext tradeQuoteDbContext,
TradeMessagesDbContext tradeMessagesDbContext,
NotificationsDbContext notificationsDbContext)
: StartupActionBase
{
private readonly TradeQuoteDbContext tradeQuoteDbContext = tradeQuoteDbContext;
private readonly TradeMessagesDbContext tradeMessagesDbContext = tradeMessagesDbContext;
private readonly NotificationsDbContext notificationsDbContext = notificationsDbContext;
public override async Task ExecuteOnStartupAsync(CancellationToken cancellationToken)
{
await this.tradeQuoteDbContext.CreateTableIfNotExists(cancellationToken);
await this.tradeMessagesDbContext.CreateTableIfNotExists(cancellationToken);
await this.notificationsDbContext.CreateTableIfNotExists(cancellationToken);
}
}
@@ -1,11 +1,7 @@
using Squealify;
namespace Daybreak.Services.TradeChat.Models;
namespace Daybreak.Services.TradeChat.Models;
[Table("traderMessages")]
public partial class TraderMessageDTO
public sealed class TraderMessageDTO
{
[PrimaryKey]
public required long Id { get; init; }
public int TraderSource { get; init; }
@@ -1,11 +1,7 @@
using Squealify;
namespace Daybreak.Services.TradeChat.Models;
namespace Daybreak.Services.TradeChat.Models;
[Table("quotes")]
public sealed class TraderQuoteDTO
{
[PrimaryKey]
public required string Id { get; init; } = Guid.NewGuid().ToString();
public int ItemId { get; set; }
@@ -1,24 +1,23 @@
using Daybreak.Services.TradeChat.Models;
using System.Core.Extensions;
using System.Extensions;
using Daybreak.Services.TradeChat.Models;
namespace Daybreak.Services.TradeChat;
internal sealed class TradeHistoryDatabase(
TradeMessagesDbContext liteCollection) : ITradeHistoryDatabase
internal sealed class TradeHistoryDatabase : ITradeHistoryDatabase
{
private readonly TradeMessagesDbContext liteCollection = liteCollection.ThrowIfNull();
private readonly SemaphoreSlim semaphore = new(1, 1);
private readonly List<TraderMessageDTO> inMemoryStore = [];
public async ValueTask<IEnumerable<TraderMessageDTO>> GetTraderMessagesSinceTime(DateTimeOffset since, CancellationToken cancellationToken)
{
return await this.liteCollection
.FindAll(cancellationToken)
.Where(async (t, ct) => await Task.FromResult(t.Timestamp > since))
.ToListAsync(cancellationToken);
using var ctx = await this.semaphore.Acquire(cancellationToken);
return [.. this.inMemoryStore.Where(t => t.Timestamp > since)];
}
public async ValueTask<bool> StoreTraderMessage(TraderMessageDTO message, CancellationToken cancellationToken)
{
await this.liteCollection.Update(message, cancellationToken);
using var ctx = await this.semaphore.Acquire(cancellationToken);
this.inMemoryStore.Add(message);
return true;
}
}
@@ -1,7 +0,0 @@
using Squealify;
using System.Data.Common;
namespace Daybreak.Services.TradeChat;
public sealed class TradeMessagesDbContext(DbConnection connection) : TraderMessageDTOTableContextBase(connection)
{
}
@@ -1,8 +0,0 @@
using Squealify;
using System.Data.Common;
namespace Daybreak.Services.TradeChat;
public sealed class TradeQuoteDbContext(DbConnection connection) : TraderQuoteDTOTableContextBase(connection)
{
public ValueTask<DbTransaction> CreateTransaction(CancellationToken cancellationToken) => this.Connection.BeginTransactionAsync(cancellationToken);
}
+3 -3
View File
@@ -3,10 +3,10 @@ using Daybreak.Shared.Models.Async;
using Daybreak.Shared.Services.ExecutableManagement;
using Daybreak.Shared.Services.Guildwars;
using System.Extensions;
using System.Threading.Tasks;
using TrailBlazr.ViewModels;
namespace Daybreak.Views;
public class ExecutablesViewModel(
IGuildWarsInstaller guildWarsInstaller,
IGuildWarsExecutableManager guildWarsExecutableManager)
@@ -72,7 +72,7 @@ public class ExecutablesViewModel(
public async void UpdateExecutable(ExecutablePath executable)
{
foreach(var e in this.Executables)
foreach (var e in this.Executables)
{
e.Locked = true;
}
@@ -116,7 +116,7 @@ public class ExecutablesViewModel(
}
catch
{
}
finally
{
-1
View File
@@ -57,7 +57,6 @@
<PackageVersion Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageVersion Include="SharpCompress" Version="0.41.0" />
<PackageVersion Include="Slim" Version="1.11.2" />
<PackageVersion Include="Squealify" Version="0.8.2.2" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="9.0.6" />
<PackageVersion Include="Swashbuckle.AspNetCore.Swagger" Version="9.0.6" />
<PackageVersion Include="Swashbuckle.AspNetCore.SwaggerGen" Version="9.0.6" />