Пример #1
0
        public async Task <StreamEventsPage> ReadStream(
            string streamName, long fromVersion, long maxCount,
            StreamReadDirection direction       = StreamReadDirection.Forward,
            CancellationToken cancellationToken = new CancellationToken())
        {
            StreamEventsSlice slice;

            using (var connection = _getEventStoreConnection())
            {
                slice = await connection
                        .ReadStreamEventsForwardAsync(streamName, fromVersion, (int)maxCount, false)
                        .ConfigureAwait(false);
            }

            var events = await Task
                         .WhenAll(slice.Events.Select(resolvedEvent => _resolveStreamEvent(resolvedEvent.Event, cancellationToken)))
                         .ConfigureAwait(false);

            return(new StreamEventsPage(
                       streamName: slice.Stream,
                       fromVersion: slice.FromEventNumber,
                       nextVersion: slice.NextEventNumber,
                       lastVersion: slice.LastEventNumber,
                       events: events,
                       direction: direction,
                       isEndOfStream: slice.IsEndOfStream));
        }
Пример #2
0
        public async Task <StreamEventsPage> ReadStream(
            string streamName, long fromVersion, long maxCount,
            StreamReadDirection direction       = StreamReadDirection.Forward,
            CancellationToken cancellationToken = new CancellationToken())
        {
            if (direction == StreamReadDirection.Backward)
            {
                throw new NotSupportedException("Marten only supports forward reads.");
            }

            if (fromVersion != 1)
            {
                throw new NotSupportedException("Marten only supports reading streams forward from the beginning (version:1).");
            }

            var streamId = GetStreamId(streamName);

            IReadOnlyList <IEvent> martenEvents;
            StreamState            streamState;

            using (var session = _getDocumentSession())
            {
                var getEvents      = session.Events.FetchStreamAsync(streamId, (int)maxCount, null, cancellationToken);
                var getStreamState = session.Events.FetchStreamStateAsync(streamId, cancellationToken);

                await Task
                .WhenAll(getEvents, getStreamState)
                .ConfigureAwait(false);

                martenEvents = await getEvents;
                streamState  = await getStreamState;
            }

            var events = martenEvents.Select(martenEvent => new StreamEvent(martenEvent.Id, martenEvent.Data, new Dictionary <string, string>
            {
                //{ EventMetadataKeys.Id          , martenEvent.Id.ToString() },
                { EventMetadataKeys.Timestamp, martenEvent.Timestamp.ToString(CultureInfo.InvariantCulture) },
                { EventMetadataKeys.Owner, streamState.AggregateType.Name },
                //{ EventMetadataKeys.OwnerId     , martenEvent.. },
                { EventMetadataKeys.OwnerVersion, martenEvent.Version.ToString() },
                { EventMetadataKeys.ClrType, martenEvent.Data.GetType().AssemblyQualifiedName },
            }));

            return(new StreamEventsPage(
                       streamName: streamId.ToString(),
                       fromVersion: 1,
                       nextVersion: martenEvents.LastOrDefault()?.Version + 1 ?? 1,
                       lastVersion: streamState.Version,
                       isEndOfStream: false,
                       events: events,
                       direction: StreamReadDirection.Forward));
        }
Пример #3
0
 public StreamEventsPage(
     string streamName,
     long fromVersion,
     long nextVersion,
     long lastVersion,
     bool isEndOfStream,
     IEnumerable <StreamEvent> events,
     StreamReadDirection direction)
 {
     IsEndOfStream = isEndOfStream;
     StreamName    = streamName;
     FromVersion   = fromVersion;
     NextVersion   = nextVersion;
     LastVersion   = lastVersion;
     Events        = events.ToArray();
     Direction     = direction;
 }
Пример #4
0
        public async Task <StreamEventsPage> ReadStream(
            string streamName, long fromVersion, long maxCount,
            StreamReadDirection direction       = StreamReadDirection.Forward,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var page = await _streamStore
                       .ReadStreamForwards(streamName, (int)fromVersion, (int)maxCount, cancellationToken)
                       .ConfigureAwait(false);

            var events = await Task
                         .WhenAll(page.Messages.Select(streamMessage => _resolveStreamEvent(streamMessage, cancellationToken)))
                         .ConfigureAwait(false);

            return(new StreamEventsPage(
                       streamName: page.StreamId,
                       fromVersion: page.FromStreamVersion,
                       nextVersion: page.NextStreamVersion,
                       lastVersion: page.LastStreamVersion,
                       isEndOfStream: page.IsEnd,
                       events: events,
                       direction: direction));
        }
Пример #5
0
        public StreamEventsPage(
            string streamId,
            int fromVersion,
            int toVersion,
            int lastVersion,
            IEnumerable<StreamEvent> events,
            StreamReadDirection direction)
        {
            var readonlyEvents = events.ToList().AsReadOnly();

            IsEndOfStream = direction == StreamReadDirection.Forward
                ? toVersion == lastVersion
                : toVersion == 0;
            StreamId      = streamId;
            FromVersion   = fromVersion;
            NextVersion   = IsEndOfStream
                ? -1
                : direction == StreamReadDirection.Forward
                    ? toVersion + 1
                    : toVersion - 1;
            LastVersion   = lastVersion;
            Events        = readonlyEvents;
            Direction     = direction;
        }
Пример #6
0
 public Task<StreamEventsPage> ReadStream(string streamId, int fromVersion, int count, StreamReadDirection direction = StreamReadDirection.Forward)
 {
     throw new NotImplementedException();
 }
Пример #7
0
        public async Task<StreamEventsPage> ReadStream(string streamId, int fromVersion, int count, StreamReadDirection direction = StreamReadDirection.Forward)
        {
            Guard.NullOrWhiteSpace(() => streamId);

            await _log.Debug("Reading stream {@streamId} from version {fromVersion} to version {count}", streamId, fromVersion, count);

            // create parameters
            var parameters = new DynamicParameters();

            parameters.AddDynamicParams(new {
                StreamId    = streamId,
                FromVersion = fromVersion,
                Count       = count,
                ReadForward = direction == StreamReadDirection.Forward ? 1 : 0
            });

            parameters.AddOutput("Error");
            parameters.AddReturnValue();

            IEnumerable<StreamEventData> result;

            // execute operation
            using(var connection = new SqlConnection(_settings.ConnectionString)) {
                // found a hardcore bug with Dapper!
                // if we exit a query without executing a select, the .QueryAsync<T> fails because it
                // tries to read the resultsetschema and fails. 
                // therefore we do not have access to return or output values.
                result = await connection
                    .QueryAsync<StreamEventData>(
                        sql        : "ReadStream",
                        param      : parameters,
                        commandType: CommandType.StoredProcedure)
                    .ConfigureAwait(false);
            }

            // check for errors 
            switch(parameters.GetOutput<int>("Error")) {
                case -100:
                    throw new StreamNotFoundException(streamId);
                case -200:
                    throw new StreamDeletedException(streamId, fromVersion);
            }

            await _log.Information("Stream {@streamId} read from version {fromVersion} to version {count}", streamId, fromVersion, count);

            // return stream page
            var streamVersion = parameters.GetReturnValue();

            var streamEvents = result.Select(
                streamEventData => {
                    var metadata        = _serializer.Deserialize<IDictionary<string, string>>(streamEventData.Metadata);
                    var domainEventType = Type.GetType(metadata[EventMetadataKeys.ClrType].ToString());
                    var streamEvent     = _serializer.DeserializeAs<object>(streamEventData.Data, domainEventType);
                    return new StreamEvent(streamEvent, metadata);
                }).ToList();

            var lastReadEventVersion = streamEvents.Any()
                ? int.Parse(streamEvents.Last().Metadata[EventMetadataKeys.Version])
                : -1;

            await _log.Debug("Stream {@streamId} event serialization finished", streamId);

            return new StreamEventsPage(
                streamId   : streamId,
                fromVersion: fromVersion,
                toVersion  : lastReadEventVersion,
                lastVersion: streamVersion,           
                events     : streamEvents,
                direction  : direction);
        }
        public async Task <StreamReadResults> ReadFrom(string streamId, Func <IAmAStoredEvent, bool> predicate = null, StreamReadDirection direction = StreamReadDirection.Backwards, CancellationToken cancellationToken = default)
        {
            predicate ??= _ => true;

            IAsyncEnumerable <StoredEvent> storedEvents;

            if (direction == StreamReadDirection.Backwards)
            {
                var readResult = await connection.ReadStreamEventsBackwardAsync(streamId, StreamPosition.End, pageSize, true);

                if (!StreamExists(readResult))
                {
                    return(new StreamReadResults(EmptyReadResult, false, StoredEventPosition.FromInt64(-1)));
                }

                storedEvents = readResult.Events
                               // Trust me, resharper is wrong in this one. Event can be null
                               // ReSharper disable once ConditionIsAlwaysTrueOrFalse
                               .Where(e => e.Event != null)
                               .Select((e, _) => e.Event.ToStoredEvent(stateFactory))
                               .TakeWhile(e => e.DeserializedEvent is not EntitySoftDeleted)
                               .Where(e => predicate(e))
                               .ToAsyncEnumerable();
            }
            else
            {
                var readResult = await connection.ReadStreamEventsForwardAsync(streamId, StreamPosition.Start, pageSize, true);

                if (!StreamExists(readResult))
                {
                    return(new StreamReadResults(EmptyReadResult, false, StoredEventPosition.FromInt64(-1)));
                }

                storedEvents = readResult.Events
                               // Trust me, resharper is wrong in this one. Event can be null
                               // ReSharper disable once ConditionIsAlwaysTrueOrFalse
                               .Where(e => e.Event != null)
                               .Select((e, c) => e.Event.ToStoredEvent(stateFactory))
                               .Where(e => predicate(e))
                               .ToAsyncEnumerable();
            }

            var result = await connection.ReadEventAsync(streamId, StreamPosition.End, false);

            var idx = result.Event?.OriginalEventNumber ?? -1;

            return(new StreamReadResults(storedEvents, true, StoredEventPosition.FromInt64(idx)));
        }
        public async Task <StreamReadResults> ReadFrom(string streamId, Func <IAmAStoredEvent, bool> predicate = null, StreamReadDirection direction = StreamReadDirection.Backwards, CancellationToken cancellationToken = default)
        {
            var readResult = client.ReadStreamAsync(
                direction == StreamReadDirection.Backwards ? Direction.Backwards : Direction.Forwards,
                streamId,
                direction == StreamReadDirection.Backwards ? StreamPosition.End : StreamPosition.Start,
                resolveLinkTos: true,
                configureOperationOptions: options => options.TimeoutAfter = TimeSpan.FromSeconds(30),
                cancellationToken: cancellationToken);

            bool streamExists = false;

            try
            {
                var readState = await readResult.ReadState;
                streamExists = readState == ReadState.Ok;
            }
#pragma warning disable 168
            catch (StreamDeletedException ex)
            // This happens when the stream is hard-deleted. We don't want to throw in that case
#pragma warning restore 168
            {
                streamExists = false;
            }

            if (!streamExists)
            {
                return(new StreamReadResults(EmptyReadResult, false, StoredEventPosition.FromInt64(-1)));
            }

            predicate ??= _ => true;

            var lastIndex = (await client.ReadStreamAsync(Direction.Backwards, streamId,
                                                          StreamPosition.End,
                                                          1,
                                                          resolveLinkTos: false).FirstAsync(cancellationToken)).OriginalEventNumber;

            IAsyncEnumerable <StoredEvent> storedEvents;
            if (direction == StreamReadDirection.Backwards)
            {
                storedEvents = readResult
                               // Trust me, resharper is wrong in this one. Event can be null
                               // ReSharper disable once ConditionIsAlwaysTrueOrFalse
                               .Where(e => e.Event != null)
                               .Select(e => e.Event.ToStoredEvent(stateFactory))
                               .TakeWhile(e => e.DeserializedEvent is not EntitySoftDeleted)
                               .Where(e => predicate(e));
            }
            else
            {
                storedEvents = readResult
                               // Trust me, resharper is wrong in this one. Event can be null
                               // ReSharper disable once ConditionIsAlwaysTrueOrFalse
                               .Where(e => e.Event != null)
                               .Select(e => e.Event.ToStoredEvent(stateFactory))
                               .Where(e => predicate(e));
            }

            return(new StreamReadResults(storedEvents, true, StoredEventPosition.FromInt64(lastIndex.ToInt64())));
        }