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(); } }
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(); } }