|
@@ -86,7 +86,8 @@ namespace InABox.Core
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// A cache of documents that is saved in the AppData folder under a specific tag.
|
|
|
+ /// A cache of documents that is saved in the AppData folder under a specific tag. Contrary to the name, this isn't just a <see cref="Document"/> cache, but
|
|
|
+ /// in fact a way to cache any kind of object that implements <see cref="ICachedDocument"/>.
|
|
|
/// </summary>
|
|
|
/// <remarks>
|
|
|
/// The files are stored with the name "<ID>.document", and they contain a binary serialised <see cref="CachedDocument"/>.
|
|
@@ -431,4 +432,135 @@ namespace InABox.Core
|
|
|
|
|
|
#endregion
|
|
|
}
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// An implementation of <see cref="ICachedDocument"/> for use with entities of type <see cref="Document"/>. The <see cref="Document.TimeStamp"/>
|
|
|
+ /// is saved along with the document, allowing us to refresh updated documents.
|
|
|
+ /// </summary>
|
|
|
+ public class DocumentCachedDocument : ICachedDocument
|
|
|
+ {
|
|
|
+ public DateTime TimeStamp { get; set; }
|
|
|
+
|
|
|
+ public Document? Document { get; set; }
|
|
|
+
|
|
|
+ public Guid ID => Document?.ID ?? Guid.Empty;
|
|
|
+
|
|
|
+ public DocumentCachedDocument() { }
|
|
|
+
|
|
|
+ public DocumentCachedDocument(Document document)
|
|
|
+ {
|
|
|
+ Document = document;
|
|
|
+ TimeStamp = document.TimeStamp;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void DeserializeBinary(CoreBinaryReader reader, bool full)
|
|
|
+ {
|
|
|
+ TimeStamp = reader.ReadDateTime();
|
|
|
+ if (full)
|
|
|
+ {
|
|
|
+ Document = reader.ReadObject<Document>();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void SerializeBinary(CoreBinaryWriter writer)
|
|
|
+ {
|
|
|
+ writer.Write(TimeStamp);
|
|
|
+ if (Document is null)
|
|
|
+ {
|
|
|
+ throw new Exception("Cannot serialize incomplete CachedDocument");
|
|
|
+ }
|
|
|
+ writer.WriteObject(Document);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Implements a <see cref="DocumentCache{T}"/> for use with <see cref="Document"/>.
|
|
|
+ /// </summary>
|
|
|
+ public abstract class DocumentCache : DocumentCache<DocumentCachedDocument>
|
|
|
+ {
|
|
|
+ public DocumentCache(string tag): base(tag) { }
|
|
|
+
|
|
|
+ protected override DocumentCachedDocument? LoadDocument(Guid id)
|
|
|
+ {
|
|
|
+ var document = Client.Query(new Filter<Document>(x => x.ID).IsEqualTo(id))
|
|
|
+ .ToObjects<Document>().FirstOrDefault();
|
|
|
+ if(document != null)
|
|
|
+ {
|
|
|
+ return new DocumentCachedDocument(document);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Fetch a bunch of documents from the cache or the database, optionally checking against the timestamp listed in the database.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="ids"></param>
|
|
|
+ /// <param name="checkTimestamp">
|
|
|
+ /// If <see langword="true"/>, then loads <see cref="Document.TimeStamp"/> from the database for all cached documents,
|
|
|
+ /// and if they are older, updates the cache.
|
|
|
+ /// </param>
|
|
|
+ public IEnumerable<Document> LoadDocuments(IEnumerable<Guid> ids, bool checkTimestamp = false)
|
|
|
+ {
|
|
|
+ var cached = new List<Guid>();
|
|
|
+ var toLoad = new List<Guid>();
|
|
|
+ foreach (var docID in ids)
|
|
|
+ {
|
|
|
+ if (Has(docID))
|
|
|
+ {
|
|
|
+ cached.Add(docID);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ toLoad.Add(docID);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var loadedCached = new List<Document>();
|
|
|
+ if (cached.Count > 0)
|
|
|
+ {
|
|
|
+ var docs = Client.Query(
|
|
|
+ new Filter<Document>(x => x.ID).InList(cached.ToArray()),
|
|
|
+ Columns.None<Document>().Add(x => x.TimeStamp, x => x.ID));
|
|
|
+ foreach (var doc in docs.ToObjects<Document>())
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ var timestamp = GetHeader(doc.ID).Document.TimeStamp;
|
|
|
+ if (doc.TimeStamp > timestamp)
|
|
|
+ {
|
|
|
+ toLoad.Add(doc.ID);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ loadedCached.Add(GetFull(doc.ID).Document.Document!);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception e)
|
|
|
+ {
|
|
|
+ CoreUtils.LogException("", e, "Error loading cached file");
|
|
|
+ toLoad.Add(doc.ID);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (toLoad.Count > 0)
|
|
|
+ {
|
|
|
+ var loaded = Client.Query(new Filter<Document>(x => x.ID).InList(toLoad.ToArray()))
|
|
|
+ .ToObjects<Document>().ToList();
|
|
|
+ foreach (var loadedDoc in loaded)
|
|
|
+ {
|
|
|
+ Add(new DocumentCachedDocument(loadedDoc));
|
|
|
+ }
|
|
|
+ return loaded.Concat(loadedCached);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return loadedCached;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+
|