public async Task <AppendEventsResult> AppendEvents( StreamName stream, ExpectedStreamVersion expectedVersion, IReadOnlyCollection <StreamEvent> events, CancellationToken cancellationToken ) { var streamName = stream.ToString(); var documents = events.Select(AsDocument).ToArray(); var bulk = new BulkDescriptor(_options.IndexName).CreateMany(documents).Refresh(Refresh.WaitFor); var result = await _client.BulkAsync(bulk, cancellationToken); return(result.IsValid ? new AppendEventsResult(0, documents.Last().StreamPosition + 1) : throw new ApplicationException($"Unable to add events: {result.DebugInformation}")); PersistedEvent AsDocument(StreamEvent evt) => new( evt.Id.ToString(), TypeMap.Instance.GetTypeName(evt.Payload !), evt.Position + 1, evt.ContentType, streamName, (ulong)evt.Position + 1, evt.Payload, evt.Metadata.ToHeaders(), DateTime.Now ); }
public Task TruncateStream( StreamName stream, StreamTruncatePosition truncatePosition, ExpectedStreamVersion expectedVersion, CancellationToken cancellationToken ) { var meta = new StreamMetadata(truncateBefore: truncatePosition.AsStreamPosition()); return(TryExecute( () => AnyOrNot( expectedVersion, () => _client.SetStreamMetadataAsync( stream, StreamState.Any, meta, cancellationToken: cancellationToken ), () => _client.SetStreamMetadataAsync( stream, expectedVersion.AsStreamRevision(), meta, cancellationToken: cancellationToken ) ), stream, () => new ErrorInfo( "Unable to truncate stream {Stream} at {Position}", stream, truncatePosition ), (s, ex) => new TruncateStreamException(s, ex) )); }
public async Task Store <T>(T aggregate) where T : Aggregate { Ensure.NotNull(aggregate, nameof(aggregate)); if (aggregate.Changes.Count == 0) { return; } var stream = StreamName.For <T>(aggregate.GetId()); var expectedVersion = new ExpectedStreamVersion(aggregate.OriginalVersion); await _eventStore.AppendEvents(stream, expectedVersion, aggregate.Changes.Select(ToStreamEvent).ToArray()); StreamEvent ToStreamEvent(object evt) => new(TypeMap.GetTypeName(evt), _serializer.Serialize(evt), null, _serializer.ContentType); }
public static async Task <AppendEventsResult> Store <T>( this IEventWriter eventWriter, StreamName streamName, T aggregate, Func <StreamEvent, StreamEvent> amendEvent, CancellationToken cancellationToken ) where T : Aggregate { Ensure.NotNull(aggregate); if (aggregate.Changes.Count == 0) { return(AppendEventsResult.NoOp); } var originalVersion = aggregate.OriginalVersion; var expectedVersion = new ExpectedStreamVersion(originalVersion); try { var result = await eventWriter.AppendEvents( streamName, expectedVersion, aggregate.Changes.Select((o, i) => ToStreamEvent(o, i + originalVersion)).ToArray(), cancellationToken ) .NoContext(); return(result); } catch (Exception e) { Log.UnableToStoreAggregate(aggregate, e); throw e.InnerException?.Message.Contains("WrongExpectedVersion") == true ? new OptimisticConcurrencyException <T>(aggregate, e) : e; } StreamEvent ToStreamEvent(object evt, int position) { var streamEvent = new StreamEvent(Guid.NewGuid(), evt, new Metadata(), "", position); return(amendEvent(streamEvent)); } }
public async Task Store <T>(T aggregate) where T : Aggregate { if (aggregate == null) { throw new ArgumentNullException(nameof(aggregate)); } if (aggregate.Changes.Count == 0) { return; } var stream = StreamName.For <T>(aggregate.GetId()); var expectedVersion = new ExpectedStreamVersion(aggregate.Version); await _eventStore.AppendEvents(stream, expectedVersion, aggregate.Changes.Select(ToStreamEvent).ToArray()); JsonStreamEvent ToStreamEvent(object evt) => new(TypeMap.GetTypeName(evt), _serializer.Serialize(evt)); }
public Task DeleteStream( StreamName stream, ExpectedStreamVersion expectedVersion, CancellationToken cancellationToken ) => TryExecute( () => AnyOrNot( expectedVersion, () => _client.DeleteAsync( stream, StreamState.Any, cancellationToken: cancellationToken ), () => _client.DeleteAsync( stream, expectedVersion.AsStreamRevision(), cancellationToken: cancellationToken ) ), stream, () => new ErrorInfo("Unable to delete stream {Stream}", stream), (s, ex) => new DeleteStreamException(s, ex) );
public static StreamRevision AsStreamRevision(this ExpectedStreamVersion version) => StreamRevision.FromInt64(version.Value);
public Task <AppendEventsResult> AppendEvents( StreamName stream, ExpectedStreamVersion expectedVersion, IReadOnlyCollection <StreamEvent> events, CancellationToken cancellationToken ) { var proposedEvents = events.Select(ToEventData); var resultTask = expectedVersion == ExpectedStreamVersion.NoStream ? _client.AppendToStreamAsync( stream, StreamState.NoStream, proposedEvents, cancellationToken: cancellationToken ) : AnyOrNot( expectedVersion, () => _client.AppendToStreamAsync( stream, StreamState.Any, proposedEvents, cancellationToken: cancellationToken ), () => _client.AppendToStreamAsync( stream, expectedVersion.AsStreamRevision(), proposedEvents, cancellationToken: cancellationToken ) ); return(TryExecute( async() => { var result = await resultTask.NoContext(); return new AppendEventsResult( result.LogPosition.CommitPosition, result.NextExpectedStreamRevision.ToInt64() ); }, stream, () => new ErrorInfo("Unable to appends events to {Stream}", stream), (s, ex) => { EventuousEventSource.Log.UnableToAppendEvents(stream, ex); return new AppendToStreamException(s, ex); } )); EventData ToEventData(StreamEvent streamEvent) { var(eventType, contentType, payload) = _serializer.SerializeEvent(streamEvent.Payload !); return(new EventData( Uuid.FromGuid(streamEvent.Id), eventType, payload, _metaSerializer.Serialize(streamEvent.Metadata), contentType )); } }
static Task <T> AnyOrNot <T>( ExpectedStreamVersion version, Func <Task <T> > whenAny, Func <Task <T> > otherwise ) => version == ExpectedStreamVersion.Any ? whenAny() : otherwise();
public Task <AppendEventsResult> AppendEvents( StreamName stream, ExpectedStreamVersion expectedVersion, IReadOnlyCollection <StreamEvent> events, CancellationToken cancellationToken ) => default !;
public Task DeleteStream( StreamName stream, ExpectedStreamVersion expectedVersion, CancellationToken cancellationToken ) => default !;
public Task TruncateStream( StreamName stream, StreamTruncatePosition truncatePosition, ExpectedStreamVersion expectedVersion, CancellationToken cancellationToken ) => default !;