From 3982537d466a952f8206e4ecf6ff8ead3d0ef5b1 Mon Sep 17 00:00:00 2001 From: Robert McRackan Date: Sun, 31 Jul 2022 21:58:53 -0400 Subject: [PATCH] Tags no longer saved outside of database --- Source/DataLayer/DataLayer.csproj | 7 +- Source/DataLayer/EfClasses/Series.cs | 1 - Source/DataLayer/EfClasses/UserDefinedItem.cs | 4 -- Source/DataLayer/LibationContext.cs | 11 +-- Source/DataLayer/TagPersistenceInterceptor.cs | 30 -------- Source/LibationFileManager/TagsPersistence.cs | 70 ------------------- .../LibationSearchEngine.csproj | 1 + 7 files changed, 4 insertions(+), 120 deletions(-) delete mode 100644 Source/DataLayer/TagPersistenceInterceptor.cs delete mode 100644 Source/LibationFileManager/TagsPersistence.cs diff --git a/Source/DataLayer/DataLayer.csproj b/Source/DataLayer/DataLayer.csproj index 3bfe8ee2..3f66307a 100644 --- a/Source/DataLayer/DataLayer.csproj +++ b/Source/DataLayer/DataLayer.csproj @@ -10,7 +10,8 @@ - + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -29,10 +30,6 @@ embedded - - - - diff --git a/Source/DataLayer/EfClasses/Series.cs b/Source/DataLayer/EfClasses/Series.cs index f419e549..1c4d92a9 100644 --- a/Source/DataLayer/EfClasses/Series.cs +++ b/Source/DataLayer/EfClasses/Series.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using Dinah.Core; -using Microsoft.EntityFrameworkCore; namespace DataLayer { diff --git a/Source/DataLayer/EfClasses/UserDefinedItem.cs b/Source/DataLayer/EfClasses/UserDefinedItem.cs index 28267a31..fd003f1e 100644 --- a/Source/DataLayer/EfClasses/UserDefinedItem.cs +++ b/Source/DataLayer/EfClasses/UserDefinedItem.cs @@ -30,10 +30,6 @@ namespace DataLayer { ArgumentValidator.EnsureNotNull(book, nameof(book)); Book = book; - - // import previously saved tags - ArgumentValidator.EnsureNotNullOrWhiteSpace(book.AudibleProductId, nameof(book.AudibleProductId)); - Tags = LibationFileManager.TagsPersistence.GetTags(book.AudibleProductId); } #region Tags diff --git a/Source/DataLayer/LibationContext.cs b/Source/DataLayer/LibationContext.cs index 04c7e411..4787e652 100644 --- a/Source/DataLayer/LibationContext.cs +++ b/Source/DataLayer/LibationContext.cs @@ -1,10 +1,9 @@ using DataLayer.Configurations; -using Dinah.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; namespace DataLayer { - public class LibationContext : InterceptableDbContext + public class LibationContext : DbContext { // IMPORTANT: USING DbSet<> // ======================== @@ -35,14 +34,6 @@ namespace DataLayer // see DesignTimeDbContextFactoryBase for info about ctors and connection strings/OnConfiguring() internal LibationContext(DbContextOptions options) : base(options) { } - // called on each instantiation - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - AddInterceptor(new TagPersistenceInterceptor()); - - base.OnConfiguring(optionsBuilder); - } - // typically only called once per execution; NOT once per instantiation protected override void OnModelCreating(ModelBuilder modelBuilder) { diff --git a/Source/DataLayer/TagPersistenceInterceptor.cs b/Source/DataLayer/TagPersistenceInterceptor.cs deleted file mode 100644 index 8be15d7f..00000000 --- a/Source/DataLayer/TagPersistenceInterceptor.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Dinah.Core.Collections.Generic; -using Dinah.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore; - -namespace DataLayer -{ - internal class TagPersistenceInterceptor : IDbInterceptor - { - public void Executed(DbContext context) { } - - public void Executing(DbContext context) - { - var tagsCollection - = context - .ChangeTracker - .Entries() - .Where(e => e.State.In(EntityState.Modified, EntityState.Added)) - .Select(e => e.Entity as UserDefinedItem) - .Where(udi => udi is not null) - // do NOT filter out entires with blank tags. blank is the valid way to show the absence of tags - .Select(t => (t.Book.AudibleProductId, t.Tags)) - .ToList(); - - LibationFileManager.TagsPersistence.Save(tagsCollection); - } - } -} diff --git a/Source/LibationFileManager/TagsPersistence.cs b/Source/LibationFileManager/TagsPersistence.cs deleted file mode 100644 index add10407..00000000 --- a/Source/LibationFileManager/TagsPersistence.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Newtonsoft.Json; -using Polly; -using Polly.Retry; - -namespace LibationFileManager -{ - /// - /// Tags must also be stored in db for search performance. Stored in json file to survive a db reset. - /// json is only read when a product is first loaded into the db - /// json is only written to when tags are edited - /// json access is infrequent and one-off - /// - public static class TagsPersistence - { - private static string TagsFile => Path.Combine(Configuration.Instance.LibationFiles, "BookTags.json"); - - private static object locker { get; } = new object(); - - // if failed, retry only 1 time after a wait of 100 ms - // 1st save attempt sometimes fails with - // The requested operation cannot be performed on a file with a user-mapped section open. - private static RetryPolicy policy { get; } - = Policy.Handle() - .WaitAndRetry(new[] { TimeSpan.FromMilliseconds(100) }); - - public static void Save(IEnumerable<(string productId, string tags)> tagsCollection) - { - ensureCache(); - - if (!tagsCollection.Any()) - return; - - // on initial reload, there's a huge benefit to adding to cache individually then updating the file only once - foreach ((string productId, string tags) in tagsCollection) - cache[productId] = tags; - - lock (locker) - policy.Execute(() => File.WriteAllText(TagsFile, JsonConvert.SerializeObject(cache, Formatting.Indented))); - } - - private static Dictionary cache; - - public static string GetTags(string productId) - { - ensureCache(); - - cache.TryGetValue(productId, out string value); - return value; - } - - private static void ensureCache() - { - if (cache is not null) - return; - - lock (locker) - { - if (File.Exists(TagsFile)) - cache = JsonConvert.DeserializeObject>(File.ReadAllText(TagsFile)); - - // if file doesn't exist. or if file is corrupt and deserialize returns null - cache ??= new Dictionary(); - } - } - } -} diff --git a/Source/LibationSearchEngine/LibationSearchEngine.csproj b/Source/LibationSearchEngine/LibationSearchEngine.csproj index 076f940a..cf14f994 100644 --- a/Source/LibationSearchEngine/LibationSearchEngine.csproj +++ b/Source/LibationSearchEngine/LibationSearchEngine.csproj @@ -14,6 +14,7 @@ +