/// <summary> /// registers an item with a specific eviction condition. If the condition is mutable, every touch/get of the item will result /// in a condition mutation. /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="evictionCondition">may be null</param> public virtual void Commit(ICommitBag cb, IExpirable evictionCondition) { lock (this._stateLock) { //commit first. if it kacks we don't do anything this.Decorated.Commit(cb); //build and commit the conditions CommitBag conditionCommitBag = new CommitBag(); //foreach add, register a condition cb.ItemsToSave.WithEach(x => { //save the eviction condition in the eviction store, keyed by the storedobjectid of the item to save var conditionToSave = x.GetStoredObjectId().BuildAsId().HasContext(evictionCondition); conditionCommitBag.MarkItemSaved(conditionToSave); }); //foreach remove, remove a condition cb.ItemsToDelete.WithEach(x => { var delId = StoredObjectId.New(typeof(ContextualIHasIdDecoration), x); conditionCommitBag.MarkItemDeleted(delId); }); this.ExpirableStore.Commit(conditionCommitBag); } }
/// <summary> /// examines all eviction conditions and removes items that have an eviction condition of true. /// If an item's eviction condition is mutable, it will be mutated (eg. touched) on every get /// </summary> public void Evict() { List <ContextualIHasIdDecoration> itemsToEvict = new List <ContextualIHasIdDecoration>(); //search the eviction store for evicts var evictions = this.ExpirableStore.GetAll(); foreach (var each in evictions) { var eachItem = each as ContextualIHasIdDecoration; if (eachItem != null && eachItem.Context != null) { IExpirable exp = eachItem.Context as IExpirable; if (exp.IsExpired()) { itemsToEvict.Add(eachItem); } } } //build deletes and commit them var mainCommitBag = new CommitBag(); var expCommitBag = new CommitBag(); itemsToEvict.WithEach(x => { StoredObjectId soid = x.Id as StoredObjectId; mainCommitBag.MarkItemDeleted(soid); expCommitBag.MarkItemDeleted(x.GetStoredObjectId()); }); //remove the item specified by the expirable policy. this.Commit(mainCommitBag); //now delete from the expiry store this.ExpirableStore.Commit(expCommitBag); //raise events (outside of state lock) itemsToEvict.WithEach(x => { this.OnItemEvicted(x, x.Context as IExpirable); }); }
/// <summary> /// overrides, supplies the default condition /// </summary> /// <param name="bag"></param> public override void Commit(ICommitBag cb) { lock (this._stateLock) { //commit first. if it kacks we don't do anything base.Commit(cb); //build and commit the conditions CommitBag conditionCommitBag = new CommitBag(); //foreach add, register a condition if (this.ExpirableFactory != null) { cb.ItemsToSave.WithEach(x => { //generate the eviction condition var evictionConditionLogic = this.ExpirableFactory.Perform(x) as LogicOfTo <IHasId, IExpirable>; //save the eviction condition in the eviction store, keyed by the storedobjectid of the item to save var conditionToSave = x.GetStoredObjectId().BuildAsId().HasContext(evictionConditionLogic.Result); //var soid = conditionToSave.GetStoredObjectId(); //var soid2 = StoredObjectId.New(typeof(ContextualIHasIdDecoration), x.GetStoredObjectId()); //bool isEq = soid.Equals(soid2); conditionCommitBag.MarkItemSaved(conditionToSave); }); } //foreach remove, remove a condition cb.ItemsToDelete.WithEach(x => { var delId = StoredObjectId.New(typeof(ContextualIHasIdDecoration), x); conditionCommitBag.MarkItemDeleted(delId); }); this.ExpirableStore.Commit(conditionCommitBag); } }
public Test() : base(LogicOf <IStore> .New((x) => { x.Clear(); var thing = AsId <string> .New("asId1"); var filteredThing = AsId <string> .New("asId2_filtered"); //1. test save events - don't save items with id's ending in "_filtered" var store = x.DecorateWithEvents(DebugLogger.New()); store.CommitOperationIntercept.AddNextIntercept("intercept1", (o) => { CommitBag newBag = new CommitBag(); var oldBag = o; oldBag.ItemsToSave.WithEach(saveItem => { string id = saveItem.Id.ToString(); if (id.EndsWith("_filtered")) { //don't add to new commitbag } else { newBag.MarkItemSaved(saveItem); } }); return(newBag); } , null, null, null, null); //event flags bool saveFlag = false; bool saveFiltFlag = false; store.ItemSaved += (sender, e) => { saveFlag = true; }; store.ItemSavedFiltered += (sender, e) => { saveFiltFlag = true; }; store.SaveItem(thing); store.SaveItem(filteredThing); Assert.True(saveFiltFlag && saveFlag); store.Dispose(); //2. test delete events - don't delete items with ids ending in "_filtered" store = x.DecorateWithEvents(DebugLogger.New()); store.CommitOperationIntercept.AddNextIntercept("intercept1", (o) => { CommitBag newBag = new CommitBag(); var oldBag = o; oldBag.ItemsToDelete.WithEach(delItem => { string id = delItem.ObjectId.ToString(); if (id.EndsWith("_filtered")) { //don't add to new commitbag } else { newBag.MarkItemDeleted(delItem); } }); return(newBag); }, null, null, null, null); bool delFlag = false; bool delFiltFlag = false; store.ItemDeleted += (sender, e) => { delFlag = true; }; store.ItemDeletedFiltered += (sender, e) => { delFiltFlag = true; }; store.SaveItem(thing); store.SaveItem(filteredThing); store.DeleteItem(thing.GetStoredObjectId()); store.DeleteItem(filteredThing.GetStoredObjectId()); Assert.True(delFiltFlag && delFlag); store.Dispose(); //3. test retrieve events - don't get items with ids ending in "_filtered" store = x.DecorateWithEvents(DebugLogger.New()); //do get all first store.GetAllOperationIntercept.AddNextIntercept("intercept1", null, null, null, (o) => { List <IHasId> newList = new List <IHasId>(); var oldList = o; oldList.WithEach(item => { if (!item.Id.ToString().EndsWith("_filtered")) newList.Add(item); }); return(newList); }, null); bool retFlag = false; bool retFiltFlag = false; store.ItemRetrieved += (sender, e) => { retFlag = true; }; store.ItemRetrievedFiltered += (sender, e) => { retFiltFlag = true; }; store.SaveItem(thing); store.SaveItem(filteredThing); var items = store.GetAll(); Assert.True(retFiltFlag && retFlag); //now test Search retFiltFlag = false; retFlag = false; store.SearchOperationIntercept.AddNextIntercept("intercept2", null, null, null, (o) => { List <IHasId> newList = new List <IHasId>(); var oldList = o; oldList.WithEach(item => { if (!item.Id.ToString().EndsWith("_filtered")) newList.Add(item); }); return(newList); }, null); var filter = LogicOfTo <AsId <string>, bool> .New((o) => { return(true); }); var searchList = store.SearchOf <AsId <string> >(filter); Assert.True(retFiltFlag && retFlag); //now test get store.GetOperationIntercept.AddNextIntercept("intercept3", null, null, null, (o) => { IHasId newObj = null; IHasId oldObj = o; if (!oldObj.Id.ToString().EndsWith("_filtered")) newObj = oldObj; return(newObj); }, null); retFiltFlag = false; retFlag = false; store.Get(thing.GetStoredObjectId()); store.Get(filteredThing.GetStoredObjectId()); Assert.True(retFiltFlag && retFlag); store.Dispose(); })) { }