public void RebuildStarted(IProjection projection, String lastCommitId) { var projectionName = projection.GetCommonName(); _checkpoints.Update( Query.EQ("_id", projectionName), Update <Checkpoint> .Set(x => x.RebuildStart, DateTime.UtcNow) .Set(x => x.RebuildStop, null) .Set(x => x.RebuildTotalSeconds, 0) .Set(x => x.RebuildActualSeconds, 0) .Set(x => x.Current, null) .Set(x => x.Events, 0) .Set(x => x.Details, null) ); //Check if some commit was deleted and lastCommitId in Eventstore //is lower than the latest dispatched commit. var trackerLastValue = LongCheckpoint.Parse(_checkpointTracker[projection.GetCommonName()]).LongValue; var lastCommitIdLong = LongCheckpoint.Parse(lastCommitId).LongValue; if (trackerLastValue > 0) { //new projection, it has no dispatched checkpoint. _slotRebuildTracker[_projectionToSlot[projectionName]] = true; } if (lastCommitIdLong < trackerLastValue) { _checkpointTracker[projection.GetCommonName()] = lastCommitId; _checkpoints.Update( Query.EQ("_id", projectionName), Update <Checkpoint> .Set(x => x.Value, lastCommitId)); } _higherCheckpointToDispatchInRebuild = Math.Max( _higherCheckpointToDispatchInRebuild, Math.Min(trackerLastValue, lastCommitIdLong)); }
public virtual IEnumerable <ICommit> GetFrom(string checkpointToken) { Logger.Debug(Messages.GettingAllCommitsFromCheckpoint, checkpointToken); LongCheckpoint checkpoint = LongCheckpoint.Parse(checkpointToken); return(QueryCommits <RavenCommitByCheckpoint>(x => x.CheckpointNumber > checkpoint.LongValue, x => x.CheckpointNumber)); }
string GetStartCheckpointForSlot(string slotName) { LongCheckpoint min = null; var projections = _projectionsBySlot[slotName]; foreach (var projection in projections) { if (_checkpointTracker.NeedsRebuild(projection)) { return(null); } var currentValue = _checkpointTracker.GetCurrent(projection); if (currentValue == null) { return(null); } var currentCheckpoint = LongCheckpoint.Parse(currentValue); if (min == null || currentCheckpoint.LongValue < min.LongValue) { min = currentCheckpoint; } } return(min.Value); }
public IEnumerable <ICommit> GetFrom(string bucketId, string checkpointToken) { var intCheckpoint = LongCheckpoint.Parse(checkpointToken); Logger.Debug(Messages.GettingAllCommitsFromBucketAndCheckpoint, bucketId, intCheckpoint.Value); return(QueryCommits <RavenCommitByCheckpoint>(x => x.BucketId == bucketId && x.CheckpointNumber > intCheckpoint.LongValue, x => x.CheckpointNumber)); }
void ConfigureProjections() { _checkpointTracker.SetUp(_allProjections, 1); var lastCommit = GetLastCommitId(); foreach (var slot in _projectionsBySlot) { var maxCheckpointDispatchedInSlot = slot.Value .Select(projection => { var checkpoint = _checkpointTracker.GetCheckpoint(projection); var longCheckpoint = LongCheckpoint.Parse(checkpoint); return(longCheckpoint.LongValue); }) .Max(); foreach (var projection in slot.Value) { //Rebuild the slot only if it has at least one dispatched commit if (_checkpointTracker.NeedsRebuild(projection) && maxCheckpointDispatchedInSlot >= 0) { //be sure that projection in rebuild has the same Last dispatched commit fo the entire slot _checkpointTracker.SetCheckpoint(projection.GetCommonName(), maxCheckpointDispatchedInSlot.ToString()); projection.Drop(); projection.StartRebuild(_rebuildContext); _checkpointTracker.RebuildStarted(projection, lastCommit); } projection.SetUp(); } } }
string GetStartGlobalCheckpoint() { var checkpoints = _projectionsBySlot.Keys.Select(GetStartCheckpointForSlot).Distinct().ToArray(); var min = checkpoints.Any() ? checkpoints.Min(x => LongCheckpoint.Parse(x).LongValue) : 0; return(new LongCheckpoint(min).Value); }
public void should_have_a_checkpoint_greater_than_the_previous_commit_on_the_other_process() { long chkNum1 = LongCheckpoint.Parse(_commit1.CheckpointToken).LongValue; long chkNum2 = LongCheckpoint.Parse(_commit2.CheckpointToken).LongValue; chkNum2.ShouldBeGreaterThan(chkNum1); }
public Task <ICheckpoint> GetCheckpoint(string checkpointToken) { if (string.IsNullOrWhiteSpace(checkpointToken)) { return(Task.FromResult <ICheckpoint>(new LongCheckpoint(-1))); } return(Task.FromResult <ICheckpoint>(LongCheckpoint.Parse(checkpointToken))); }
public ICheckpoint GetCheckpoint(string checkpointToken) { if (string.IsNullOrWhiteSpace(checkpointToken)) { return(new LongCheckpoint(-1)); } return(LongCheckpoint.Parse(checkpointToken)); }
protected override void Context() { var commit = Persistence.Commit(Guid.NewGuid().ToString().BuildAttempt()); _checkpointBeforePurge = LongCheckpoint.Parse(commit.CheckpointToken); Persistence.DeleteStream(commit.StreamId); Persistence.Purge("default"); }
void ConfigureProjections() { _checkpointTracker.SetUp(_allProjections, 1); var lastCommit = GetLastCommitId(); foreach (var slot in _projectionsBySlot) { var maxCheckpointDispatchedInSlot = slot.Value .Select(projection => { var checkpoint = _checkpointTracker.GetCheckpoint(projection); var longCheckpoint = LongCheckpoint.Parse(checkpoint); return(longCheckpoint.LongValue); }) .Max(); foreach (var projection in slot.Value) { if (_checkpointTracker.NeedsRebuild(projection)) { //Check if this slot has ever dispatched at least one commit if (maxCheckpointDispatchedInSlot > 0) { _checkpointTracker.SetCheckpoint(projection.GetCommonName(), maxCheckpointDispatchedInSlot.ToString()); projection.Drop(); projection.StartRebuild(_rebuildContext); _checkpointTracker.RebuildStarted(projection, lastCommit); } else { //this is a new slot, all the projection should execute //as if they are not in rebuild, because they are new //so we need to immediately stop rebuilding. projection.StopRebuild(); } } projection.SetUp(); } } var errors = _checkpointTracker.GetCheckpointErrors(); if (errors.Any()) { StringBuilder fullError = new StringBuilder(); foreach (var error in errors) { Logger.ErrorFormat("CheckpointError: {0}", error); fullError.AppendLine(error); } throw new Exception(String.Format("Found {0} errors in checkpoint status: {1}", errors.Count, fullError.ToString())); } }
public void OnNext(ICommit value) { var chkpoint = LongCheckpoint.Parse(value.CheckpointToken).LongValue; if (chkpoint > _lastCheckpoint) { _counter++; } _lastCheckpoint = chkpoint; }
public IEnumerable <ICommit> GetFrom(string checkpointToken) { Logger.Debug(Resources.GettingAllCommitsFromCheckpoint, checkpointToken); ICheckpoint checkpoint = LongCheckpoint.Parse(checkpointToken); return(_buckets .Values .SelectMany(b => b.GetCommits()) .Where(c => c.Checkpoint.CompareTo(checkpoint) > 0) .OrderBy(c => c.Checkpoint) .ToArray()); }
public CheckPointReplayStatus GetCheckpointStatus(string id, string checkpoint) { string lastDispatched = _checkpointTracker[id]; var currentCheckpointValue = LongCheckpoint.Parse(checkpoint).LongValue; long lastDispatchedValue = LongCheckpoint.Parse(lastDispatched).LongValue; bool isLast = currentCheckpointValue == lastDispatchedValue; bool isReplay = currentCheckpointValue <= lastDispatchedValue; _checkpointSlotTracker[_projectionToSlot[id]] = _higherCheckpointToDispatchInRebuild - currentCheckpointValue; return(new CheckPointReplayStatus(isLast, isReplay)); }
public IEnumerable <ICommit> GetFrom(string checkpointToken) { LongCheckpoint checkpoint = LongCheckpoint.Parse(checkpointToken); Logger.Debug(Messages.GettingAllCommitsFromCheckpoint, checkpointToken); return(ExecuteQuery(query => { string statement = _dialect.GetCommitsFromCheckpoint; query.AddParameter(_dialect.CheckpointNumber, checkpoint.LongValue); return query.ExecutePagedQuery(statement, (q, r) => { }) .Select(x => x.GetCommit(_serializer, _dialect)); })); }
public IEnumerable <ICommit> GetFrom(string bucketId, string checkpointToken) { LongCheckpoint checkpoint = LongCheckpoint.Parse(checkpointToken); Logger.Debug(Messages.GettingAllCommitsFromBucketAndCheckpoint, bucketId, checkpointToken); return(this.ExecuteQuery(query => { string statement = this._dialect.GetCommitsFromBucketAndCheckpoint; query.AddParameter(this._dialect.BucketId, bucketId, DbType.AnsiString); query.AddParameter(this._dialect.CheckpointNumber, checkpoint.LongValue); return query.ExecutePagedQuery(statement, (q, r) => { }) .Select(x => x.GetCommit(this._serializer, this._dialect)); })); }
private void Init() { _maxDispatchedCheckpoint = 0; DumpProjections(); TenantContext.Enter(_config.TenantId); _housekeeper.Init(); _eventstore = Wireup .Init() .LogTo(t => new NEventStoreLog4NetLogger(LoggerFactory.Create(t))) .UsingMongoPersistence(() => _config.EventStoreConnectionString, new DocumentObjectSerializer()) .InitializeStorageEngine() .Build(); ConfigureProjections(); // cleanup _housekeeper.RemoveAll(_eventstore.Advanced); var allSlots = _projectionsBySlot.Keys.ToArray(); //recreate all polling clients. foreach (var bucket in _config.BucketInfo) { var client = _pollingClientFactory(_eventstore.Advanced); _clients.Add(client); _bucketToClient.Add(bucket, client); } foreach (var slotName in allSlots) { MetricsHelper.CreateMeterForDispatcherCountSlot(slotName); var startCheckpoint = GetStartCheckpointForSlot(slotName); Logger.InfoFormat("Slot {0} starts from {1}", slotName, startCheckpoint); var name = slotName; //find right consumer var slotBucket = _config.BucketInfo.SingleOrDefault(b => b.Slots.Any(s => s.Equals(slotName, StringComparison.OrdinalIgnoreCase))) ?? _config.BucketInfo.Single(b => b.Slots[0] == "*"); var client = _bucketToClient[slotBucket]; client.AddConsumer(commit => DispatchCommit(commit, name, LongCheckpoint.Parse(startCheckpoint))); } MetricsHelper.SetProjectionEngineCurrentDispatchCount(() => _countOfConcurrentDispatchingCommit); }
public IEnumerable <ICommit> GetFrom(string checkpointToken) { var intCheckpoint = LongCheckpoint.Parse(checkpointToken); Logger.Debug(Messages.GettingAllCommitsFromCheckpoint, intCheckpoint.Value); return(TryMongo(() => PersistedCommits .Find( Query.And( Query.NE(MongoCommitFields.BucketId, MongoSystemBuckets.RecycleBin), Query.GT(MongoCommitFields.CheckpointNumber, intCheckpoint.LongValue) ) ) .SetSortOrder(MongoCommitFields.CheckpointNumber) .Select(x => x.ToCommit(_serializer)) )); }
private void Init() { _maxDispatchedCheckpoint = 0; DumpProjections(); _stopping = new ManualResetEventSlim(false); TenantContext.Enter(_config.TenantId); _housekeeper.Init(); _eventstore = Wireup .Init() .LogTo(t => new NEventStoreLog4NetLogger(LoggerFactory.Create(t))) .UsingMongoPersistence(() => _config.EventStoreConnectionString, new DocumentObjectSerializer()) .InitializeStorageEngine() .Build(); ConfigureProjections(); // cleanup _housekeeper.RemoveAll(_eventstore.Advanced); var allSlots = _projectionsBySlot.Keys.ToArray(); _client.Create(_eventstore.Advanced, _config.PollingMsInterval); var subscriptions = new List <IDisposable>(); _observeCommits = _client.ObserveFrom(GetStartGlobalCheckpoint()); foreach (var slotName in allSlots) { MetricsHelper.CreateMeterForDispatcherCountSlot(slotName); var startCheckpoint = GetStartCheckpointForSlot(slotName); Logger.InfoFormat("Slot {0} starts from {1}", slotName, startCheckpoint); var name = slotName; subscriptions.Add( _observeCommits.Subscribe(commit => DispatchCommit(commit, name, LongCheckpoint.Parse(startCheckpoint)), HandleError)); } _subscriptions = subscriptions.ToArray(); }
public ICheckpoint GetCheckpoint(string checkpointToken = null) { return(LongCheckpoint.Parse(checkpointToken)); }
void DispatchCommit(ICommit commit, string slotName, LongCheckpoint startCheckpoint) { Interlocked.Increment(ref _countOfConcurrentDispatchingCommit); //Console.WriteLine("[{0:00}] - Slot {1}", Thread.CurrentThread.ManagedThreadId, slotName); if (Logger.IsDebugEnabled) { Logger.ThreadProperties["commit"] = commit.CommitId; } if (Logger.IsDebugEnabled) { Logger.DebugFormat("Dispatching checkpoit {0} on tenant {1}", commit.CheckpointToken, _config.TenantId); } TenantContext.Enter(_config.TenantId); var chkpoint = LongCheckpoint.Parse(commit.CheckpointToken); if (!lastCheckpointDispatched.ContainsKey(slotName)) { lastCheckpointDispatched[slotName] = 0; } if (!(lastCheckpointDispatched[slotName] < chkpoint.LongValue)) { var error = String.Format("Sequence broken, last checkpoint for slot {0} was {1} and now we dispatched {2}", slotName, lastCheckpointDispatched[slotName], chkpoint.LongValue); Logger.Error(error); throw new Exception(error); } if (lastCheckpointDispatched[slotName] + 1 != chkpoint.LongValue) { if (lastCheckpointDispatched[slotName] > 0) { Logger.WarnFormat("Sequence of commit non consecutive, last dispatched {0} receiving {1}", lastCheckpointDispatched[slotName], chkpoint.LongValue); } } lastCheckpointDispatched[slotName] = chkpoint.LongValue; if (chkpoint.LongValue <= startCheckpoint.LongValue) { //Already dispatched, skip it. Interlocked.Decrement(ref _countOfConcurrentDispatchingCommit); return; } var projections = _projectionsBySlot[slotName]; bool dispatchCommit = false; var eventCount = commit.Events.Count(); var projectionToUpdate = new List <string>(); for (int index = 0; index < eventCount; index++) { var eventMessage = commit.Events.ElementAt(index); try { var evt = (DomainEvent)eventMessage.Body; if (Logger.IsDebugEnabled) { Logger.ThreadProperties["evType"] = evt.GetType().Name; } if (Logger.IsDebugEnabled) { Logger.ThreadProperties["evMsId"] = evt.MessageId; } if (Logger.IsDebugEnabled) { Logger.ThreadProperties["evCheckpointToken"] = commit.CheckpointToken; } string eventName = evt.GetType().Name; foreach (var projection in projections) { var cname = projection.GetCommonName(); if (Logger.IsDebugEnabled) { Logger.ThreadProperties["prj"] = cname; } var checkpointStatus = _checkpointTracker.GetCheckpointStatus(cname, commit.CheckpointToken); bool handled; long ticks = 0; try { //pay attention, stopwatch consumes time. var sw = new Stopwatch(); sw.Start(); handled = projection.Handle(evt, checkpointStatus.IsRebuilding); sw.Stop(); ticks = sw.ElapsedTicks; MetricsHelper.IncrementProjectionCounter(cname, slotName, eventName, ticks); } catch (Exception ex) { Logger.FatalFormat(ex, "[Slot: {3} Projection: {4}] Failed checkpoint: {0} StreamId: {1} Event Name: {2}", commit.CheckpointToken, commit.StreamId, eventName, slotName, cname ); throw; } if (handled) { _metrics.Inc(cname, eventName, ticks); if (Logger.IsDebugEnabled) { Logger.DebugFormat("[{3}] [{4}] Handled checkpoint {0}: {1} > {2}", commit.CheckpointToken, commit.StreamId, eventName, slotName, cname ); } } if (!checkpointStatus.IsRebuilding) { if (handled) { dispatchCommit = true; } projectionToUpdate.Add(cname); } else { if (checkpointStatus.IsLast && (index == eventCount - 1)) { projection.StopRebuild(); var meter = _metrics.GetMeter(cname); _checkpointTracker.RebuildEnded(projection, meter); Logger.InfoFormat("Rebuild done {0} @ {1}", projection.GetType().FullName, commit.CheckpointToken ); } } if (Logger.IsDebugEnabled) { Logger.ThreadProperties["prj"] = null; } } ClearLoggerThreadPropertiesForEventDispatchLoop(); } catch (Exception ex) { Logger.ErrorFormat(ex, "Error dispathing commit id: {0}\nMessage: {1}\nError: {2}", commit.CheckpointToken, eventMessage.Body, ex.Message); ClearLoggerThreadPropertiesForEventDispatchLoop(); throw; } } if (projectionToUpdate.Count == 0) { //I'm in rebuilding or no projection had run any events, only update slot _checkpointTracker.UpdateSlot(slotName, commit.CheckpointToken); } else { //I'm not on rebuilding, we have projection to update, update everything with one call. _checkpointTracker.UpdateSlotAndSetCheckpoint(slotName, projectionToUpdate, commit.CheckpointToken); } MetricsHelper.MarkCommitDispatchedCount(slotName, 1); if (dispatchCommit) { _notifyCommitHandled.SetDispatched(commit); } // ok in multithread wihout locks! if (_maxDispatchedCheckpoint < chkpoint.LongValue) { if (Logger.IsDebugEnabled) { Logger.DebugFormat("Updating last dispatched checkpoint from {0} to {1}", _maxDispatchedCheckpoint, chkpoint.LongValue ); } _maxDispatchedCheckpoint = chkpoint.LongValue; } if (Logger.IsDebugEnabled) { Logger.ThreadProperties["commit"] = null; } Interlocked.Decrement(ref _countOfConcurrentDispatchingCommit); }
void DispatchCommit(ICommit commit, string slotName, LongCheckpoint startCheckpoint) { if (Logger.IsDebugEnabled) { Logger.ThreadProperties["commit"] = commit.CommitId; } if (Logger.IsDebugEnabled) { Logger.DebugFormat("Dispatching checkpoit {0} on tenant {1}", commit.CheckpointToken, _config.TenantId); } TenantContext.Enter(_config.TenantId); var chkpoint = LongCheckpoint.Parse(commit.CheckpointToken); if (chkpoint.LongValue <= startCheckpoint.LongValue) { // già fatta return; } var projections = _projectionsBySlot[slotName]; bool dispatchCommit = false; var eventMessages = commit.Events.ToArray(); var projectionToUpdate = new List <string>(); for (int index = 0; index < eventMessages.Length; index++) { var eventMessage = eventMessages[index]; try { var evt = (DomainEvent)eventMessage.Body; if (Logger.IsDebugEnabled) { Logger.ThreadProperties["evType"] = evt.GetType().Name; } if (Logger.IsDebugEnabled) { Logger.ThreadProperties["evMsId"] = evt.MessageId; } string eventName = evt.GetType().Name; foreach (var projection in projections) { var cname = projection.GetCommonName(); if (Logger.IsDebugEnabled) { Logger.ThreadProperties["prj"] = cname; } var checkpointStatus = _checkpointTracker.GetCheckpointStatus(cname, commit.CheckpointToken); bool handled; long ticks = 0; try { var sw = new Stopwatch(); sw.Start(); //if (Logger.IsDebugEnabled)Logger.DebugFormat("Handling {0} with {1}", commit.CheckpointToken, projection.GetType().Name); handled = projection.Handle(evt, checkpointStatus.IsRebuilding); //if (Logger.IsDebugEnabled)Logger.DebugFormat("Handled {0} with {1}", commit.CheckpointToken, projection.GetType().Name); sw.Stop(); ticks = sw.ElapsedTicks; } catch (Exception ex) { Logger.FatalFormat(ex, "[{3}] Failed checkpoint {0}: {1} > {2}", commit.CheckpointToken, commit.StreamId, eventName, slotName ); throw; } if (handled) { _metrics.Inc(cname, eventName, ticks); Logger.DebugFormat("[{3}] [{4}] Handled checkpoint {0}: {1} > {2}", commit.CheckpointToken, commit.StreamId, eventName, slotName, cname ); } if (!checkpointStatus.IsRebuilding) { if (handled) { dispatchCommit = true; } projectionToUpdate.Add(cname); } else { if (checkpointStatus.IsLast && (index == eventMessages.Length - 1)) { projection.StopRebuild(); var meter = _metrics.GetMeter(cname); _checkpointTracker.RebuildEnded(projection, meter); Logger.InfoFormat("Rebuild done {0} @ {1}", projection.GetType().FullName, commit.CheckpointToken ); } } if (Logger.IsDebugEnabled) { Logger.ThreadProperties["prj"] = null; } } if (Logger.IsDebugEnabled) { Logger.ThreadProperties["evType"] = null; } if (Logger.IsDebugEnabled) { Logger.ThreadProperties["evMsId"] = null; } } catch (Exception ex) { if (Logger.IsDebugEnabled) { Logger.ErrorFormat(ex, "{0} -> {1}", eventMessage.Body, ex.Message); } throw; } } _checkpointTracker.UpdateSlot(slotName, commit.CheckpointToken); MetricsHelper.MarkCommitDispatchedCount(slotName, 1); foreach (var cname in projectionToUpdate) { _checkpointTracker.SetCheckpoint(cname, commit.CheckpointToken); } if (dispatchCommit) { _notifyCommitHandled.SetDispatched(commit); } // ok in multithread wihout locks! if (_maxDispatchedCheckpoint < chkpoint.LongValue) { if (Logger.IsDebugEnabled) { Logger.DebugFormat("Updating last dispatched checkpoint from {0} to {1}", _maxDispatchedCheckpoint, chkpoint.LongValue ); } _maxDispatchedCheckpoint = chkpoint.LongValue; } if (Logger.IsDebugEnabled) { Logger.ThreadProperties["commit"] = null; } }
public void should_have_correct_checkpoint() { LongCheckpoint.Parse(_checkpointToken).LongValue.ShouldBe(Clients * Iterations + 1); }
public void should_have_checkpoint_equal_to_two() { LongCheckpoint.Parse(_commit.CheckpointToken).LongValue.ShouldBe(2); }
public void last_deleted_commit_has_the_higher_checkpoint_number() { LongCheckpoint.Parse(_commits[0].CheckpointToken).LongValue.ShouldBe(4); }
public ICheckpoint GetCheckpoint(string checkpointToken) { return(string.IsNullOrWhiteSpace(checkpointToken) ? null : LongCheckpoint.Parse(checkpointToken)); }
public Task <ICheckpoint> GetCheckpoint(string checkpointToken = null) { return(Task.FromResult <ICheckpoint>(LongCheckpoint.Parse(checkpointToken))); }
protected override void Because() { var commit = Persistence.Commit(Guid.NewGuid().ToString().BuildAttempt()); _checkpointAfterPurge = LongCheckpoint.Parse(commit.CheckpointToken); }
public ICheckpoint ParseCheckpoint(string checkpointValue) { return(LongCheckpoint.Parse(checkpointValue)); }