Example #1
0
        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);
        }
Example #2
0
        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" }));
        }
Example #3
0
        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);
        }
Example #4
0
        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
        }
Example #5
0
        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);
        }
Example #6
0
        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);
        }