|
@@ -0,0 +1,196 @@
|
|
|
+using InABox.Core;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Diagnostics.CodeAnalysis;
|
|
|
+using System.Linq;
|
|
|
+using System.Text;
|
|
|
+using System.Threading.Tasks;
|
|
|
+
|
|
|
+namespace InABox.Avalonia;
|
|
|
+
|
|
|
+public static class CacheManager
|
|
|
+{
|
|
|
+ private static Dictionary<string, DateTime> _expiries = new();
|
|
|
+
|
|
|
+ private static Timer? _timer;
|
|
|
+
|
|
|
+ private static void StartTimer()
|
|
|
+ {
|
|
|
+ if (_timer is not null) return;
|
|
|
+
|
|
|
+ // _timer = new Timer(ProcessCache, null, TimeSpan.Zero, TimeSpan.FromMinutes(5));
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void ProcessCache(object? state)
|
|
|
+ {
|
|
|
+ var now = DateTime.Now;
|
|
|
+ var toDelete = _expiries.Where(x => x.Value < now).Select(x => x.Key).ToArray();
|
|
|
+ foreach (var item in toDelete)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ File.Delete(CacheFileName(item));
|
|
|
+ }
|
|
|
+ catch(Exception e)
|
|
|
+ {
|
|
|
+ MobileLogging.Log(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ lock (_expiries)
|
|
|
+ {
|
|
|
+ foreach (var item in toDelete)
|
|
|
+ {
|
|
|
+ _expiries.Remove(item);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private static void AddExpiry(string key, DateTime expiry)
|
|
|
+ {
|
|
|
+ // lock (_expiries)
|
|
|
+ // {
|
|
|
+ // _expiries[key] = expiry;
|
|
|
+ // }
|
|
|
+ // SaveExpiries();
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Guid CacheID { get; set; }
|
|
|
+
|
|
|
+ private static bool IsCached(string key) => File.Exists(CacheFileName(key));
|
|
|
+
|
|
|
+ private static string CacheFileName(string key) =>
|
|
|
+ Path.Combine(CacheFolder(), key);
|
|
|
+
|
|
|
+ private static string CacheFolder()
|
|
|
+ {
|
|
|
+ var result = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
|
|
+ if (OperatingSystem.IsWindows())
|
|
|
+ {
|
|
|
+ var assembly = Path.GetFileNameWithoutExtension(System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName);
|
|
|
+ result = Path.Combine(result, assembly);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (CacheID != Guid.Empty)
|
|
|
+ result = Path.Combine(result, CacheID.ToString());
|
|
|
+ if (!Directory.Exists(result))
|
|
|
+ Directory.CreateDirectory(result);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private const string EXPIRY_FILE = "cache_expiry.json";
|
|
|
+
|
|
|
+ private static void LoadExpiries()
|
|
|
+ {
|
|
|
+ var filename = CacheFileName(EXPIRY_FILE);
|
|
|
+ if (File.Exists(filename))
|
|
|
+ {
|
|
|
+ var json = File.ReadAllText(filename);
|
|
|
+ lock (_expiries)
|
|
|
+ {
|
|
|
+ _expiries = Serialization.Deserialize<Dictionary<string, DateTime>>(json) ?? [];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ lock (_expiries)
|
|
|
+ {
|
|
|
+ _expiries = [];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private static void SaveExpiries()
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ lock (_expiries)
|
|
|
+ {
|
|
|
+ var file = CacheFileName(EXPIRY_FILE);
|
|
|
+ var json = Serialization.Serialize(_expiries);
|
|
|
+ File.WriteAllText(file, json);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception e)
|
|
|
+ {
|
|
|
+ MobileLogging.Log(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #region Public Interface
|
|
|
+
|
|
|
+ public static void Initialise(Guid cacheID)
|
|
|
+ {
|
|
|
+ CacheID = cacheID;
|
|
|
+ // LoadExpiries();
|
|
|
+
|
|
|
+ StartTimer();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static bool TryLoadBinary<T>(string key, [NotNullWhen(true)] out T? value, out DateTime lastUpdated)
|
|
|
+ where T : class, ISerializeBinary, new()
|
|
|
+ {
|
|
|
+ var filename = CacheFileName(key);
|
|
|
+ if (File.Exists(filename))
|
|
|
+ {
|
|
|
+ lastUpdated = File.GetLastWriteTime(filename);
|
|
|
+ using var stream = new FileStream(filename, FileMode.Open);
|
|
|
+ value = Serialization.ReadBinary<T>(stream, BinarySerializationSettings.Latest);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ lastUpdated = default;
|
|
|
+ value = null;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public static void SaveBinary<T>(string key, T value, DateTime expiry)
|
|
|
+ where T : class, ISerializeBinary, new()
|
|
|
+ {
|
|
|
+ var data = value.WriteBinary(BinarySerializationSettings.Latest);
|
|
|
+ try
|
|
|
+ {
|
|
|
+ var file = CacheFileName(key);
|
|
|
+ File.WriteAllBytes(file, data);
|
|
|
+ AddExpiry(key, expiry);
|
|
|
+ }
|
|
|
+ catch (Exception e)
|
|
|
+ {
|
|
|
+ MobileLogging.Log(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static bool TryLoadJSON<T>(string key, [NotNullWhen(true)] out T? value, out DateTime lastUpdated)
|
|
|
+ where T : class, new()
|
|
|
+ {
|
|
|
+ var filename = CacheFileName(key);
|
|
|
+ if (File.Exists(filename))
|
|
|
+ {
|
|
|
+ lastUpdated = File.GetLastWriteTime(filename);
|
|
|
+ var json = File.ReadAllText(filename);
|
|
|
+ value = Serialization.Deserialize<T>(json);
|
|
|
+ return value is not null;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ lastUpdated = default;
|
|
|
+ value = null;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public static void SaveJSON<T>(string key, T value, DateTime expiry)
|
|
|
+ where T : class, new()
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ var file = CacheFileName(key);
|
|
|
+ var json = Serialization.Serialize(value);
|
|
|
+ File.WriteAllText(file, json);
|
|
|
+ AddExpiry(key, expiry);
|
|
|
+ }
|
|
|
+ catch (Exception e)
|
|
|
+ {
|
|
|
+ MobileLogging.Log(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+}
|