using System; using MongoDB.Driver; using StardewModdingAPI.Toolkit.Framework.UpdateData; using StardewModdingAPI.Web.Framework.ModRepositories; namespace StardewModdingAPI.Web.Framework.Caching.Mods { /// Manages cached mod data in MongoDB. internal class ModCacheMongoRepository : BaseCacheRepository, IModCacheRepository { /********* ** Fields *********/ /// The collection for cached mod data. private readonly IMongoCollection Mods; /********* ** Public methods *********/ /// Construct an instance. /// The authenticated MongoDB database. public ModCacheMongoRepository(IMongoDatabase database) { // get collections this.Mods = database.GetCollection("mods"); // add indexes if needed this.Mods.Indexes.CreateOne(new CreateIndexModel(Builders.IndexKeys.Ascending(p => p.ID).Ascending(p => p.Site))); } /********* ** Public methods *********/ /// Get the cached mod data. /// The mod site to search. /// The mod's unique ID within the . /// The fetched mod. /// Whether to update the mod's 'last requested' date. public bool TryGetMod(ModRepositoryKey site, string id, out CachedMod mod, bool markRequested = true) { // get mod id = this.NormalizeId(id); mod = this.Mods.Find(entry => entry.ID == id && entry.Site == site).FirstOrDefault(); if (mod == null) return false; // bump 'last requested' if (markRequested) { mod.LastRequested = DateTimeOffset.UtcNow; mod = this.SaveMod(mod); } return true; } /// Save data fetched for a mod. /// The mod site on which the mod is found. /// The mod's unique ID within the . /// The mod data. /// The stored mod record. public void SaveMod(ModRepositoryKey site, string id, ModInfoModel mod, out CachedMod cachedMod) { id = this.NormalizeId(id); cachedMod = this.SaveMod(new CachedMod(site, id, mod)); } /// Delete data for mods which haven't been requested within a given time limit. /// The minimum age for which to remove mods. public void RemoveStaleMods(TimeSpan age) { DateTimeOffset minDate = DateTimeOffset.UtcNow.Subtract(age); this.Mods.DeleteMany(p => p.LastRequested < minDate); } /// Save data fetched for a mod. /// The mod data. public CachedMod SaveMod(CachedMod mod) { string id = this.NormalizeId(mod.ID); this.Mods.ReplaceOne( entry => entry.ID == id && entry.Site == mod.Site, mod, new ReplaceOptions { IsUpsert = true } ); return mod; } /********* ** Private methods *********/ /// Normalize a mod ID for case-insensitive search. /// The mod ID. public string NormalizeId(string id) { return id.Trim().ToLower(); } } }