public virtual void Commit(Commit attempt) { Logger.Debug(Messages.AttemptingToCommit, attempt.Events.Count, attempt.StreamId, attempt.CommitSequence); TryMongo(() => { BsonDocument commit = attempt.ToMongoCommit(_serializer); try { // for concurrency / duplicate commit detection safe mode is required PersistedCommits.Insert(commit, WriteConcern.Acknowledged); UpdateStreamHeadAsync(attempt.BucketId, attempt.StreamId, attempt.StreamRevision, attempt.Events.Count); Logger.Debug(Messages.CommitPersisted, attempt.CommitId); } catch (MongoException e) { if (!e.Message.Contains(ConcurrencyException)) { throw; } Commit savedCommit = PersistedCommits.FindOne(attempt.ToMongoCommitIdQuery()).ToCommit(_serializer); if (savedCommit.CommitId == attempt.CommitId) { throw new DuplicateCommitException(); } Logger.Debug(Messages.ConcurrentWriteDetected); throw new ConcurrencyException(); } }); }
private ICommit PersistWithClientSideOptimisticLoop(CommitAttempt attempt) { return(TryMongo(() => { BsonDocument commitDoc = attempt.ToMongoCommit( _getNextCheckpointNumber(), _serializer ); bool retry = true; while (retry) { try { // for concurrency / duplicate commit detection safe mode is required PersistedCommits.Insert(commitDoc, _insertCommitWriteConcern); retry = false; UpdateStreamHeadAsync(attempt.BucketId, attempt.StreamId, attempt.StreamRevision, attempt.Events.Count); Logger.Debug(Messages.CommitPersisted, attempt.CommitId); } catch (MongoException e) { if (!e.Message.Contains(ConcurrencyException)) { throw; } // checkpoint index? if (e.Message.Contains(MongoCommitIndexes.CheckpointNumberMMApV1) || e.Message.Contains(MongoCommitIndexes.CheckpointNumberWiredTiger)) { commitDoc[MongoCommitFields.CheckpointNumber] = _getNextCheckpointNumber().LongValue; } else { ICommit savedCommit = PersistedCommits.FindOne(attempt.ToMongoCommitIdQuery()).ToCommit(_serializer); if (savedCommit.CommitId == attempt.CommitId) { throw new DuplicateCommitException(); } Logger.Debug(Messages.ConcurrentWriteDetected); throw new ConcurrencyException(); } } } return commitDoc.ToCommit(_serializer); })); }