using GrossesMitainesAPI.Data; using GrossesMitainesAPI.Models; using Microsoft.EntityFrameworkCore; namespace GrossesMitainesAPI.Services { public class DatabaseCacheService { private readonly IServiceScopeFactory _contextFactory; // https://entityframeworkcore.com/knowledge-base/51939451/how-to-use-a-database-context-in-a-singleton-service- private readonly ILogger _logger; private Product[] _cache = new Product[1]; private bool _ok = false, _needUpd = true; private PeriodicTimer _timer = new PeriodicTimer(TimeSpan.FromSeconds(10)); public DatabaseCacheService(ILogger logger, IServiceScopeFactory scopeFactory) { _contextFactory = scopeFactory; _logger = logger; _ok = UpdateCache(); _needUpd = !_ok; UpdateJob(); } private async void UpdateJob() { while (await _timer.WaitForNextTickAsync()) if (_needUpd) { _ok = UpdateCache(); _needUpd = !_ok; } } private bool UpdateCache() { try { Product[] prods; using (var scope = _contextFactory.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService(); prods = db.Products.ToArray(); } lock (_cache) { _cache = prods; } } catch (Exception e) { _logger.LogError(e, "Erreur de mise à jour de cache."); return false; } return true; } public bool isOk() { return _ok; } public void askForRefresh() { _needUpd = true; } public Product[]? GetCacheCopy() { if (!_ok) return null; Product[] copy; try { lock (_cache) { copy = new Product[_cache.Length]; _cache.CopyTo(copy, 0); } } catch (Exception e) { _logger.LogError(e, "Erreur de copie de cache."); return null; } return copy; } public IQueryable queryCache() { if (!_ok) return null; try { return _cache.AsQueryable(); } catch (Exception e) { _logger.LogError(e, "Erreur de cache."); return null; } } } }