using System.Reflection; using AIStudio.Tools.Databases; using AIStudio.Tools.Databases.ProvenanceStore; using Microsoft.Data.Sqlite; using Microsoft.Extensions.Logging.Abstractions; namespace AIStudio.Tests.Tools.Databases; /// /// A provenance store in a directory of its own, migrated the way the app migrates its own, and /// deleted again afterward. /// /// The directory the database lives in. /// The path of the database file. internal sealed class TemporaryProvenanceStore(string directory, string databasePath) : IAsyncDisposable { public SqliteProvenanceStoreClientImplementation Client { get; } = new("SQLite", databasePath, directory, string.Empty); /// /// The file of the database, to check what it holds on the disk. /// public string DatabasePath => databasePath; public static async Task CreateAsync() { SQLitePCL.Batteries_V2.Init(); var directory = Path.Combine(Path.GetTempPath(), $"ai-studio-provenance-store-{Guid.NewGuid():N}"); Directory.CreateDirectory(directory); var store = new TemporaryProvenanceStore(directory, Path.Combine(directory, "provenance.sqlite3")); await using var context = store.CreateContext(); await ProvenanceStoreSchemaMigrator.MigrateAsync(context, CancellationToken.None); return store; } /// /// Makes a provider of the database clients which hands out this store, and nothing else. /// public DatabaseClientProvider CreateClientProvider() { var databases = new DatabaseClientProvider(null!, NullLoggerFactory.Instance); var clients = (Dictionary)typeof(DatabaseClientProvider).GetField("clients", BindingFlags.Instance | BindingFlags.NonPublic)!.GetValue(databases)!; clients.Add(DatabaseRole.PROVENANCE_STORE, this.Client); return databases; } /// /// Opens the database directly, to check what the client does not show. /// public ProvenanceStoreDbContext CreateContext() => new(ProvenanceStoreDbContext.CreateOptions(databasePath)); public ValueTask DisposeAsync() { // The pooled connections hold the file open, which would keep it from being deleted on Windows: SqliteConnection.ClearAllPools(); Directory.Delete(directory, true); return ValueTask.CompletedTask; } }