using System.Reactive.Concurrency; using System.Reactive.Linq; using InnovEnergy.App.Backend.DataTypes; using InnovEnergy.App.Backend.DataTypes.Methods; using InnovEnergy.App.Backend.Relations; using InnovEnergy.Lib.Utils; using SQLite; namespace InnovEnergy.App.Backend.Database; public static partial class Db { internal const String DbPath = "./db.sqlite"; private static SQLiteConnection Connection { get; } = new SQLiteConnection(DbPath); public static TableQuery<Session> Sessions => Connection.Table<Session>(); public static TableQuery<Folder> Folders => Connection.Table<Folder>(); public static TableQuery<Installation> Installations => Connection.Table<Installation>(); public static TableQuery<User> Users => Connection.Table<User>(); public static TableQuery<FolderAccess> FolderAccess => Connection.Table<FolderAccess>(); public static TableQuery<InstallationAccess> InstallationAccess => Connection.Table<InstallationAccess>(); public static TableQuery<OrderNumber2Installation> OrderNumber2Installation => Connection.Table<OrderNumber2Installation>(); public static TableQuery<DeletedInstallation> DeletedInstallations => Connection.Table<DeletedInstallation>(); public static TableQuery<DeletedUser> DeletedUsers => Connection.Table<DeletedUser>(); public static TableQuery<DeletedFolder> DeletedFolders => Connection.Table<DeletedFolder>(); public static void Init() { // used to force static constructor } static Db() { // on startup create/migrate tables Connection.RunInTransaction(() => { Connection.CreateTable<User>(); Connection.CreateTable<DeletedUser>(); Connection.CreateTable<Installation>(); Connection.CreateTable<DeletedInstallation>(); Connection.CreateTable<DeletedFolder>(); Connection.CreateTable<Folder>(); Connection.CreateTable<FolderAccess>(); Connection.CreateTable<InstallationAccess>(); Connection.CreateTable<Session>(); Connection.CreateTable<OrderNumber2Installation>(); }); Observable.Interval(TimeSpan.FromDays(0.5)) .StartWith(0) // Do it right away (on startup) .ObserveOn(TaskPoolScheduler.Default) .SubscribeOn(TaskPoolScheduler.Default) .SelectMany(Cleanup) .Subscribe(); } private static Boolean RunTransaction(Func<Boolean> func) { var savepoint = Connection.SaveTransactionPoint(); var success = false; try { success = func(); } finally { if (success) Connection.Release(savepoint); else Connection.RollbackTo(savepoint); } return success; } private static async Task<Boolean> Cleanup(Int64 _) { await UpdateS3Urls(); DeleteStaleSessions(); return true; } private static void DeleteStaleSessions() { var deadline = DateTime.Now - Session.MaxAge; Sessions.Delete(s => s.LastSeen < deadline); } private static Task UpdateS3Urls() { return Installations .Select(i => i.RenewS3BucketUrl()) .WhenAll(); } }