//Update counters public virtual void UpdateCounters( EntityContext entityContext, IList generatedEntities, bool isFlushRequired) { OrderIterationType next = _queue.Peek(); if (entityContext.Type != next.EntityType) { throw new ArgumentException($"Type {entityContext.Type.Name} provided in {nameof(UpdateCounters)} does not match the latest action Type {next.EntityType}"); } next.GenerateCount -= generatedEntities.Count; if (entityContext.Description.InsertToPersistentStorageBeforeUse) { //for entities that generate Id on database, will generate as much as possible before flushing. //the number to generate will be determined by IFlushTrigger. EntityProgress progress = entityContext.EntityProgress; bool isCompleted = progress.CurrentCount >= progress.TargetCount; if (isFlushRequired || isCompleted) { _queue.Pop(); } return; } if (next.GenerateCount <= 0) { _queue.Pop(); } }
public virtual void SetNextReleaseCount(EntityContext entityContext) { EntityProgress progress = entityContext.EntityProgress; long capacity = GetCapacity(entityContext); progress.NextReleaseCount = progress.ReleasedCount + capacity; }
//Helper private EntityContext ToEntityContext(EntityProgress entityProgress) { return(new EntityContext { EntityProgress = entityProgress }); }
public virtual bool IsFlushRequired(EntityContext entityContext) { EntityProgress progress = entityContext.EntityProgress; long capacity = GetCapacity(entityContext); long tempStorageCount = progress.CurrentCount - progress.FlushedCount; return(tempStorageCount >= capacity); }
//methods /// <summary> /// Update NextNodeFinder internal counters updates entity was generated /// </summary> /// <param name="updateEntityContext"></param> public virtual void UpdateCounters(EntityContext updateEntityContext, IList generatedEntities) { EntityProgress progress = updateEntityContext.EntityProgress; bool isCompleted = progress.TargetCount <= progress.CurrentCount; if (isCompleted) { NotCompletedEntities.Remove(updateEntityContext); CompletedEntityTypes.Add(updateEntityContext.Type); } }
public void AddEntityProgress(EntityInfo entityInfo, EntityProgress entityProgress) { entityProgress.DateTime = DateTime.UtcNow; entityProgress.IpAddress = HttpContext.Current.Request.UserHostAddress; if (entityProgress.UserId == null && _userContext.IsAuthenticated) { entityProgress.UserId = _userContext.User.Id; } entityInfo.EntityProgress.Add(entityProgress); }
//Flush required checks public virtual bool CheckIsFlushRequired(EntityContext entityContext) { EntityProgress progress = entityContext.EntityProgress; bool isFlushInProgress = progress.IsFlushInProgress(); if (isFlushInProgress) { return(false); } //NextReleaseCount will be used by child entities to check if they still can generate from this parent IFlushStrategy flushTrigger = _generatorSetup.GetFlushTrigger(entityContext.Description); flushTrigger.SetNextReleaseCount(entityContext); //when all entities are generated also should flush bool isFlushRequired = flushTrigger.IsFlushRequired(entityContext); bool isCompleted = progress.CurrentCount >= progress.TargetCount; if (isCompleted) { isFlushRequired = true; } if (!isFlushRequired) { //if flush is not required NextFlushCount should not be updated //isFlushInProgress is using NextFlushCount return(isFlushRequired); } //update next flush count flushTrigger.SetNextFlushCount(entityContext); //add to flush candidates if will be used by dependent children bool hasDependentChild = FindChildThatCanGenerate(entityContext, true) != null; if (hasDependentChild) { _flushCandidates.Add(entityContext); } return(isFlushRequired); }
protected virtual Task[] FlushToPersistentTask(EntityContext entityContext, List <IPersistentStorage> storages) { EntityProgress progress = entityContext.EntityProgress; if (_entitiesAwaitingFlush.ContainsKey(entityContext.Type) == false) { return(new Task[0]); } //lock operations on list for same Type IList nextItems = null; entityContext.RunWithWriteLock(() => { IList entitiesAwaitingFlush = _entitiesAwaitingFlush[entityContext.Type]; long numberToFlush = progress.NextFlushCount - progress.FlushedCount; //take number of items to flush nextItems = _listOperations .Take(entityContext.Type, entitiesAwaitingFlush, (int)numberToFlush); //remove items from temporary storage _entitiesAwaitingFlush[entityContext.Type] = _listOperations .Skip(entityContext.Type, entitiesAwaitingFlush, (int)numberToFlush); //update progess progress.AddFlushedCount(nextItems.Count); progress.AddReleasedCount(nextItems.Count); }); if (nextItems.Count == 0) { return(new Task[0]); } Task[] insertTasks = storages .Select(storage => _reflectionInvoker.InvokeInsert(storage, entityContext.Description, nextItems)) .ToArray(); return(insertTasks); }
//InsertToPersistentStorageBeforeUse /// <summary> /// Insert entities to persistent storage but keep in temporary storage /// </summary> public virtual void GenerateStorageIds(EntityContext entityContext, List <IPersistentStorage> storages) { //Must be a sync operation, so inserted Ids are available immediatly EntityProgress progress = entityContext.EntityProgress; if (_entitiesAwaitingFlush.ContainsKey(entityContext.Type) == false) { return; } //lock operations on list for same Type IList nextItems = null; entityContext.RunWithReadLock(() => { IList entitiesAwaitingFlush = _entitiesAwaitingFlush[entityContext.Type]; long numberToSkip = progress.FlushedCount - progress.ReleasedCount; long numberToFlush = progress.NextFlushCount - progress.FlushedCount; //skip entities that already were flushed nextItems = _listOperations.Skip(entityContext.Type, entitiesAwaitingFlush, (int)numberToSkip); //take number of items to flush nextItems = _listOperations.Take(entityContext.Type, nextItems, (int)numberToFlush); //update progress progress.AddFlushedCount(nextItems.Count); }); if (nextItems.Count == 0) { return; } storages.ForEach(storage => { _reflectionInvoker.InvokeInsert(storage, entityContext.Description, nextItems).Wait(); }); }
public virtual void ReleaseFromTempStorage(EntityContext entityContext) { EntityProgress progress = entityContext.EntityProgress; if (_entitiesAwaitingFlush.ContainsKey(entityContext.Type) == false) { return; } //lock operations on list for same Type entityContext.RunWithWriteLock(() => { IList entitiesAwaitingFlush = _entitiesAwaitingFlush[entityContext.Type]; long numberToRemove = progress.NextReleaseCount - progress.ReleasedCount; //remove items from temporary storage _entitiesAwaitingFlush[entityContext.Type] = _listOperations .Skip(entityContext.Type, entitiesAwaitingFlush, (int)numberToRemove); //update progress progress.AddReleasedCount(numberToRemove); }); }