/// <summary> /// Create a poller, start the poller and return starting position of the poller. /// </summary> /// <param name="poller"></param> /// <param name="pollerId"></param> /// <returns></returns> private Int64 CreatePollerAndStart(ref PollingClient poller, Int32 pollerId, Func <AtomicDispatchChunk, Task <Boolean> > dispatchToTplFunction) { if (poller != null) { poller.Stop(); } var startingPosition = TryGetStartingPoint(pollerId); Logger.InfoFormat("AtomicProjectionEngine: Starting poller id {0} from position {1}", pollerId, startingPosition); var subscription = new JarvisFrameworkLambdaSubscription(c => dispatchToTplFunction(new AtomicDispatchChunk(pollerId, c))); poller = new PollingClient(_persistence, startingPosition, subscription, _nStoreLoggerFactory); poller.Start(); return(startingPosition); }
/// <summary> /// Create a poller, start the poller and return starting position of the poller. /// </summary> /// <param name="poller"></param> /// <param name="pollerId"></param> /// <returns></returns> private Int64 CreatePollerAndStart(ref PollingClient poller, Int32 pollerId, Func <AtomicDispatchChunk, Task <Boolean> > dispatchToTplFunction) { if (poller != null) { poller.Stop(); } //The default value to start is zero, it is a situation that should never happen, if it happens this poller has no projection to dispatch. var startingPosition = TryGetStartingPoint(pollerId, 0); Logger.InfoFormat("AtomicProjectionEngine: Starting poller id {0} from position {1}", pollerId, startingPosition); var subscription = new JarvisFrameworkLambdaSubscription(c => dispatchToTplFunction(new AtomicDispatchChunk(pollerId, c))); poller = new PollingClient(_persistence, startingPosition, subscription, _nStoreLoggerFactory); poller.Start(); return(startingPosition); }
public void Configure( Int64 checkpointTokenFrom, Int32 bufferSize) { _logger.InfoFormat("CommitPollingClient {0}: Configured starting from {1} buffer {2}", _id, checkpointTokenFrom, bufferSize); _bufferSize = bufferSize; _lastDispatchedPosition = checkpointTokenFrom - 1; LastException = null; //prepare single poller thread. CreateTplChain(); _innerSubscription = new JarvisFrameworkLambdaSubscription(DispatchChunk); _innerClient = new PollingClient( _persistence, checkpointTokenFrom, _innerSubscription, _factory); RegisterHealthChecks(_id); }
public async Task UnwindAsync() { var lastEvent = _unwindedEventCollection .Find(Builders <UnwindedDomainEvent> .Filter.Empty) .Sort(Builders <UnwindedDomainEvent> .Sort.Descending(e => e.CheckpointToken)) .Limit(1) .SingleOrDefault(); Int64 startToken = 1; //remember with NStore is inclusive if (lastEvent != null) { startToken = lastEvent.CheckpointToken; } //we want to avoid holes up to the maximum committed tokens, holes are only when we are //in high concurrency. var lastCommittedToken = await _persistence.ReadLastPositionAsync().ConfigureAwait(false); lastCommittedToken = Math.Max(0, lastCommittedToken - 10); //we choose an arbitrary offset to avoid problem in high concurrency _logger.InfoFormat("Unwind events starting from commit {0}", startToken); //Since we could have crashed during unwind of last commit, we want to reunwind again last commit Int64 checkpointToken = startToken; _unwindedEventCollection.DeleteMany(Builders <UnwindedDomainEvent> .Filter.Gte(e => e.CheckpointToken, startToken)); Int64 count = 0; List <UnwindedDomainEvent> batchEventUnwind = new List <UnwindedDomainEvent>(550); var subscription = new JarvisFrameworkLambdaSubscription(async data => { foreach (var evt in UnwindChunk(data)) { batchEventUnwind.Add(evt); if (batchEventUnwind.Count > 500) { await _unwindedEventCollection.InsertManyAsync(batchEventUnwind).ConfigureAwait(false); batchEventUnwind.Clear(); } } checkpointToken = data.Position; if (++count % 10000 == 0) { _logger.InfoFormat("Unwinded block of 10000 commit, now we are at checkpoint {0}", checkpointToken); } return(true); }, "unwinder"); var sequencer = new NStoreSequencer( startToken - 1, subscription, timeToWaitInMilliseconds: 0, maximumWaitCountForSingleHole: 5, safePosition: lastCommittedToken, logger: _logger); //Need to cycle until the sequencer skipped an hole, to be sure to unwind all events. do { //Reload from the last position where the sequencer stopped. await _persistence.ReadAllAsync(sequencer.Position + 1, sequencer).ConfigureAwait(false); } while (sequencer.RetriesOnHole > 0); if (subscription.Failed) { throw new JarvisFrameworkEngineException("Error unwinding commits", subscription.LastException); } //Flush last batch. if (batchEventUnwind.Count > 0) { _unwindedEventCollection.InsertMany(batchEventUnwind); } _logger.InfoFormat("Unwind events ends, started from commit {0} and ended with commit {1}", startToken, checkpointToken); }