// using System.Collections.Concurrent; // using System.Text.Json; // using BTCPayApp.Core.Attempt2; // using BTCPayApp.Core.Contracts; // using BTCPayApp.Core.Data; // using BTCPayApp.VSS; // using BTCPayServer.Lightning; // using Microsoft.EntityFrameworkCore; // using Microsoft.EntityFrameworkCore.Diagnostics; // using Microsoft.Extensions.Logging; // using VSSProto; // // namespace BTCPayApp.Core; // // // // public class VSSMapperInterceptor : SaveChangesInterceptor // { // // public VSSMapperInterceptor(BTCPayConnectionManager btcPayConnectionManager, ILogger logger) // { // } // // private ConcurrentDictionary PendingEvents = new ConcurrentDictionary(); // public override ValueTask SavedChangesAsync(SaveChangesCompletedEventData eventData, int result, // CancellationToken cancellationToken = new CancellationToken()) // { // return base.SavedChangesAsync(eventData, result, cancellationToken); // } // // private IVSSAPI api; // public override ValueTask> SavingChangesAsync(DbContextEventData eventData, InterceptionResult result, // CancellationToken cancellationToken = new CancellationToken()) // { // foreach (var entry in eventData.Context.ChangeTracker.Entries()) // { // // if (entry.Entity is LightningPayment lightningPayment) // { // if (entry.State == EntityState.Deleted) // { // // api.DeleteObjectAsync(new DeleteObjectRequest // { // KeyValue = new KeyValue() // { // // } // Key = $"LightningPayment/{lightningPayment.Id}" // }); // } // } // if (entry.Entity is Channel channel) // { // // } // if (entry.Entity is Setting setting) // { // // } // } // // return base.SavingChangesAsync(eventData, result, cancellationToken); // } // // public override Task SaveChangesCanceledAsync(DbContextEventData eventData, // CancellationToken cancellationToken = new CancellationToken()) // { // PendingEvents.Remove(eventData.EventId, out _); // return base.SaveChangesCanceledAsync(eventData, cancellationToken); // } // // public override Task SaveChangesFailedAsync(DbContextErrorEventData eventData, // CancellationToken cancellationToken = new CancellationToken()) // { // PendingEvents.Remove(eventData.EventId, out _); // return base.SaveChangesFailedAsync(eventData, cancellationToken); // } // // // } // using System.Text.Json; using AsyncKeyedLock; using BTCPayApp.Core.Contracts; using BTCPayApp.Core.Data; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; namespace BTCPayApp.Core; public class DatabaseConfigProvider( IDbContextFactory dbContextFactory, ILogger logger) : ConfigProvider { private readonly AsyncKeyedLocker _lock = new(); public override async Task Get(string key) where T : default { await using var dbContext = await dbContextFactory.CreateDbContextAsync(); var config = await dbContext.Settings.FindAsync(key); if (typeof(T) == typeof(byte[])) return (T?) (config?.Value as object); return config is null ? default : JsonSerializer.Deserialize(config.Value); } public override async Task Set(string key, T? value, bool backup) where T : default { using var releaser = await _lock.LockAsync(key); logger.LogDebug("Setting {Key} to {Value} {Backup}", key, value, backup ? "backup": "no backup"); await using var dbContext = await dbContextFactory.CreateDbContextAsync(); if (value is null) { try { dbContext.Settings.Remove(new Setting {Key = key}); await dbContext.SaveChangesAsync(); } catch (DbUpdateException) { } return; } var newValue = typeof(T) == typeof(byte[])? value as byte[]:JsonSerializer.SerializeToUtf8Bytes(value); var setting = new Setting {Key = key, Value = newValue, Backup = backup}; await dbContext.Upsert(setting, CancellationToken.None); } public override async Task> List(string prefix) { await using var dbContext = await dbContextFactory.CreateDbContextAsync(); return await dbContext.Settings.Where(s => s.Key.StartsWith(prefix)).Select(s => s.Key).ToListAsync(); } }