/// <inheritdoc /> public async Task AppendToStream(string stream, int expectedVersion, UncommittedMessages data, CancellationToken token = default(CancellationToken)) { Guard.StreamName(stream, nameof(stream)); if (expectedVersion < ExpectedVersion.Any) { throw new ArgumentException("Expected version must be greater or equal 1, or 'Any', or 'NoStream'.", nameof(expectedVersion)); } if (data == null) { throw new ArgumentNullException(nameof(data)); } try { switch (expectedVersion) { default: _settings.Logger.Trace("Appending {0} messages to stream '{1}' with expected version {2}...", data.Messages.Length, stream, expectedVersion); await AppendToStreamWithExpectedVersion(stream, expectedVersion, data, token).NotOnCapturedContext(); break; case ExpectedVersion.Any: _settings.Logger.Trace("Appending {0} messages to stream '{1}' with any version...", data.Messages.Length, stream); await AppendToStreamWithAnyVersion(stream, data, token).NotOnCapturedContext(); break; case ExpectedVersion.NoStream: _settings.Logger.Trace("Appending {0} messages to stream '{1}' where stream not existed yet...", data.Messages.Length, stream); await AppendToStreamWithExpectedVersion(stream, ExpectedVersion.NoStream, data, token).NotOnCapturedContext(); break; } _settings.Linearizer?.Start(); } catch (WrongExpectedVersionException) { throw; } catch (Exception e) { _settings.Logger.Error(e.ToString()); } }
private async Task AppendToStreamWithAnyVersion(string stream, UncommittedMessages data, CancellationToken token) { _settings.Logger.Trace("Appending {0} messages to stream '{1}' with any version...", data.Messages.Length, stream); using (var connection = new SqlConnection(_settings.ConnectionString)) { await connection.OpenAsync(token).NotOnCapturedContext(); using (var tran = connection.BeginTransaction(IsolationLevel.ReadCommitted)) { try { foreach (var msg in data.Messages) { using (var cmd = connection.CreateCommandToAppendingWithAnyVersion(stream, data, msg)) { cmd.Transaction = tran; await cmd.ExecuteNonQueryAsync(token).NotOnCapturedContext(); } } tran.Commit(); } catch (SqlException e) { tran.Rollback(); if (e.IsUniqueConstraintViolation() || e.IsWrongExpectedVersionRised()) { throw new WrongExpectedVersionException($"Appending {data.Messages.Length} messages to stream '{stream}' with any version failed.", e); } throw; } } } }
private static async Task ReadingExecute(UncommittedMessages data) { await store.ReadStreamForward(data.CorrelationId.ToString(), 0); }
private static async Task AppendingExecute(UncommittedMessages data) { await store.AppendToStream(data.CorrelationId.ToString(), ExpectedVersion.NoStream, data).NotOnCapturedContext(); }
private async Task AppendToStreamWithExpectedVersion(string stream, int expectedVersion, UncommittedMessages data, CancellationToken token) { using (var connection = new SqlConnection(_settings.ConnectionString)) { await connection.OpenAsync(token).NotOnCapturedContext(); using (var tran = connection.BeginTransaction(IsolationLevel.ReadCommitted)) { try { var messageVersion = expectedVersion; foreach (var msg in data.Messages) { messageVersion += 1; using (var cmd = expectedVersion == 0 && messageVersion == 1 ? connection.CreateCommandToAppendingWithNoStream(stream, data, msg) : connection.CreateCommandToAppendingWithExpectedVersion(stream, data, msg, messageVersion)) { cmd.Transaction = tran; await cmd.ExecuteNonQueryAsync(token).NotOnCapturedContext(); } } tran.Commit(); } catch (SqlException e) { tran.Rollback(); if (e.IsUniqueConstraintViolation() || e.IsWrongExpectedVersionRised()) { throw new WrongExpectedVersionException($"Appending {data.Messages.Length} messages to stream '{stream}' with expected version {ExpectedVersion.Parse(expectedVersion)} failed.", e); } throw; } } } }
public static SqlCommand CreateCommandToAppendingWithNoStream(this SqlConnection cnn, string name, UncommittedMessages data, MessageRecord msg) { Guard.StreamName(msg.ContractName, "contractName"); return(cnn .CreateCommand(mantaAppendNoStreamCommand) .AddInputParam(paramStreamName, SqlDbType.VarChar, name, SqlClientExtensions.DefaultStreamNameLength) .AddInputParam(paramCorrelationId, SqlDbType.UniqueIdentifier, data.CorrelationId) .AddInputParam(paramContractName, SqlDbType.VarChar, msg.ContractName, SqlClientExtensions.DefaultContractNameLength) .AddInputParam(paramMessageId, SqlDbType.UniqueIdentifier, msg.MessageId) .AddInputParam(paramPayload, SqlDbType.VarBinary, msg.Payload) .AddInputParam(paramMetadataPayload, SqlDbType.VarBinary, data.Metadata)); }