Esempio n. 1
0
        public virtual ICommit Commit(CommitAttempt attempt)
        {
            Logger.Debug(Messages.AttemptingToCommit, attempt.Events.Count, attempt.StreamId, attempt.CommitSequence);

            return(TryMongo(() =>
            {
                BsonDocument commitDoc = attempt.ToMongoCommit(_getNextCheckpointNumber, _serializer);
                try
                {
                    // for concurrency / duplicate commit detection safe mode is required
                    PersistedCommits.Insert(commitDoc, 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;
                    }
                    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);
            }));
        }
        private ICommit PersistWithServerSideOptimisticLoop(CommitAttempt attempt)
        {
            BsonDocument commitDoc = attempt.ToMongoCommit(_checkpointZero, _serializer);

            return(TryMongo(() =>
            {
                var result = PersistedCommits.Database.Eval(new EvalArgs()
                {
                    Code = _updateScript,
                    Lock = false,
                    Args = new BsonValue[] { commitDoc }
                });

                if (!result.IsBsonDocument)
                {
                    throw new Exception("Invalid response. Check server side js");
                }

                if (result.AsBsonDocument.Contains("id"))
                {
                    commitDoc["_id"] = result["id"];
                    UpdateStreamHeadAsync(attempt.BucketId, attempt.StreamId, attempt.StreamRevision, attempt.Events.Count);
                    Logger.Debug(Messages.CommitPersisted, attempt.CommitId);
                }
                else if (result.AsBsonDocument.Contains("err"))
                {
                    var errorDocument = result.AsBsonDocument;

                    if (errorDocument["code"] != ConcurrencyExceptionCode)
                    {
                        throw new Exception(errorDocument["err"].AsString);
                    }

                    ICommit savedCommit = PersistedCommits.FindOne(attempt.ToMongoCommitIdQuery()).ToCommit(_serializer);

                    if (savedCommit.CommitId == attempt.CommitId)
                    {
                        throw new DuplicateCommitException(String.Format(
                                                               "Duplicated Commit: bucketId [{0}]: commitId [{1}] - streamId [{2}] - streamRevision [{3}]",
                                                               attempt.BucketId, attempt.CommitId, attempt.StreamId, attempt.StreamRevision));
                    }
                    Logger.Debug(Messages.ConcurrentWriteDetected);
                    throw new ConcurrencyException(String.Format(
                                                       "Concurrency exception forbucketId [{0}]: commitId [{1}] - streamId [{2}] - streamRevision [{3}]\n Inner provider error: {4}",
                                                       attempt.BucketId, attempt.CommitId, attempt.StreamId, attempt.StreamRevision, errorDocument["err"].AsString));
                }
                else
                {
                    throw new Exception("Invalid response. Check server side js");
                }

                return commitDoc.ToCommit(_serializer);
            }));
        }
Esempio n. 3
0
        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);
            }));
        }
Esempio n. 4
0
        public virtual ICommit Commit(CommitAttempt attempt)
        {
            if (Logger.IsDebugEnabled)
            {
                Logger.Debug(Messages.AttemptingToCommit, attempt.Events.Count, attempt.StreamId, attempt.CommitSequence);
            }

            return(TryMongo(() =>
            {
                Int64 checkpointId;
                var commitDoc = attempt.ToMongoCommit(
                    checkpointId = _checkpointGenerator.Next(),
                    _serializer
                    );

                bool retry = true;
                while (retry)
                {
                    try
                    {
                        // for concurrency / duplicate commit detection safe mode is required
                        PersistedCommits.InsertOne(commitDoc);

                        retry = false;
                        if (!_options.DisableSnapshotSupport)
                        {
                            UpdateStreamHeadInBackgroundThread(attempt.BucketId, attempt.StreamId, attempt.StreamRevision, attempt.Events.Count);
                        }

                        if (Logger.IsDebugEnabled)
                        {
                            Logger.Debug(Messages.CommitPersisted, attempt.CommitId);
                        }
                    }
                    catch (MongoException e)
                    {
                        if (!e.Message.Contains(ConcurrencyException))
                        {
                            if (Logger.IsErrorEnabled)
                            {
                                Logger.Error(Messages.GenericPersistingError, attempt.CommitId, checkpointId, attempt.BucketId, attempt.StreamId, e);
                            }
                            throw;
                        }

                        // checkpoint index?
                        if (e.Message.Contains(MongoCommitIndexes.CheckpointNumberMMApV1) ||
                            e.Message.Contains(MongoCommitIndexes.CheckpointNumberWiredTiger))
                        {
                            if (Logger.IsWarnEnabled)
                            {
                                Logger.Warn(Messages.DuplicatedCheckpointTokenError, attempt.CommitId, checkpointId, attempt.BucketId, attempt.StreamId);
                            }
                            _checkpointGenerator.SignalDuplicateId(checkpointId);
                            commitDoc[MongoCommitFields.CheckpointNumber] = checkpointId = _checkpointGenerator.Next();
                        }
                        else
                        {
                            if (_options.ConcurrencyStrategy == ConcurrencyExceptionStrategy.FillHole)
                            {
                                FillHole(attempt, checkpointId);
                            }

                            if (e.Message.Contains(MongoCommitIndexes.CommitId))
                            {
                                var msg = String.Format(Messages.DuplicatedCommitError, attempt.CommitId, checkpointId, attempt.BucketId, attempt.StreamId);
                                if (Logger.IsInfoEnabled)
                                {
                                    Logger.Info(msg);
                                }
                                throw new DuplicateCommitException(msg);
                            }

                            ICommit savedCommit = PersistedCommits
                                                  .FindSync(attempt.ToMongoCommitIdQuery())
                                                  .FirstOrDefault()
                                                  .ToCommit(_serializer);

                            if (savedCommit != null && savedCommit.CommitId == attempt.CommitId)
                            {
                                var msg = String.Format(Messages.DuplicatedCommitError, attempt.CommitId, checkpointId, attempt.BucketId, attempt.StreamId);
                                if (Logger.IsInfoEnabled)
                                {
                                    Logger.Info(msg);
                                }
                                throw new DuplicateCommitException(msg);
                            }

                            if (Logger.IsInfoEnabled)
                            {
                                Logger.Info(Messages.ConcurrencyExceptionError, attempt.CommitId, checkpointId, attempt.BucketId, attempt.StreamId, e);
                            }
                            throw new ConcurrencyException();
                        }
                    }
                }

                return commitDoc.ToCommit(_serializer);
            }));
        }