public void SubtractionOperator() { var sut = new StreamRevision(1); Assert.AreEqual(new StreamRevision(0), sut - 1); Assert.AreEqual(new StreamRevision(0), 1 - sut); }
public void ImplicitConversionExpectedResult() { const ulong expected = 0UL; ulong actual = new StreamRevision(expected); Assert.AreEqual(expected, actual); }
public StreamMessageResource(string streamId, StreamRevision streamRevision, ResolvedEvent resolvedEvent = default) { StreamId = streamId; StreamRevision = streamRevision; Event = resolvedEvent; }
public async Task <ulong> TerminateAsync(Guid eventID, string eventName, string streamName, ulong?expectedEventNumber, EventStoreState expectedState) { var eventData = new EventData(Uuid.FromGuid(eventID), "Delete", null, null); if (expectedEventNumber.HasValue) { var revision = new StreamRevision(expectedEventNumber.Value); var writeResult = await client.AppendToStreamAsync(streamName, revision, new EventData[] { eventData }); await client.TombstoneAsync(streamName, revision); return(writeResult.NextExpectedStreamRevision); } else { StreamState state; switch (expectedState) { case EventStoreState.Any: state = StreamState.Any; break; case EventStoreState.NotExisting: state = StreamState.NoStream; break; case EventStoreState.Existing: state = StreamState.StreamExists; break; default: throw new NotImplementedException(); } var writeResult = await client.AppendToStreamAsync(streamName, state, new EventData[] { eventData }); await client.TombstoneAsync(streamName, state); return(writeResult.NextExpectedStreamRevision); } }
public WrongExpectedVersionResult(string streamName, StreamRevision nextExpectedStreamRevision) { StreamName = streamName; ActualVersion = NextExpectedVersion = nextExpectedStreamRevision.ToInt64(); ActualStreamRevision = NextExpectedStreamRevision = nextExpectedStreamRevision; LogPosition = default; }
public static StreamOptions FromStreamNameAndRevision( string streamName, StreamRevision streamRevision) { if (streamName == null) { throw new ArgumentNullException(nameof(streamName)); } if (streamRevision == StreamRevision.End) { return(new StreamOptions { StreamName = streamName, End = new Empty() }); } if (streamRevision == StreamRevision.Start) { return(new StreamOptions { StreamName = streamName, Start = new Empty() }); } return(new StreamOptions { StreamName = streamName, Revision = streamRevision }); }
public async Task StreamRevisionWorksSameForTcpAndHttp() { EventStoreFacade f = ConnectEs(); Guid g = Guid.NewGuid(); string sm = $"test-{g}"; List <ResolvedEvent> events_1 = new List <ResolvedEvent>(); List <ResolvedEvent> events_2 = new List <ResolvedEvent>(); StreamRevision sr = new StreamRevision(1); await f.AppendToStreamAsync(sm, AnyStreamRevision.Any, TestEvents(new RoomAdded(), new RoomAdded())); await foreach (var i in f.ReadStreamAsync(Direction.Forwards, sm, StreamRevision.Start, 2)) { events_1.Add(i); } f.IsTcp = !f.IsTcp; await foreach (var i in f.ReadStreamAsync(Direction.Forwards, sm, StreamRevision.Start, 2)) { events_2.Add(i); } for (int i = 0; i < 2; i++) { var e1 = events_1[i]; var e2 = events_2[i]; e1.OriginalEventNumber.Should().Be(e2.OriginalEventNumber); } }
public void SubtractionOutOfBoundsThrows(StreamRevision streamRevision, ulong operand) { Assert.Throws <OverflowException>(() => { var _ = streamRevision - operand; }); Assert.Throws <OverflowException>(() => { var _ = (ulong)streamRevision - new StreamRevision(operand); }); }
public void AdditionOutOfBoundsThrows(StreamRevision streamRevision, ulong operand) { Assert.Throws <OverflowException>(() => { var _ = streamRevision + operand; }); Assert.Throws <OverflowException>(() => { var _ = operand + streamRevision; }); }
private static IEnumerable <Link> GetStreamMessageLinks(ResolvedEvent resolvedEvent) { var @event = resolvedEvent.OriginalEvent; var self = LinkFormatter.StreamMessageByStreamVersion(@event.EventStreamId, StreamRevision.FromStreamPosition(@event.EventNumber)); yield return(new Link(Constants.Relations.Message, self)); yield return(new Link(Constants.Relations.Self, self)); yield return(new Link(Constants.Relations.Self, LinkFormatter.Stream(@event.EventStreamId))); }
public StreamResource(string streamId, Direction readDirection, StreamRevision fromStreamRevisionInclusive, long maxCount, bool embedPayload, IReadOnlyList <ResolvedEvent>?events = null) { StreamId = streamId; EmbedPayload = embedPayload; ReadDirection = readDirection; FromStreamRevisionInclusive = fromStreamRevisionInclusive; MaxCount = maxCount; Events = events ?? Array.Empty <ResolvedEvent>(); Self = LinkFormatter.ReadStream(StreamId, FromStreamRevisionInclusive, MaxCount, EmbedPayload, ReadDirection); }
public async Task soft_deleting_a_stream_should_return_log_position() { var stream = _fixture.GetStreamName(); var writeResult = await _fixture.Client.AppendToStreamAsync( stream, AnyStreamRevision.NoStream, _fixture.CreateTestEvents()); var deleteResult = await _fixture.Client.SoftDeleteAsync(stream, StreamRevision.FromInt64(writeResult.NextExpectedVersion)); Assert.True(deleteResult.LogPosition > writeResult.LogPosition); }
public static bool TryParseStreamRevision(this StringValues value, out StreamRevision streamRevision) { streamRevision = default; if (!ulong.TryParse(value.ToString(), out var x)) { return(false); } streamRevision = new StreamRevision(x); return(true); }
public Task SaveAsync(IAggregateRoot aggregateRoot, CancellationToken ct) { var events = aggregateRoot .GetEvents() .Select(ToEventData); return(_eventStore.AppendToStreamAsync( StreamName(aggregateRoot.GetType(), aggregateRoot.Id), StreamRevision.FromInt64(aggregateRoot.Version), events, cancellationToken: ct )); }
protected override async Task When() { var enumerator = new Enumerators.ReadStreamForwards(_node.Node.MainQueue, _streamName, StreamRevision.FromInt64(11), _maxCount, false, CreateTestUser(), false, DateTime.Now.AddMinutes(5), e => { Assert.Fail($"Failed to read: {e}"); return(Task.CompletedTask); }, CancellationToken.None); while (await enumerator.MoveNextAsync().ConfigureAwait(false)) { _responses.Add(enumerator.Current); } }
public async Task <ISubscription> Subscribe(IEventHandlerFactory factory, object[] args = null) { if (!factory.SupportedEventTypes.Contains <TEvent>()) { throw new InvalidOperationException( $"Event Handler Factory seems not to support this Event. {typeof(TEvent).Name}"); } // uhhh and we need to know from when... Type checkpointRepo = typeof(ICheckpointRepository <,>).MakeGenericType(_schema.Type, typeof(TEvent)); var repo = (ICheckpointEventRepository <TEvent>)_serviceProvider.GetService(checkpointRepo); string streamName = $"$et-{typeof(TEvent).Name}"; var lastCheckpoint = await repo.GetLastCheckpoint(); StreamRevision start = StreamRevision.Start; if (!lastCheckpoint.HasValue) { // this is the first time we run this processor. var(globalPosition, streamRevision) = await _eventStore.GetLastStreamPosition(streamName); start = streamRevision; await repo.SaveCheckpoint(start.ToUInt64()); } else { start = new StreamRevision(lastCheckpoint.Value + 1); } Subscription s = new Subscription(); await _eventStore.SubscribeToStreamAsync(streamName, start, async (s, r, c) => { using (var scope = factory.Scope()) { var handler = scope.CreateHandler <TEvent>(); var(m, e) = _eventConverter.Convert <TEvent>(r); await handler.Execute(m, e); await repo.SaveCheckpoint(r.Link.EventNumber.ToUInt64()); } }, ss => s.MakeLive(), true); return(s); }
public static async Task Append( this EventStoreClient eventStore, string id, object @event, uint version, CancellationToken cancellationToken ) { await eventStore.AppendToStreamAsync( id, StreamRevision.FromInt64(version), new[] { @event.ToJsonEventData() }, cancellationToken : cancellationToken ); }
/// <summary> /// Inserts the events. /// </summary> /// <param name="streamName">Name of the stream.</param> /// <param name="expectedVersion">The expected version.</param> /// <param name="aggregateEvents">The aggregate events.</param> /// <param name="metadata">The metadata.</param> /// <param name="cancellationToken">The cancellation token.</param> public async Task InsertEvents(String streamName, Int64 expectedVersion, List <EventData> aggregateEvents, Object metadata, CancellationToken cancellationToken) { List <EventData> eventData = new List <EventData>(); JsonSerializerSettings s = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; this.LogInformation($"About to append {aggregateEvents.Count} to Stream {streamName}"); await this.EventStoreClient.AppendToStreamAsync(streamName, StreamRevision.FromInt64(expectedVersion), aggregateEvents.AsEnumerable(), cancellationToken : cancellationToken); }
private static async Task TestReadFromtombstoned(EventStoreClient client) { var idForTombstoneTest = Guid.NewGuid().ToString(); await client.AppendToStreamAsync(idForTombstoneTest, StreamRevision.FromInt64(-1), new[] { new EventData(Uuid.NewUuid(), "TestType", new byte[] { 0x00 }) }); await client.TombstoneAsync(idForTombstoneTest, StreamState.Any); var testResultNonExistent = client.ReadStreamAsync(Direction.Backwards, Guid.NewGuid().ToString(), StreamPosition.End); var testResult = client.ReadStreamAsync(Direction.Backwards, idForTombstoneTest, StreamPosition.End, configureOperationOptions: o => { o.ThrowOnAppendFailure = false; }); var testState = await testResultNonExistent.ReadState; testState = await testResult.ReadState; }
public async Task append_with_correct_expected_version_to_existing_stream() { var stream = _fixture.GetStreamName(); var writeResult = await _fixture.Client.AppendToStreamAsync( stream, AnyStreamRevision.NoStream, _fixture.CreateTestEvents(1)); writeResult = await _fixture.Client.AppendToStreamAsync( stream, StreamRevision.FromInt64(writeResult.NextExpectedVersion), _fixture.CreateTestEvents()); Assert.Equal(1, writeResult.NextExpectedVersion); }
private static IEnumerable <Link> LinksForInternal(StreamResource resource) { yield return(new Link(Constants.Relations.Index, "./")); yield return(new Link(Constants.Relations.Find, LinkFormatter.FindStreamTemplate())); yield return(new Link(Constants.Relations.Browse, LinkFormatter.BrowseStreamsTemplate())); yield return(new Link(Constants.Relations.Self, resource.Self)); var first = LinkFormatter.ReadStream(resource.StreamId, StreamRevision.FromStreamPosition(StreamPosition.Start), resource.MaxCount, resource.EmbedPayload, Direction.Forwards); var last = LinkFormatter.ReadStream(resource.StreamId, StreamRevision.FromStreamPosition(StreamPosition.End), resource.MaxCount, resource.EmbedPayload, Direction.Backwards); yield return(new Link(Constants.Relations.First, first)); if (resource.Events.Count > 0) { var minStreamRevision = resource.Events.Min(x => x.OriginalEvent.EventNumber); if (minStreamRevision != StreamRevision.FromStreamPosition(StreamPosition.Start)) { yield return(new Link(Constants.Relations.Previous, LinkFormatter.ReadStream(resource.StreamId, StreamRevision.FromStreamPosition(minStreamRevision - 1), resource.MaxCount, resource.EmbedPayload, Direction.Backwards))); } } yield return(new Link(Constants.Relations.Feed, resource.Self)); if (resource.Events.Count > 0) { yield return(new Link(Constants.Relations.Next, LinkFormatter.ReadStream(resource.StreamId, StreamRevision.FromStreamPosition(resource.Events.Max(x => x.OriginalEvent.EventNumber).Next()), resource.MaxCount, resource.EmbedPayload, Direction.Forwards))); } yield return(new Link(Constants.Relations.Last, last)); yield return(new Link(Constants.Relations.Metadata, LinkFormatter.StreamMetadata(resource.StreamId))); }
public async Task SubscribeFromStart() { EventStoreFacade f = ConnectEs(); Guid g = Guid.NewGuid(); string sm = $"test-{g}"; List <ResolvedEvent> events = new List <ResolvedEvent>(); StreamRevision sr = new StreamRevision(0); await f.SubscribeToStreamAsync(sm, sr, async (s, r, c) => { events.Add(r); }, null, true); await f.AppendToStreamAsync(sm, AnyStreamRevision.Any, TestEvents(new RoomAdded())); await Task.Delay(1000); events.Should().HaveCount(1); }
public async Task reading_throws() { var stream = _fixture.GetStreamName(); var writeResult = await _fixture.Client.AppendToStreamAsync( stream, AnyStreamRevision.NoStream, _fixture.CreateTestEvents()); Assert.Equal(0, writeResult.NextExpectedVersion); await _fixture.Client.SoftDeleteAsync(stream, StreamRevision.FromInt64(writeResult.NextExpectedVersion)); await Assert.ThrowsAsync <StreamNotFoundException>( () => _fixture.Client.ReadStreamForwardsAsync(stream, StreamRevision.Start, int.MaxValue) .ToArrayAsync().AsTask()); }
public async Task Save <TAggregate>(TAggregate aggregate) where TAggregate : Aggregate { if (aggregate == null) { throw new ArgumentNullException(nameof(aggregate)); } var stream = GetStreamName <TAggregate>(aggregate.Id); var changes = aggregate.Changes.ToArray(); var events = changes.Select(CreateEventData); var resultTask = aggregate.Version < 0 ? _client.AppendToStreamAsync(stream, StreamState.NoStream, events) : _client.AppendToStreamAsync(stream, StreamRevision.FromInt64(aggregate.Version), events); var result = await resultTask; aggregate.ClearChanges();
public async Task AppendToStream(string streamName, long expectedVersion, IEnumerable <Event> events, string correlationId) { var eventData = events.Select(e => { var metadata = new Dictionary <string, string> { { "$correlationId", correlationId } }; var eventBytes = Encoding.UTF8.GetBytes(EventSerializer.Serialize(e)); var metadataBytes = Encoding.UTF8.GetBytes(EventSerializer.SerializeMetadata(metadata)); return(new EventData(Uuid.NewUuid(), e.GetType().Name, eventBytes, metadataBytes)); }); var expectedRevision = StreamRevision.FromInt64(expectedVersion); await _client.AppendToStreamAsync(streamName, expectedRevision, eventData); }
public override void Write(Utf8JsonWriter writer, ResolvedEvent value, JsonSerializerOptions options) { var @event = value.OriginalEvent; if (@event == null) { writer.WriteStartObject(); writer.WriteEndObject(); return; } writer.WriteStartObject(); writer.WritePropertyName("messageId"); options.GetConverter <Uuid>().Write(writer, @event.EventId, options); writer.WriteString("createdUtc", @event.Created); writer.WritePropertyName("position"); options.GetConverter <Position>().Write(writer, @event.Position, options); writer.WriteString("streamId", @event.EventStreamId); writer.WritePropertyName("streamVersion"); options.GetConverter <StreamRevision>() .Write(writer, StreamRevision.FromStreamPosition(@event.EventNumber), options); writer.WriteString("type", @event.EventType); writer.WritePropertyName("payload"); if (MediaTypeHeaderValue.TryParse(@event.ContentType, out var contentType) && contentType.SubType.EndsWith("json", StringComparison.Ordinal)) { var reader = new Utf8JsonReader(@event.Data.Span); if (JsonDocument.TryParseValue(ref reader, out var payload)) { payload.WriteTo(writer); } else { writer.WriteBase64StringValue(@event.Data.Span); } }
public async Task <ISubscription> Subscribe(IEventHandlerFactory factory, object[] args = null) { Subscription s = new Subscription(); if (!factory.SupportedEventTypes.Contains <TEvent>()) { throw new InvalidOperationException($"Event Handler Factory seems not to support this Event. {typeof(TEvent).Name}"); } // Projections stream type might not be the same as origin of the event. // For instance Stream might go directly to memory, where as some events // come from EventStore // In such a case, we could assume to subscribe from the beginning // or we could assume that we want to subscribe from now. // For now we subscribe from beginning - however this is a problem. // We don't know the nature of this subscription - if it is temporal or not. // If it had been temporal, we would subscribe from now // It it had not been temporal, we would subscribe from beginning var position = await Stream.LastPosition(); StreamRevision sr = StreamRevision.Start; if (position is StreamPosition lastPosition) { sr = lastPosition.IsStart ? StreamRevision.Start : new StreamRevision(lastPosition.StreamRevision + 1); } await _eventStore.SubscribeToStreamAsync(STREAM_NAME, sr, async (s, r, c) => { using (var scope = factory.Scope()) { var handler = scope.CreateHandler <TEvent>(); var(m, e) = _eventConverter.Convert <TEvent>(r); await handler.Execute(m, e); } }, ss => s.MakeLive(), true); return(s); }
private static IEnumerable <Link> GetStreamMessageLinks(StreamMessageResource resource) { var self = LinkFormatter.StreamMessageByStreamVersion(resource.StreamId, resource.StreamRevision); yield return(new Link(Constants.Relations.Message, self)); yield return(new Link(Constants.Relations.Self, self)); yield return(new Link(Constants.Relations.Self, LinkFormatter.Stream(resource.StreamId))); if (resource.StreamRevision > StreamRevision.FromStreamPosition(StreamPosition.Start)) { yield return(new Link(Constants.Relations.Previous, LinkFormatter.StreamMessageByStreamVersion(resource.StreamId, resource.StreamRevision - 1))); } yield return(new Link(Constants.Relations.Next, LinkFormatter.StreamMessageByStreamVersion(resource.StreamId, resource.StreamRevision + 1))); }
public async Task <IStreamSubscription> SubscribeToStreamAsync(string streamName, StreamRevision start, Func <IStreamSubscription, ResolvedEvent, CancellationToken, Task> eventAppeared, Action <IStreamSubscription> onLiveProcessingStarted, bool resolveLinkTos = false, Action <IStreamSubscription, SubscriptionDroppedReason, Exception> subscriptionDropped = null, Action <EventStoreClientOperationOptions> configureOperationOptions = null, UserCredentials userCredentials = null, CancellationToken cancellationToken = new CancellationToken()) { Log.Debug("SubscribeToStreamAsync {streamName} starting from revision.", streamName); if (onLiveProcessingStarted != null && _client == _tcpClient) { return(await _tcpClient.SubscribeToStreamAsync(streamName, start, eventAppeared, onLiveProcessingStarted, resolveLinkTos, subscriptionDropped, configureOperationOptions, DefaultCredentials ?? userCredentials, cancellationToken)); } else { var result = await _client.SubscribeToStreamAsync(streamName, start, eventAppeared, resolveLinkTos, subscriptionDropped, configureOperationOptions, DefaultCredentials ?? userCredentials, cancellationToken); onLiveProcessingStarted?.Invoke(result); return(result); } }
async Task IEventStore.SaveEventsAsync(string streamName, int expectedVersion, IEnumerable <LoadedEvent> changes) { var eventList = new List <EventData>(); foreach (var loadedEvent in changes) { if (!_eventsConverter.TryConvert(loadedEvent.Data, out var externalEvent)) { throw new InvalidOperationException($"Cannot convert event {loadedEvent.Data.GetType().Name}"); } eventList.Add(new EventData( Uuid.NewUuid(), externalEvent.GetType().Name, JsonSerializer.SerializeToUtf8Bytes(externalEvent, externalEvent.GetType()), null)); } var streamRevision = expectedVersion == 0 ? StreamRevision.None : StreamRevision.FromInt64(expectedVersion - 1); var result = await _client.AppendToStreamAsync(streamName, streamRevision, eventList); }