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;
 }
示例#4
0
        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;
 }
示例#6
0
                        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;
     });
 }
示例#10
0
        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);
 }
示例#12
0
        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);
        }
示例#13
0
        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);
        }
示例#14
0
    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);
                }
            }
示例#16
0
        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);
        }
示例#17
0
 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
         );
 }
示例#18
0
        /// <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;
        }
示例#20
0
        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);
        }
示例#21
0
        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);
        }
示例#23
0
        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());
        }
示例#24
0
        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();
示例#25
0
        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);
        }
示例#26
0
        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)));
        }
示例#29
0
        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);
            }
        }
示例#30
0
        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);
        }