Пример #1
0
        void IHandle <ReplicationMessage.WriteCommit> .Handle(ReplicationMessage.WriteCommit message)
        {
            Interlocked.Decrement(ref _flushMessagesInQueue);
            try
            {
                var result = _readIndex.CheckCommitStartingAt(message.PrepareStartPosition);
                switch (result.Decision)
                {
                case CommitDecision.Ok:
                {
                    var commit = WriteCommitWithRetry(LogRecord.Commit(_writer.Checkpoint.ReadNonFlushed(),
                                                                       message.CorrelationId,
                                                                       message.PrepareStartPosition,
                                                                       result.CurrentVersion + 1));
                    _readIndex.Commit(commit);
                    break;
                }

                case CommitDecision.WrongExpectedVersion:
                    message.Envelope.ReplyWith(new ReplicationMessage.WrongExpectedVersion(message.CorrelationId));
                    break;

                case CommitDecision.Deleted:
                    message.Envelope.ReplyWith(new ReplicationMessage.StreamDeleted(message.CorrelationId));
                    break;

                case CommitDecision.Idempotent:
                    message.Envelope.ReplyWith(new ReplicationMessage.AlreadyCommitted(message.CorrelationId,
                                                                                       result.EventStreamId,
                                                                                       result.StartEventNumber,
                                                                                       result.EndEventNumber));
                    break;

                case CommitDecision.CorruptedIdempotency:
                    //TODO AN add messages and error code for invalid idempotent request
                    throw new Exception("The request was partially committed and other part is different.");

                case CommitDecision.InvalidTransaction:
                    message.Envelope.ReplyWith(new ReplicationMessage.InvalidTransaction(message.CorrelationId));
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
            finally
            {
                Flush();
            }
        }
Пример #2
0
        void IHandle <ReplicationMessage.WriteCommit> .Handle(ReplicationMessage.WriteCommit message)
        {
            if (_state != VNodeState.Master)
            {
                throw new InvalidOperationException("Write request not in working state.");
            }
            Interlocked.Decrement(ref _flushMessagesInQueue);

            try
            {
                // TODO AN: do it without exception catching
                PrepareLogRecord prepare;
                try
                {
                    prepare = _readIndex.GetPrepare(message.PrepareStartPosition);
                }
                catch (InvalidOperationException)
                {
                    message.Envelope.ReplyWith(new ReplicationMessage.InvalidTransaction(message.CorrelationId));
                    return;
                }

                var eventStreamId  = prepare.EventStreamId;
                int currentVersion = _readIndex.GetLastStreamEventNumber(eventStreamId);

                if (currentVersion == EventNumber.DeletedStream)
                {
                    message.Envelope.ReplyWith(new ReplicationMessage.StreamDeleted(message.CorrelationId));
                    return;
                }
                if (prepare.ExpectedVersion != ExpectedVersion.Any && currentVersion != prepare.ExpectedVersion)
                {
                    message.Envelope.ReplyWith(new ReplicationMessage.WrongExpectedVersion(message.CorrelationId));
                    return;
                }

                var commit = WriteCommitWithRetry(LogRecord.Commit(_writer.Checkpoint.ReadNonFlushed(),
                                                                   message.CorrelationId,
                                                                   message.PrepareStartPosition,
                                                                   currentVersion + 1));
                _readIndex.Commit(commit);
            }
            finally
            {
                Flush();
            }
        }