/// <summary> /// Catchup poller is different, instead of sending everything to real TPL, it will simply /// fix readmodels until we reach minimum dispatch, then finally it will simply dispatch /// to the standard tpl. /// </summary> /// <param name="atomicDispatchChunk"></param> /// <returns></returns> private async Task <Boolean> DispatchCatchupToTpl(AtomicDispatchChunk atomicDispatchChunk) { //Process only if we have a payload if (atomicDispatchChunk?.Chunk?.Payload != null) { //if catchup poller reach starting point of the engine, it can start sending data to TPL if (atomicDispatchChunk.Chunk.Position > _defaultPollerStartingPoint) { //Catchup poller reached the original checkpoint, we can start doing standard projection. return(await DispatchToTpl(atomicDispatchChunk).ConfigureAwait(false)); } //to be more efficient, until we reach the startup commit of default, we can project //differently, because we can simply project all the id in one shot. //we need to completely reconstruct all readnodel that should be catched. if (atomicDispatchChunk.Chunk.Payload is Changeset cs) { var identity = cs.GetIdentity(); if (identity != null) //remember empty commits. { if (_catchupConsumerBlocks.TryGetValue(identity.GetType(), out var consumers)) { //if I already projected this id, nothing to do. if (!_catchupPollerIdList.Contains(identity.AsString())) { foreach (var consumer in consumers) { await consumer.Consumer.FullProject(identity).ConfigureAwait(false); _atomicProjectionCheckpointManager.MarkPosition( consumer.Consumer.AtomicReadmodelInfoAttribute.Name, atomicDispatchChunk.Chunk.Position); } _catchupPollerIdList.Add(identity.AsString()); } } } } //Clear everything when we reach the ponit if (atomicDispatchChunk.Chunk.Position == _defaultPollerStartingPoint) { _catchupPollerIdList.Clear(); //we need to clear all the in memory id list. foreach (var consumer in _catchupConsumerBlocks.Values.SelectMany(c => c)) { _atomicProjectionCheckpointManager.MarkPosition( consumer.Consumer.AtomicReadmodelInfoAttribute.Name, atomicDispatchChunk.Chunk.Position); } } } return(true); }
private async Task <Boolean> DispatchToTpl(AtomicDispatchChunk atomicDispatchChunk) { var result = await _tplBuffer.SendAsync(atomicDispatchChunk).ConfigureAwait(false); if (!result) { Logger.ErrorFormat("Unable to dispatch chunk {0} for poller {1}", atomicDispatchChunk.Chunk.Position, atomicDispatchChunk.PollerId); throw new JarvisFrameworkEngineException(String.Format("Unable to dispatch chunk {0} for poller {1}", atomicDispatchChunk.Chunk.Position, atomicDispatchChunk.PollerId)); } return(result); }