Пример #1
0
        public async Task <StreamResponse> WriteAsync(
            StreamId streamId,
            IReadOnlyCollection <object> events,
            StreamVersion version,
            StreamWriteOptions?options,
            CancellationToken cancellationToken)
        {
            var metadata = await metadataReader
                           .GetAsync(streamId, cancellationToken)
                           .ConfigureAwait(false);

            validator.Validate(metadata, version);

            var batch = batchProducer
                        .FromEvents(events, metadata, options);

            var response = await batchWriter
                           .WriteAsync(batch, cancellationToken)
                           .ConfigureAwait(false);

            return(new StreamResponse(
                       response.StreamId,
                       response.Version,
                       response.Timestamp,
                       response.State));
        }
 public void Validate(IStreamMetadata metadata, StreamVersion version)
 {
     if (metadata.State == StreamState.Closed)
     {
         throw new StreamClosedException(metadata.StreamId);
     }
 }
Пример #3
0
 public void Should_Be_GreatherThan_Using_CompareTo(
     [Frozen] long version,
     StreamVersion sut)
 => sut
 .CompareTo(version + 1)
 .Should()
 .Be(-1);
Пример #4
0
        public async Task RememberConsumedStreamVersionAsync_WhenSkipCurrentFlagIsTrue_CommitsOnlyProcessedEvents(
            [Frozen] StreamVersion version,
            [Frozen] CommitStreamVersionFMock commitStreamVersionMock,
            [Frozen] Mock <IEventStreamReader> readerMock,
            [Frozen] JournaledEvent[] events,
            EventStreamConsumer consumer)
        {
            var streamVersion = version.Increment(events.Length);

            readerMock
            .Setup(self => self.StreamVersion)
            .Returns(streamVersion);

            await consumer.ReceiveEventsAsync();

            var handledEvents = 0;

            foreach (var e in consumer.EnumerateEvents())
            {
                handledEvents++;
                await consumer.CommitProcessedStreamVersionAsync(skipCurrent : true);
            }

            Assert.Equal(handledEvents - 1, commitStreamVersionMock.CallsCount);
            Assert.Equal(streamVersion.Decrement(), commitStreamVersionMock.CommitedVersion);
        }
Пример #5
0
        public async Task RememberConsumedStreamVersionAsync_WhenLatestManuallyCommitedVersionEqualsToStreamCurrent_SkipCommitOnReceiveAsync(
            [Frozen] StreamVersion version,
            [Frozen] CommitStreamVersionFMock commitStreamVersionMock,
            [Frozen] Mock <IEventStreamReader> readerMock,
            [Frozen] JournaledEvent[] events,
            EventStreamConsumer consumer)
        {
            var streamVersion = version.Increment(events.Length);

            readerMock
            .Setup(self => self.StreamVersion)
            .Returns(streamVersion);

            await consumer.ReceiveEventsAsync();

            var handledEvents = 0;

            foreach (var e in consumer.EnumerateEvents())
            {
                handledEvents++;
                await consumer.CommitProcessedStreamVersionAsync();
            }

            await consumer.ReceiveEventsAsync();

            Assert.Equal(handledEvents, commitStreamVersionMock.CallsCount);
            Assert.Equal(streamVersion, commitStreamVersionMock.CommitedVersion);
        }
Пример #6
0
 public void Should_Be_EqualTo_Using_CompareTo(
     [Frozen] long version,
     StreamVersion sut)
 => sut
 .CompareTo(version)
 .Should()
 .Be(0);
Пример #7
0
        public async Task CommitStreamReaderPositionAsync(
            string streamName,
            EventStreamReaderId readerId,
            StreamVersion readerVersion)
        {
            Require.NotEmpty(streamName, "streamName");
            Require.NotNull(readerId, "readerId");

            var properties = await m_table.ReadStreamReaderPropertiesAsync(streamName, readerId);

            if (properties == null)
            {
                await m_table.InserStreamReaderPropertiesAsync(
                    streamName,
                    readerId,
                    readerVersion);
            }
            else
            {
                var readerVersionValue = (int)readerVersion;
                var savedVersionValue  = (int)properties[EventJournalTableRowPropertyNames.Version];
                var etag = (string)properties[KnownProperties.ETag];
                Ensure.True(savedVersionValue <= readerVersionValue,
                            "Saved reader stream version is greater then passed value.");

                if (readerVersionValue != savedVersionValue)
                {
                    await m_table.UpdateStreamReaderPropertiesAsync(streamName, readerId, readerVersion, etag);
                }
            }
        }
Пример #8
0
 public void Should_Be_LessThan_Using_CompareTo(
     [Frozen] long version,
     StreamVersion sut)
 => sut
 .CompareTo(version - 1)
 .Should()
 .Be(1);
Пример #9
0
 public void Can_Get_Version_As_Long_FromStreamVersion(
     [Frozen] long version,
     StreamVersion sut)
 => StreamVersion
 .FromStreamVersion(sut)
 .Should()
 .Be(version);
Пример #10
0
 public void Should_Be_Equal_When_InnerVersion_Has_The_Same_Value(
     [Frozen] long version,
     StreamVersion left,
     StreamVersion right)
 => (left == right)
 .Should()
 .BeTrue();
Пример #11
0
        protected override async Task <EventProcessingResult> TryProcessEventFromConsumerAsync(
            IEventStreamConsumer consumer,
            StreamVersion notificationStreamVersion)
        {
            foreach (var journaledEvent in consumer.EnumerateEvents())
            {
                var failed = false;
                try
                {
                    await ProcessEventAsync(journaledEvent);
                }
                catch (Exception exception)
                {
                    ListenerLogger.Error(
                        exception,
                        "Processing event {EventId} of type {EventType} from stream {Stream} failed.",
                        journaledEvent.EventId,
                        journaledEvent.EventTypeName,
                        consumer.StreamName);

                    failed = true;
                }

                if (failed)
                {
                    await consumer.CommitProcessedStreamVersionAsync(skipCurrent : true);

                    return(new EventProcessingResult(false, false));
                }
            }

            return(new EventProcessingResult(true, true));
        }
Пример #12
0
        public async IAsyncEnumerable <IEvent> ReadAsync(
            StreamId streamId,
            StreamVersion fromVersion,
            StreamReadFilter?filter,
            [EnumeratorCancellation] CancellationToken cancellationToken)
        {
            var metadata = await metadataReader
                           .GetAsync(streamId, cancellationToken)
                           .ConfigureAwait(false);

            readValidator.Validate(
                metadata,
                filter?.RequiredVersion ?? StreamVersion.Any);

            // If we don't have any events in the stream, then skip reading from stream.
            if (metadata.Version == 0)
            {
                yield break;
            }

            await foreach (var evt in streamIterator
                           .ReadAsync(streamId, fromVersion, filter, cancellationToken)
                           .ConfigureAwait(false))
            {
                yield return(evt);
            }
        }
        public Task Invoke(StreamVersion version)
        {
            CallsCount++;
            CommitedVersion = version;

            return(TaskDone.Done);
        }
        public Task Invoke(StreamVersion version)
        {
            CallsCount++;
            CommitedVersion = version;

            return TaskDone.Done;
        }
Пример #15
0
        public async Task DeleteAsync(string streamName, StreamVersion streamVersion)
        {
            Require.NotEmpty(streamName, "streamName");

            try
            {
                var operation = m_table.PrepareBatchOperation();

                operation.Delete(
                    partitionKey: GetPartitionKey(streamName),
                    rowKey: GetRowKey(streamName, streamVersion),
                    etag: "*");

                await operation.ExecuteAsync();
            }
            catch (BatchOperationException exception)
            {
                if (exception.HttpStatusCode != HttpStatusCode.NotFound)
                {
                    throw;
                }

                s_logger.Debug(exception, "Stream {SteamName} version {Version} pending notification record has been deleted.", streamName, streamVersion);
            }
        }
Пример #16
0
        public async Task <IDictionary <string, List <EventStreamUpdated> > > LoadAsync()
        {
            var result      = new Dictionary <string, List <EventStreamUpdated> >();
            var query       = m_table.PrepareEntityGetAllQuery();
            var queryResult = await query.ExecuteAsync();

            foreach (var row in queryResult)
            {
                var rowKey      = (string)row[KnownProperties.RowKey];
                var rowKeyParts = rowKey.Split('|');
                var streamName  = rowKeyParts[0];
                var fromVersion = StreamVersion.Parse(rowKeyParts[1]);
                var toVersion   = StreamVersion.Create((int)row["ToVersion"]);

                List <EventStreamUpdated> streamNotifications;
                if (result.ContainsKey(streamName))
                {
                    streamNotifications = result[streamName];
                }
                else
                {
                    streamNotifications = new List <EventStreamUpdated>();
                    result[streamName]  = streamNotifications;
                }

                streamNotifications.Add(new EventStreamUpdated(streamName, fromVersion, toVersion));
            }

            return(result);
        }
Пример #17
0
        public EventStreamHeader(string etag, StreamVersion version)
        {
            Require.NotNull(etag, "etag");

            m_etag    = etag;
            m_version = version;
        }
Пример #18
0
 public void Should_Be_Constructed_With_Version(
     [Frozen] long version,
     StreamVersion sut)
 => sut
 .Value
 .Should()
 .Be(version);
Пример #19
0
        public InitialCursorState(EventStreamHeader streamHeader, StreamVersion fromVersion, FetchEvents fetch)
            : base(streamHeader)
        {
            Require.NotNull(fetch, "fetch");

            m_version = fromVersion;
            m_fetch   = fetch;
        }
Пример #20
0
        public async Task CreatedWriter_AppendsEventsAndMovesPositionForward(JournaledEvent[] dummyEvents)
        {
            var writer = await Connection.CreateStreamWriterAsync(StreamName);

            await writer.AppendEventsAsync(dummyEvents);

            Assert.Equal(StreamVersion.Create(dummyEvents.Length), writer.StreamVersion);
        }
Пример #21
0
        private EventStreamCursor(EventStreamHeader streamHeader, StreamVersion fromVersion, FetchEvents fetch)
        {
            Require.NotNull(fetch, "fetch");

            m_state = new InitialCursorState(streamHeader, fromVersion, fetch);
            m_slice = EventStreamSlice.Empty;
            m_cursorStreamVersion = fromVersion;
        }
Пример #22
0
        public EventStreamUpdated(string streamName, StreamVersion fromVersion, StreamVersion toVersion)
        {
            Require.NotEmpty(streamName, "streamName");

            StreamName  = streamName;
            FromVersion = fromVersion;
            ToVersion   = toVersion;
        }
Пример #23
0
        public void TwoHeadersWithDifferentVersionValue_AreNotSame(string etag, StreamVersion version1, StreamVersion version2)
        {
            var header1 = new EventStreamHeader(etag, version1);
            var header2 = new EventStreamHeader(etag, version2);

            Assert.NotEqual(header1, header2);
            Assert.False(header1 == header2);
        }
Пример #24
0
        public void Increment_IncreasesVersionByOne(int versionValue)
        {
            var expectedVersion = StreamVersion.Create(versionValue + 1);
            var version         = StreamVersion.Create(versionValue);

            var incrementedVersion = version.Increment();

            Assert.Equal(expectedVersion, incrementedVersion);
        }
Пример #25
0
        public FetchingCursorState(
            EventStreamHeader streamHeader,
            StreamVersion sliceSteamVersion,
            FetchEvents fetch) : base(streamHeader)
        {
            Require.NotNull(fetch, "fetch");

            m_sliceSteamVersion = sliceSteamVersion;
            m_fetch             = fetch;
        }
Пример #26
0
        public ConsumerDescription(StreamVersion streamVersion, string consumerName, EventStreamReaderId consumerId)
        {
            Require.NotNull(streamVersion, nameof(streamVersion));
            Require.NotEmpty(consumerName, nameof(consumerName));
            Require.NotNull(consumerId, nameof(consumerId));

            StreamVersion = streamVersion;
            ConsumerName  = consumerName;
            ConsumerId    = consumerId;
        }
Пример #27
0
        public StreamReaderDescription(string streamName, EventStreamReaderId streamReaderId, StreamVersion streamVersion)
        {
            Require.NotEmpty(streamName, nameof(streamName));
            Require.NotNull(streamReaderId, nameof(streamReaderId));
            Require.NotNull(streamVersion, nameof(streamVersion));

            StreamName     = streamName;
            StreamReaderId = streamReaderId;
            StreamVersion  = streamVersion;
        }
Пример #28
0
        public async Task AppendEventsAsync_WriteEventsToEndOfStream(string streamName)
        {
            // arrange
            var position = EventStreamHeader.Unknown;

            // act
            position = await AppendEventsAsync(streamName, batchNumber : 3);

            // assert
            Assert.Equal(StreamVersion.Create(30), position.Version);
        }
Пример #29
0
        public async Task<IEventStreamReader> CreateStreamReaderAsync(string streamName, StreamVersion streamVersion)
        {
            Require.NotEmpty(streamName, "streamName");

            var reader = new EventStreamReader(
                streamName,
                await m_journal.OpenEventStreamCursorAsync(streamName, streamVersion),
                version => m_journal.OpenEventStreamCursorAsync(streamName, version));

            return reader;
        }
Пример #30
0
        public async Task<IEventStreamCursor> OpenEventStreamCursorAsync(string streamName, StreamVersion fromVersion, int sliceSize)
        {
            Require.NotEmpty(streamName, "streamName");
            Require.Positive(sliceSize, "sliceSize");

            var position = await ReadEndOfStreamPositionAsync(streamName);
            return new EventStreamCursor(
                position,
                fromVersion,
                from => FetchEvents(streamName, from, position.Version, sliceSize));
        }
Пример #31
0
        public static Task <IEventStreamCursor> OpenEventStreamCursorAsync(
            this IEventJournal journal,
            string streamName,
            StreamVersion fromVersion)
        {
            Require.NotNull(journal, "journal");

            return(journal.OpenEventStreamCursorAsync(
                       streamName,
                       fromVersion,
                       Constants.Settings.EVENT_SLICE_SIZE));
        }
Пример #32
0
        public async Task <IEnumerable <StreamReaderDescription> > GetStreamReadersDescriptionsAsync(string streamName)
        {
            Require.NotEmpty(streamName, nameof(streamName));

            var streamReadersProperties = await m_table.ReadAllStreamReadersPropertiesAsync(streamName);

            var descriptions = streamReadersProperties.Select(streamReaderProperties => new StreamReaderDescription(
                                                                  streamName,
                                                                  EventStreamReaderId.Parse(streamReaderProperties[KnownProperties.RowKey].ToString().Split('|').Last()),
                                                                  StreamVersion.Create((int)streamReaderProperties[EventJournalTableRowPropertyNames.Version])));

            return(descriptions);
        }
Пример #33
0
        public async Task Execute_ReturnsHeaderWithIncrementedVersion(
            [Frozen] StreamVersion currentVersion,
            JournaledEvent[] events,
            AppendOperation operation)
        {
            var targetVersion = currentVersion.Increment(events.Count());

            operation.Prepare(events);

            var result = await operation.ExecuteAsync();

            Assert.Equal(targetVersion, result.Version);
        }
Пример #34
0
        public EventStreamCursor(EventStreamPosition position, StreamVersion fromVersion, FetchEvents fetch)
        {
            Require.NotNull(fetch, "fetch");

            if (EventStreamPosition.IsNewStream(position))
            {
                m_state = new EndOfStreamCursorState();
                m_slice = EventStreamSlice.Empty;
            }
            else
            {
                m_state = new InitialCursorState(position, fromVersion, fetch);
            }
        }
Пример #35
0
        public EventStreamConsumer(
            string consumerName,
            IEventStreamReader streamReader,
            IEventStreamConsumingSession session,
            StreamVersion commitedStreamVersion,
            Func<StreamVersion, Task> commitConsumedVersion)
        {
            Require.NotEmpty(consumerName, "consumerName");
            Require.NotNull(streamReader, "streamReader");
            Require.NotNull(session, "session");
            Require.NotNull(commitConsumedVersion, "commitConsumedVersion");

            m_consumerName = consumerName;
            m_reader = streamReader;
            m_session = session;
            m_commitConsumedVersion = commitConsumedVersion;
            m_commitedStreamVersion = commitedStreamVersion;
        }
Пример #36
0
        public async Task<bool> ReceiveEventsAsync()
        {
            AssertConsumerWasNotClosed();
            AssertConsumerIsNotInConsumingState();

            if (!(await m_session.PromoteToLeaderAsync()))
            {
                return false;
            }

            if (m_receiving && m_commitedStreamVersion != m_reader.CurrentStreamVersion)
            {
                await m_commitConsumedVersion(m_reader.CurrentStreamVersion);
                m_commitedStreamVersion = m_reader.CurrentStreamVersion;
                m_eventSliceOffset = 0;
            }

            if (m_reader.IsCompleted)
            {
                await m_reader.ContinueAsync();
                m_receiving = false;
            }

            if (m_reader.HasEvents)
            {
                await m_reader.ReadEventsAsync();

                m_hasUnprocessedEvents = true;
                m_receiving = true;

                return true;
            }

            await m_session.FreeAsync();
            m_receiving = false;

            return false;
        }
Пример #37
0
        public async Task CommitStreamReaderPositionAsync(
            string streamName,
            string readerName,
            StreamVersion readerVersion)
        {
            Require.NotEmpty(streamName, "streamName");
            Require.NotEmpty(readerName, "readerName");

            var referenceRow = await ReadReferenceRowHeadAsync(
                streamName,
                "RDR_" + readerName);

            var operation = m_table.PrepareBatchOperation();
            if (referenceRow == null)
            {
                operation.Insert(
                    streamName,
                    "RDR_" + readerName,
                    new Dictionary<string, object>
                    {
                        { EventJournalTableRowPropertyNames.Version, (int)readerVersion }
                    });
            }
            else
            {
                operation.Merge(
                    streamName,
                    "RDR_" + readerName,
                    (string)referenceRow[KnownProperties.ETag],
                    new Dictionary<string, object>
                    {
                        { EventJournalTableRowPropertyNames.Version, (int)readerVersion }
                    });
            }

            await operation.ExecuteAsync();
        }
Пример #38
0
        private async Task<SortedList<StreamVersion, JournaledEvent>> FetchEvents(
            string stream,
            StreamVersion fromVersion,
            StreamVersion toVersion,
            int sliceSize)
        {
            var nextSliceVersion = fromVersion.Increment(sliceSize);
            if (nextSliceVersion >= toVersion)
            {
                nextSliceVersion = toVersion;
            }

            var query = m_table.PrepareEntityFilterRangeQuery(
                "(PartitionKey eq '{0}') and (RowKey ge '{1}' and RowKey le '{2}')".FormatString(
                    stream,
                    fromVersion.ToString(),
                    nextSliceVersion.ToString()), JournaledEventPropertyNames.All);

            var queryResult = await query.ExecuteAsync();

            var result = new SortedList<StreamVersion, JournaledEvent>(sliceSize);
            foreach (var properties in queryResult)
            {
                result.Add(StreamVersion.Parse((string)properties[KnownProperties.RowKey]), JournaledEvent.Create(properties));
            }

            return result;
        }
Пример #39
0
        private async Task<List<JournaledEvent>> ReadEventsPartialAsync(StreamVersion fromVersion,
            StreamVersion toVersion, int sliceSize = 1000)
        {
            var stream = await Journal.OpenEventStreamCursorAsync(StreamName, fromVersion, toVersion, sliceSize);

            var result = new List<JournaledEvent>();
            while (!stream.EndOfStream)
            {
                await stream.FetchSlice();
                result.AddRange(stream.Slice);
            }

            return result;
        }
Пример #40
0
        private static void WriteEvents(string stream, StreamVersion version, IEnumerable<JournaledEvent> events, IBatchOperation batch)
        {
            var currentVersion = version;
            foreach (var journaledEvent in events)
            {
                currentVersion = currentVersion.Increment(1);

                // InsertOrReplace is faster then Insert operation, because storage engine
                // can skip etag checking.
                batch.InsertOrReplace(stream, currentVersion.ToString(), journaledEvent.ToDictionary());
            }
        }
Пример #41
0
        public async Task<IEventStreamCursor> OpenEventStreamCursorAsync(
            string streamName,
            StreamVersion fromVersion,
            StreamVersion toVersion,
            int sliceSize)
        {
            Require.NotEmpty(streamName, "streamName");
            Require.Positive(sliceSize, "sliceSize");

            var headProperties = await ReadHeadAsync(streamName);
            if (headProperties == null)
            {
                return EventStreamCursor.Empty;
            }

            return new EventStreamCursor(
                new EventStreamPosition(string.Empty, toVersion),
                fromVersion,
                from => FetchEvents(streamName, from, toVersion, sliceSize));
        }
Пример #42
0
        public async Task CommitProcessedStreamVersionAsync(bool skipCurrent)
        {
            AssertConsumerWasNotClosed();

            if (m_consuming)
            {
                var eventOffset = skipCurrent ? m_eventSliceOffset : m_eventSliceOffset + 1;
                if (eventOffset <= m_commitedEventCount)
                {
                    // current event has been commited.
                    return;
                }

                var version = m_commitedStreamVersion.Increment(eventOffset - m_commitedEventCount);

                if (m_commitedStreamVersion < version)
                {
                    await m_commitConsumedVersion(version);

                    m_commitedStreamVersion = version;
                    m_commitedEventCount++;
                }
            }
            else
            {
                await m_commitConsumedVersion(m_reader.CurrentStreamVersion);
                m_commitedStreamVersion = m_reader.CurrentStreamVersion;
                m_eventSliceOffset = 0;
            }
        }