Ejemplo n.º 1
0
        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 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);
            }));
        }
Ejemplo 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);
            }));
        }