public async Task SimpleReadThroughCache() { var path = System.IO.Path.GetTempFileName(); var conn = new SQLite.SQLiteAsyncConnection(path); var db = new TestDatabase(conn); await db.Reset(); var sqliteThingCache = new SqliteClassCache <Parent, long>(db); await sqliteThingCache.Setup(); var cache1 = new ModelCache(aClassCache: new Dictionary <Type, IModelClassCache>() { { typeof(Parent), sqliteThingCache } }); // read from origin var cascade = new CascadeDataLayer(origin, new ICascadeCache[] { cache1 }, new CascadeConfig() { DefaultFreshnessSeconds = 1 }); var thing1 = await cascade.Get <Parent>(5); Assert.AreEqual(5, thing1 !.id); Assert.AreEqual(cascade.NowMs, thing1.updatedAtMs); origin.IncNowMs(); var thing2 = await cascade.Get <Parent>(5, freshnessSeconds : 2); Assert.AreEqual(thing1.updatedAtMs, thing2 !.updatedAtMs); var thing3 = await cascade.Get <Parent>(5, freshnessSeconds : 0); Assert.AreEqual(origin.NowMs, thing3 !.updatedAtMs); }
public async Task QueryWithSqliteCache() { var path = System.IO.Path.GetTempFileName(); var conn = new SQLite.SQLiteAsyncConnection(path); var db = new TestDatabase(conn); await db.Reset(); Child[] allGadgets = new[] { new Child() { id = "aaa", power = 1, weight = 100 }, new Child() { id = "bbb", power = 2, weight = 123 }, new Child() { id = "ccc", power = 3, weight = 456 }, new Child() { id = "ddd", power = 4, weight = 100 } }; foreach (var t in allGadgets) { await gadgetOrigin.Store(t.id, t); } var memoryGadgetCache = new ModelClassCache <Child, string>(); var memoryCache = new ModelCache(aClassCache: new Dictionary <Type, IModelClassCache>() { { typeof(Child), memoryGadgetCache } }); var sqliteGadgetCache = new SqliteClassCache <Child, string>(db); await sqliteGadgetCache.Setup(); var sqliteCache = new ModelCache(aClassCache: new Dictionary <Type, IModelClassCache>() { { typeof(Child), sqliteGadgetCache } }); var cascade = new CascadeDataLayer(origin, new ICascadeCache[] { memoryCache, sqliteCache }, new CascadeConfig()); var gadgets100 = await cascade.Query <Child>("gadgets100", new JsonObject { ["weight"] = 100 }); var gadgets100Ids = gadgets100.Select(t => t.id).ToImmutableArray(); Assert.That(gadgets100Ids, Is.EqualTo(new string[] { "aaa", "ddd" })); }
public async Task TestCollections() { var path = System.IO.Path.GetTempFileName(); var conn = new SQLite.SQLiteAsyncConnection(path); var db = new TestDatabase(conn); await db.Reset(); var sqliteThingCache = new SqliteClassCache <Parent, long>(db); await sqliteThingCache.Setup(); var sqliteGadgetCache = new SqliteClassCache <Child, string>(db); await sqliteGadgetCache.Setup(); var cache = new ModelCache(aClassCache: new Dictionary <Type, IModelClassCache>() { { typeof(Parent), sqliteThingCache }, { typeof(Child), sqliteGadgetCache } }); var cascade = new CascadeDataLayer(origin, new ICascadeCache[] { cache }, new CascadeConfig() { DefaultFreshnessSeconds = 1 }); var collection_key = "my_things"; var ids = ImmutableArray.Create <object>(1, 2, 3); var response = await cache.Fetch(RequestOp.QueryOp <Parent>(collection_key, new JsonObject(), 0)); Assert.AreEqual(false, response.Exists); Assert.AreEqual(null, response.Result); await cache.StoreCollection(typeof(Parent), collection_key, ids, 0); response = await cache.Fetch(RequestOp.QueryOp <Parent>(collection_key, null, 0)); Assert.IsTrue(CascadeTypeUtils.IsEqualEnumerable(ids, response.ResultIds)); response = await cache.Fetch(RequestOp.QueryOp <Parent>("not_my_key", null, 0)); Assert.IsFalse(response.Exists); response = await cache.Fetch(RequestOp.QueryOp <Child>(collection_key, null, 0)); Assert.IsFalse(response.Exists); }
public async Task Simple() { Parent[] allThings = new[] { new Parent() { id = 1, colour = "red" }, new Parent() { id = 2, colour = "green" }, new Parent() { id = 3, colour = "red" }, new Parent() { id = 4, colour = "yellow" }, }; foreach (var t in allThings) { await thingOrigin.Store(t.id, t); } var thingModelStore1 = new ModelClassCache <Parent, long>(); var cache1 = new ModelCache(aClassCache: new Dictionary <Type, IModelClassCache>() { { typeof(Parent), thingModelStore1 } }); var cascade = new CascadeDataLayer(origin, new ICascadeCache[] { cache1 }, new CascadeConfig()); var redThings = await cascade.Query <Parent>("red_things", new JsonObject { ["colour"] = "red" }); var redIds = redThings.Select(t => t.id).ToImmutableArray(); Assert.That(redIds, Is.EqualTo(new long[] { 1, 3 })); // check that collection & models are in cache Parent?thing; thing = await thingModelStore1.Fetch <Parent>(1); Assert.AreEqual(1, thing.id); Assert.AreEqual("red", thing.colour); thing = await thingModelStore1.Fetch <Parent>(3); Assert.AreEqual(3, thing.id); Assert.AreEqual("red", thing.colour); thing = await thingModelStore1.Fetch <Parent>(2); Assert.AreEqual(null, thing); var rcBefore = origin.RequestCount; origin.IncNowMs(); // request with freshness=2 var redThings2 = await cascade.Query <Parent>("red_things", new JsonObject { ["colour"] = "red" }, freshnessSeconds : 2); Assert.That(redThings2.Select(t => t.id).ToImmutableArray(), Is.EqualTo(new long[] { 1, 3 })); // same response Assert.AreEqual(rcBefore, origin.RequestCount); // didn't use origin rcBefore = origin.RequestCount; origin.IncNowMs(); redThings2 = (await cascade.Query <Parent>("red_things", new JsonObject { ["colour"] = "red" }, freshnessSeconds: 0)).ToImmutableArray(); Assert.That(redThings2.Select(t => t.id).ToImmutableArray(), Is.EqualTo(new long[] { 1, 3 })); // same response Assert.AreEqual(rcBefore + 1, origin.RequestCount); // did use origin }
public async Task ReadWithModelCachesMultitest() { var thingModelStore1 = new ModelClassCache <Parent, long>(); var cache1 = new ModelCache(aClassCache: new Dictionary <Type, IModelClassCache>() { { typeof(Parent), thingModelStore1 } }); var thingModelStore2 = new ModelClassCache <Parent, long>(); var cache2 = new ModelCache(aClassCache: new Dictionary <Type, IModelClassCache>() { { typeof(Parent), thingModelStore2 } }); // read from origin var cascade = new CascadeDataLayer(origin, new ICascadeCache[] { cache1, cache2 }, new CascadeConfig() { DefaultFreshnessSeconds = 1 }); var thing1 = await cascade.Get <Parent>(5); Assert.AreEqual(5, thing1 !.id); Assert.AreEqual(cascade.NowMs, thing1.updatedAtMs); // should also be in both caches var store1ThingResponse = await thingModelStore1.Fetch(RequestOp.GetOp <Parent>(5, cascade.NowMs)); Assert.AreEqual((store1ThingResponse.Result as Parent) !.id, 5); Assert.AreEqual(cascade.NowMs, (store1ThingResponse.Result as Parent) !.updatedAtMs); var store2ThingResponse = await thingModelStore2.Fetch(RequestOp.GetOp <Parent>(5, cascade.NowMs)); Assert.AreEqual((store2ThingResponse.Result as Parent) !.id, 5); Assert.AreEqual(cascade.NowMs, (store2ThingResponse.Result as Parent) !.updatedAtMs); origin.IncNowMs(); // freshness=5 allows for cached version var thing2 = (await cascade.Get <Parent>(5, freshnessSeconds: 5)) !; Assert.AreEqual(thing1.updatedAtMs, thing2.updatedAtMs); // freshness=0 doesn't allow for cached version var thing3 = (await cascade.Get <Parent>(5, freshnessSeconds: 0)) !; Assert.AreEqual(origin.NowMs, thing3.updatedAtMs); // caches should also be updated store1ThingResponse = await thingModelStore1.Fetch(RequestOp.GetOp <Parent>(5, cascade.NowMs)); Assert.AreEqual(origin.NowMs, (store1ThingResponse.Result as Parent) !.updatedAtMs); store2ThingResponse = await thingModelStore2.Fetch(RequestOp.GetOp <Parent>(5, cascade.NowMs)); Assert.AreEqual(origin.NowMs, (store2ThingResponse.Result as Parent) !.updatedAtMs); origin.IncNowMs(2000); // freshness=2 should allow for cached version var thing4 = (await cascade.Get <Parent>(5, freshnessSeconds: 2)) !; Assert.AreEqual(thing3.updatedAtMs, thing4.updatedAtMs); // freshness=1 should get fresh version var thing5 = (await cascade.Get <Parent>(5, freshnessSeconds: 1)) !; Assert.AreEqual(origin.NowMs, thing5.updatedAtMs); origin.IncNowMs(1000); // clear cache1, freshnessSeconds=1 should return value from cache2 and update cache1 await cache1.Clear(); var thing6 = (await cascade.Get <Parent>(thing4.id, freshnessSeconds: 1)) !; // should get cache2 version Assert.AreEqual(thing6.updatedAtMs, thing5.updatedAtMs); store1ThingResponse = await thingModelStore1.Fetch(RequestOp.GetOp <Parent>(5, cascade.NowMs)); Assert.AreEqual(thing6.updatedAtMs, (store1ThingResponse.Result as Parent) !.updatedAtMs); }
public async Task TestMetadata() { var path = System.IO.Path.GetTempFileName(); var conn = new SQLite.SQLiteAsyncConnection(path); var db = new TestDatabase(conn); await db.Reset(); var sqliteThingCache = new SqliteClassCache <Parent, long>(db); await sqliteThingCache.Setup(); var sqliteGadgetCache = new SqliteClassCache <Child, string>(db); await sqliteGadgetCache.Setup(); var cache1 = new ModelCache(aClassCache: new Dictionary <Type, IModelClassCache>() { { typeof(Parent), sqliteThingCache }, { typeof(Child), sqliteGadgetCache } }); // read from origin var cascade = new CascadeDataLayer(origin, new ICascadeCache[] { cache1 }, new CascadeConfig() { DefaultFreshnessSeconds = 1 }); var thing5 = new Parent() { id = 5, colour = "red" }; var thing5ArrivedAt = cascade.NowMs; await sqliteThingCache.Store(thing5.id, thing5, thing5ArrivedAt); origin.IncNowMs(); var gadget6 = new Child() { id = "abc", weight = 2.5, power = 9.2 }; var gadget6ArrivedAt = cascade.NowMs; await sqliteGadgetCache.Store(gadget6.id, gadget6, gadget6ArrivedAt); origin.IncNowMs(); var opResponse = await sqliteThingCache.Fetch(RequestOp.GetOp <Parent>(thing5.id, cascade.NowMs)); var loaded5 = (opResponse.Result as Parent) !; Assert.AreEqual(thing5ArrivedAt, opResponse.ArrivedAtMs); Assert.AreEqual(thing5.colour, loaded5.colour); opResponse = await sqliteGadgetCache.Fetch(RequestOp.GetOp <Child>(gadget6.id, cascade.NowMs)); var loaded6 = (opResponse.Result as Child) !; Assert.AreEqual(gadget6ArrivedAt, opResponse.ArrivedAtMs); Assert.AreEqual(gadget6.weight, loaded6.weight); await sqliteGadgetCache.Clear(); // thing unaffected opResponse = await sqliteThingCache.Fetch(RequestOp.GetOp <Parent>(thing5.id, cascade.NowMs)); Assert.NotNull(opResponse.Result); Assert.AreEqual(thing5ArrivedAt, opResponse.ArrivedAtMs); // gadget cleared including metadata opResponse = await sqliteGadgetCache.Fetch(RequestOp.GetOp <Child>(gadget6.id, cascade.NowMs)); Assert.IsNull(opResponse.Result); Assert.IsNull(opResponse.ArrivedAtMs); var meta6 = await db.Get <CascadeModelMeta>(CascadeModelMeta.GenerateId <Child>(6)); Assert.IsNull(meta6); }