Beispiel #1
0
        public async Task <IEnumerable <EventModel> > ReadAllEventsForwardAsync()
        {
            var records =
                await eventStoreConnection.ReadAllEventsForwardAsync(Position.Start, PageSize, false,
                                                                     CredentialsHelper.Default);

            return(records.Events.Select(@event => @event.Event.ParseEvent()).ToList());
        }
Beispiel #2
0
        public static void ReadSavedEvents()
        {
            var            allEvents     = new List <ResolvedEvent>();
            var            nonStatEvents = new List <ResolvedEvent>();
            AllEventsSlice currentSlice;
            var            nextSliceStart = Position.Start;

            do
            {
                currentSlice =
                    connection.ReadAllEventsForwardAsync(nextSliceStart, 200, false).Result;

                nextSliceStart = currentSlice.NextPosition;

                allEvents.AddRange(currentSlice.Events);
            } while (!currentSlice.IsEndOfStream);

            foreach (var resolvedEvent in allEvents)
            {
                if (resolvedEvent.OriginalStreamId != "user-admin" &&
                    resolvedEvent.OriginalStreamId[0] != '$')
                {
                    nonStatEvents.Add(resolvedEvent);
                }
            }

            distrbuteSavedEvents(nonStatEvents);
        }
Beispiel #3
0
        public async IAsyncEnumerable <IEvent> GetAllEventsBetween(Position startPosition, Position endPosition, IReadOnlyCollection <Type> eventTypes)
        {
            await Connect();

            var eventTypesByName = eventTypes.ToDictionary(x => x.Name);

            AllEventsSlice currentSlice;

            do
            {
                currentSlice = await _connection.ReadAllEventsForwardAsync(startPosition, EVENT_COUNT, false);

                startPosition = currentSlice.NextPosition;
                foreach (var @event in currentSlice.Events.Where(x => !x.Event.EventType.StartsWith("$")))
                {
                    if (eventTypesByName.TryGetValue(@event.Event.EventType, out var eventType))
                    {
                        yield return(ConvertToDomainEvent(@event, eventType));
                    }
                    if (@event.OriginalPosition == endPosition)
                    {
                        yield break;
                    }
                }
            } while (!currentSlice.IsEndOfStream);
        }
Beispiel #4
0
        private async Task ReadEventsInternalAsync(IEventStoreConnection connection, bool resolveLinkTos,
                                                   UserCredentials userCredentials, long?lastCommitPosition, long?lastEventNumber)
        {
            var slice = await connection.ReadAllEventsForwardAsync(_nextReadPosition, ReadBatchSize, resolveLinkTos, userCredentials).ConfigureAwait(false);

            await ReadEventsCallbackAsync(slice, connection, resolveLinkTos, userCredentials, lastCommitPosition, lastEventNumber).ConfigureAwait(false);
        }
        public static void ReadSavedEvents()
        {
            var log = Connection.Book.From("EventLog", new { Id = 1 }).ToObject <EventLog>().Execute();

            if (log.EventCount == 0)
            {
                //Task<AllEventsSlice>
                var            allEvents     = new List <ResolvedEvent>();
                var            nonStatEvents = new List <ResolvedEvent>();
                AllEventsSlice currentSlice;
                var            nextSliceStart = Position.Start;
                do
                {
                    currentSlice =
                        connection.ReadAllEventsForwardAsync(nextSliceStart, 200, false).Result;

                    nextSliceStart = currentSlice.NextPosition;

                    allEvents.AddRange(currentSlice.Events);
                } while (!currentSlice.IsEndOfStream);

                foreach (var resolvedEvent in allEvents)
                {
                    if (resolvedEvent.OriginalStreamId != "user-admin" &&
                        resolvedEvent.OriginalStreamId[0] != '$')
                    {
                        nonStatEvents.Add(resolvedEvent);
                    }
                }

                distrbuteSavedEvents(nonStatEvents);
            }
        }
        /// <summary>
        /// Read events until the given position.
        /// </summary>
        /// <param name="connection">The connection.</param>
        /// <param name="resolveLinkTos">Whether to resolve Link events.</param>
        /// <param name="userCredentials">User credentials for the operation.</param>
        /// <param name="lastCommitPosition">The commit position to read until.</param>
        /// <param name="lastEventNumber">The event number to read until.</param>
        protected override void ReadEventsTill(IEventStoreConnection connection, bool resolveLinkTos,
                                               UserCredentials userCredentials, long?lastCommitPosition, int?lastEventNumber)
        {
            bool done;

            do
            {
                AllEventsSlice slice = connection.ReadAllEventsForwardAsync(_nextReadPosition, ReadBatchSize, resolveLinkTos, userCredentials).Result;
                foreach (var e in slice.Events)
                {
                    if (e.OriginalPosition == null)
                    {
                        throw new Exception("Subscription event came up with no OriginalPosition.");
                    }
                    TryProcess(e);
                }
                _nextReadPosition = slice.NextPosition;

                done = lastCommitPosition == null
                               ? slice.IsEndOfStream
                               : slice.NextPosition >= new Position(lastCommitPosition.Value, lastCommitPosition.Value);

                if (!done && slice.IsEndOfStream)
                {
                    Thread.Sleep(1); // we are waiting for server to flush its data
                }
            } while (!done && !ShouldStop);

            if (Verbose)
            {
                Log.Debug("Catch-up Subscription to {0}: finished reading events, nextReadPosition = {1}.",
                          IsSubscribedToAll ? "<all>" : StreamId, _nextReadPosition);
            }
        }
        private void UpgradeProjectionPartitionCheckpoints()
        {
            Log("Looking for projection partition checkpoint streams");
            var from = Position.Start;

            _oldTfScanPercent = 0d;
            var lastSlice = _connection.ReadAllEventsBackwardAsync(Position.End, 1, false, _credentials).Result;

            if (lastSlice.Events.Length == 0)
            {
                throw new Exception("Empty TF");
            }
            _lastTfPosition = lastSlice.Events[0].OriginalPosition.Value.PreparePosition;
            AllEventsSlice slice;

            do
            {
                slice = _connection.ReadAllEventsForwardAsync(@from, 100, false, _credentials).Result;
                DisplayTfScanProgress(slice);
                foreach (var @event in slice.Events)
                {
                    if (@event.OriginalEventNumber == 0)
                    {
                        UpgradeStreamIfPartitionCheckpoint(@event.OriginalStreamId);
                    }
                }
                from = slice.NextPosition;
            } while (!slice.IsEndOfStream);
            Log("Completed looking for partition checkpoint streams");
        }
        public static AllEventsSlice ReadAllEventsForward(this IEventStoreConnection con, Position position, int maxCount, bool resolveLinkTos, UserCredentials userCredentials = null)
        {
            var task = con.ReadAllEventsForwardAsync(position, maxCount, resolveLinkTos, userCredentials);

            task.Wait();
            return(task.Result);
        }
Beispiel #9
0
        public async Task ReplayAllEvents()
        {
            var result = await _connection.ReadAllEventsForwardAsync(Position.Start, 4096, false, _credentials);

            foreach (var evnt in result.Events)
            {
                BroadcastEvent(evnt);
            }
        }
Beispiel #10
0
        public async Task PerformAll(Action <Guid> actionToNotifyEventIsDone = null)
        {
            var currentposition = await _positionReaderService.GetCurrentPosition();

            var position = new Position(currentposition.CommitPosition, currentposition.PreparePosition);
            var maxCount = 4096;

            var retrievedEvents = await _eventStoreConnection.ReadAllEventsForwardAsync(position, maxCount, false);

            PerformEventHandlerInvoke(actionToNotifyEventIsDone, retrievedEvents.Events);
        }
Beispiel #11
0
        private async Task ReadEventsInternalAsync(IEventStoreConnection connection, bool resolveLinkTos,
                                                   UserCredentials userCredentials, long?lastCommitPosition)
        {
            bool shouldStopOrDone;

            do
            {
                var slice = await connection.ReadAllEventsForwardAsync(_nextReadPosition, ReadBatchSize, resolveLinkTos, userCredentials).ConfigureAwait(false);

                shouldStopOrDone = await ReadEventsCallbackAsync(slice, lastCommitPosition).ConfigureAwait(false);
            } while (!shouldStopOrDone);
        }
        public async Task Load()
        {
            var readEvents = await _storeConnection.ReadAllEventsForwardAsync(new Position(0, 0), 4000, false);

            foreach (var resolvedEvent in readEvents.Events)
            {
                Console.WriteLine("Processing event", resolvedEvent.Event.EventType);
                ProcessEvent(resolvedEvent);
            }

            _storeConnection.SubscribeToAllAsync(false, EventAppeared);
        }
Beispiel #13
0
        public async Task <IEnumerable <EventWrapper> > GetEvents()
        {
            var eventStoreResponse = await _connection.ReadAllEventsForwardAsync(_position, 100, false);

            _position = eventStoreResponse.NextPosition;

            var events = eventStoreResponse
                         .Events
                         .Where(e => _cachedTypes.ContainsKey(e.Event.EventType))
                         .Select(e => new EventWrapper(
                                     JsonConvert.DeserializeObject(Encoding.UTF8.GetString(e.Event.Data), _cachedTypes[e.Event.EventType]),
                                     JsonConvert.DeserializeObject <Metadata>(Encoding.UTF8.GetString(e.Event.Metadata))));

            return(events);
        }
Beispiel #14
0
        private async Task <ReactiveDomain.Testing.RecordedEvent[]> ReadThens(Position position)
        {
            var recorded = new List <ReactiveDomain.Testing.RecordedEvent>();
            var slice    = await _connection.ReadAllEventsForwardAsync(position, 1024, false, new UserCredentials("admin", "changeit"));

            recorded.AddRange(
                slice.Events
                .Where(resolved =>
                       !resolved.OriginalStreamId.StartsWith("$") &&
                       resolved.OriginalStreamId.StartsWith(_prefix.ToString()) &&
                       resolved.OriginalEvent.IsJson)
                .Select(resolved => new ReactiveDomain.Testing.RecordedEvent(
                            new StreamName(resolved.OriginalStreamId),
                            JsonConvert.DeserializeObject(
                                Encoding.UTF8.GetString(resolved.OriginalEvent.Data),
                                Type.GetType(resolved.OriginalEvent.EventType, true),
                                _settings))));
            while (!slice.IsEndOfStream)
            {
                slice = await _connection.ReadAllEventsForwardAsync(slice.NextPosition, 1024, false, new UserCredentials("admin", "changeit"));

                recorded.AddRange(
                    slice.Events
                    .Where(resolved =>
                           !resolved.OriginalStreamId.StartsWith("$") &&
                           resolved.OriginalStreamId.StartsWith(_prefix.ToString()) &&
                           resolved.OriginalEvent.IsJson)
                    .Select(resolved => new ReactiveDomain.Testing.RecordedEvent(
                                new StreamName(resolved.OriginalStreamId),
                                JsonConvert.DeserializeObject(
                                    Encoding.UTF8.GetString(resolved.OriginalEvent.Data),
                                    Type.GetType(resolved.OriginalEvent.EventType, true),
                                    _settings))));
            }
            return(recorded.ToArray());
        }
 private void ReadEventsInternal(IEventStoreConnection connection, bool resolveLinkTos,
                                 UserCredentials userCredentials, long?lastCommitPosition, int?lastEventNumber)
 {
     try {
         connection.ReadAllEventsForwardAsync(_nextReadPosition, ReadBatchSize, resolveLinkTos, userCredentials)
         .ContinueWith(_ =>
         {
             ReadEventsCallback(_, connection, resolveLinkTos, userCredentials, lastCommitPosition, lastEventNumber);
         });
     }
     catch (Exception ex)
     {
         _completion.TrySetException(ex);
     }
 }
        private async Task <IEnumerable <ResolvedEvent> > ReadAllEvents()
        {
            var            streamEvents = new List <ResolvedEvent>();
            AllEventsSlice currentSlice;
            var            nextSliceStart = Position.Start;

            do
            {
                currentSlice = await _connection.ReadAllEventsForwardAsync(nextSliceStart, EVENT_COUNT, false);

                nextSliceStart = currentSlice.NextPosition;
                streamEvents.AddRange(currentSlice.Events);
            } while (!currentSlice.IsEndOfStream);

            return(streamEvents);
        }
Beispiel #17
0
        private static void ReadAllEventsForward(IEventStoreConnection connection)
        {
            UserCredentials credentials = new UserCredentials("admin", "changeit");
            AllEventsSlice slice = connection.ReadAllEventsForwardAsync(Position.Start, 100, false, credentials).Result;

            if (slice.Events.Length > 0)
            {
                Console.WriteLine("id: " + slice.Events[0].Event.EventId);

                string data = Encoding.UTF8.GetString(slice.Events[0].Event.Data);
                Console.WriteLine("data: " + data);

                string metadata = Encoding.UTF8.GetString(slice.Events[0].Event.Metadata);
                Console.WriteLine("metadata: " + metadata);
            }
        }
Beispiel #18
0
        public async Task GetAllEvents()
        {
            var allEvents = new List <ResolvedEvent>();

            AllEventsSlice currentSlice;

            var nextSliceStart = Position.Start;

            do
            {
                currentSlice = await _connection.ReadAllEventsForwardAsync(nextSliceStart, 200, false);

                nextSliceStart = currentSlice.NextPosition;
                allEvents.AddRange(currentSlice.Events);
            } while (!currentSlice.IsEndOfStream);

            Console.ReadLine();
        }
Beispiel #19
0
        private async Task <Position> ReadHistoricalEventsFrom(Position from)
        {
            var            position = from;
            AllEventsSlice slice;

            while (!stop && (slice = await eventStoreConnection.ReadAllEventsForwardAsync(position, ReadPageSize, false)).Events.Length > 0)
            {
                foreach (var rawEvent in slice.Events)
                {
                    historicalQueue.Enqueue(rawEvent);
                }
                EnsurePublishEvents(historicalQueue, historicalDone);

                position = slice.NextPosition;
            }

            return(position);
        }
Beispiel #20
0
        public void RepublishAllEvents()
        {
            AllEventsSlice currentSlice;
            var            nextPosition = Position.Start;

            do
            {
                currentSlice = _eventStoreConnection
                               .ReadAllEventsForwardAsync(nextPosition, ReadPageSize, false)
                               .Result;

                nextPosition = currentSlice.NextPosition;

                foreach (var evnt in currentSlice.Events)
                {
                    DomainEvent aggrEvent = (DomainEvent)DeserializeEvent(evnt.OriginalEvent.Metadata, evnt.OriginalEvent.Data);
                    this._publisher.Publish(aggrEvent);
                }
            } while (!currentSlice.IsEndOfStream);
        }
        public IList <IEvent> GetStreamForAggregate(int aggregateId)
        {
            var serializedEvents  = _connection.ReadAllEventsForwardAsync(Position.Start, 1000, false, credentials).GetAwaiter().GetResult();
            var deserializeEvents = new List <IEvent>();

            foreach (var serializeEvent in serializedEvents.Events)
            {
                var eventType = GetTypeFromName(serializeEvent.Event.EventType);

                if (eventType == typeof(CleaningRequested))
                {
                    deserializeEvents.Add(Utf8Json.JsonSerializer.Deserialize <CleaningRequested>(serializeEvent.Event.Data));
                }
            }

            return(deserializeEvents);

            Type GetTypeFromName(string typeName)
            {
                return(Type.GetType(typeName));
            }
        }
        public async Task <AllCommittedEventsPage> LoadAllCommittedEvents(
            GlobalPosition globalPosition,
            int pageSize,
            CancellationToken cancellationToken)
        {
            var            nextPosition   = ParsePosition(globalPosition);
            var            resolvedEvents = new List <ResolvedEvent>();
            AllEventsSlice allEventsSlice;

            do
            {
                allEventsSlice = await _connection.ReadAllEventsForwardAsync(nextPosition, pageSize, false).ConfigureAwait(false);

                resolvedEvents.AddRange(allEventsSlice.Events.Where(e => !e.OriginalStreamId.StartsWith("$")));
                nextPosition = allEventsSlice.NextPosition;
            }while (resolvedEvents.Count < pageSize && !allEventsSlice.IsEndOfStream);

            var eventStoreEvents = Map(resolvedEvents);

            return(new AllCommittedEventsPage(
                       new GlobalPosition(string.Format("{0}-{1}", nextPosition.CommitPosition, nextPosition.PreparePosition)),
                       eventStoreEvents));
        }
        public static void DeleteAllStreams(this IEventStoreConnection connection)
        {
            var slice = connection.
                        ReadAllEventsForwardAsync(
                Position.Start, Int32.MaxValue, false, EmbeddedEventStore.Credentials);

            slice.Wait();
            var streams = slice.Result.
                          Events.
                          Select(_ => _.OriginalStreamId).
                          Where(StreamNameIsNotReserved).
                          Distinct();

            foreach (var stream in streams)
            {
                var streamStatusSlice = connection.ReadStreamEventsForwardAsync(stream, 0, 1, false);
                streamStatusSlice.Wait();
                if (streamStatusSlice.Result.Status != SliceReadStatus.StreamDeleted &&
                    streamStatusSlice.Result.Status != SliceReadStatus.StreamNotFound)
                {
                    connection.DeleteStreamAsync(stream, ExpectedVersion.Any, EmbeddedEventStore.Credentials).Wait();
                }
            }
        }
Beispiel #24
0
        public async Task ReadAllEventsForward(StreamMessageReceived streamMessageReceived)
        {
            AllEventsSlice currentSlice;
            var            nextSliceStart = Position.Start;

            do
            {
                currentSlice = await _eventSourcing.ReadAllEventsForwardAsync(nextSliceStart, 100, false)
                               .ConfigureAwait(false);

                nextSliceStart = currentSlice.NextPosition;

                foreach (var @event in currentSlice.Events)
                {
                    await streamMessageReceived(new EventResponse(
                                                    @event.Event.EventStreamId,
                                                    @event.Event.EventId,
                                                    @event.Event.EventNumber,
                                                    @event.Event.EventType,
                                                    @event.Event.Data
                                                    ));
                }
            } while (!currentSlice.IsEndOfStream);
        }
Beispiel #25
0
        /// <summary>
        /// Read events until the given position async.
        /// </summary>
        /// <param name="connection">The connection.</param>
        /// <param name="resolveLinkTos">Whether to resolve Link events.</param>
        /// <param name="userCredentials">User credentials for the operation.</param>
        /// <param name="lastCommitPosition">The commit position to read until.</param>
        /// <param name="lastEventNumber">The event number to read until.</param>
        /// <returns></returns>
        protected override Task ReadEventsTillAsync(IEventStoreConnection connection, bool resolveLinkTos,
                                                    UserCredentials userCredentials, long?lastCommitPosition, int?lastEventNumber)
        {
            return(connection.ReadAllEventsForwardAsync(_nextReadPosition, ReadBatchSize, resolveLinkTos, userCredentials)
                   .ContinueWith(_ =>
            {
                if (_.IsFaulted || _.IsCanceled)
                {
                    _.Wait();         //force exception to be thrown
                }

                if (!ProcessEvents(lastCommitPosition, _.Result) && !ShouldStop)
                {
                    ReadEventsTillAsync(connection, resolveLinkTos, userCredentials,
                                        lastCommitPosition, lastEventNumber);
                }
                else if (Verbose)
                {
                    Log.Debug(
                        "Catch-up Subscription to {0}: finished reading events, nextReadPosition = {1}.",
                        IsSubscribedToAll ? "<all>" : StreamId, _nextReadPosition);
                }
            }, TaskContinuationOptions.AttachedToParent));
        }
Beispiel #26
0
        public async Task ReadEvents(
            Shared.Position fromPosition, Func <BaseOriginalEvent, ValueTask> next, CancellationToken cancellationToken
            )
        {
            await _realtime.Start().ConfigureAwait(false);

            Log.Info("Starting TCP reader");

            var sequence = 0;

            var start =
                fromPosition != Shared.Position.Start
                    ? new Position((long)fromPosition.EventPosition, (long)fromPosition.EventPosition)
                    : new Position(0, 0);

            if (fromPosition != Shared.Position.Start)
            {
                // skip one
                var e = await _connection.ReadAllEventsForwardAsync(start, 1, false).ConfigureAwait(false);

                start = e.NextPosition;
            }

            while (!cancellationToken.IsCancellationRequested)
            {
                using var activity = new Activity("read");
                activity.Start();

                var slice = await ReplicationMetrics.Measure(
                    () => _connection.ReadAllEventsForwardAsync(start, _pageSize, false),
                    ReplicationMetrics.ReadsHistogram,
                    x => x.Events.Length,
                    ReplicationMetrics.ReadErrorsCount
                    ).ConfigureAwait(false);

                foreach (var sliceEvent in slice?.Events ?? Enumerable.Empty <ResolvedEvent>())
                {
                    if (sliceEvent.Event.EventType.StartsWith('$') &&
                        sliceEvent.Event.EventType != Predefined.MetadataEventType)
                    {
                        await next(MapIgnored(sliceEvent, sequence++, activity)).ConfigureAwait(false);

                        continue;
                    }

                    if (Log.IsDebugEnabled())
                    {
                        Log.Debug(
                            "TCP: Read event with id {Id} of type {Type} from {Stream} at {Position}",
                            sliceEvent.Event.EventId,
                            sliceEvent.Event.EventType,
                            sliceEvent.OriginalStreamId,
                            sliceEvent.OriginalPosition
                            );
                    }

                    if (sliceEvent.Event.EventType == Predefined.MetadataEventType)
                    {
                        if (sliceEvent.Event.EventStreamId.StartsWith('$'))
                        {
                            continue;
                        }

                        if (Encoding.UTF8.GetString(sliceEvent.Event.Data) == StreamDeletedBody)
                        {
                            if (Log.IsDebugEnabled())
                            {
                                Log.Debug("Stream deletion {Stream}", sliceEvent.Event.EventStreamId);
                            }

                            await next(MapStreamDeleted(sliceEvent, sequence++, activity));
                        }
                        else
                        {
                            var meta = MapMetadata(sliceEvent, sequence++, activity);

                            if (Log.IsDebugEnabled())
                            {
                                Log.Debug("Stream meta {Stream}: {Meta}", sliceEvent.Event.EventStreamId, meta);
                            }

                            await next(meta);
                        }
                    }
                    else if (sliceEvent.Event.EventType[0] != '$')
                    {
                        var originalEvent = Map(sliceEvent, sequence++, activity);
                        await next(originalEvent).ConfigureAwait(false);
                    }
                }

                if (slice !.IsEndOfStream)
                {
                    Log.Info("Reached the end of the stream at {Position}", slice.NextPosition);
                    break;
                }

                start = slice.NextPosition;
            }
        }
        /// <summary>
        /// Read events until the given position.
        /// </summary>
        /// <param name="connection">The connection.</param>
        /// <param name="resolveLinkTos">Whether to resolve Link events.</param>
        /// <param name="userCredentials">User credentials for the operation.</param>
        /// <param name="lastCommitPosition">The commit position to read until.</param>
        /// <param name="lastEventNumber">The event number to read until.</param>
        protected override void ReadEventsTill(IEventStoreConnection connection, bool resolveLinkTos, 
                                               UserCredentials userCredentials, long? lastCommitPosition, int? lastEventNumber)
        {
            bool done;
            do
            {
                AllEventsSlice slice = connection.ReadAllEventsForwardAsync(_nextReadPosition, ReadBatchSize, resolveLinkTos, userCredentials).Result;
                foreach (var e in slice.Events)
                {
                    if (e.OriginalPosition == null) throw new Exception("Subscription event came up with no OriginalPosition.");
                    TryProcess(e);
                }
                _nextReadPosition = slice.NextPosition;

                done = lastCommitPosition == null
                               ? slice.IsEndOfStream
                               : slice.NextPosition >= new Position(lastCommitPosition.Value, lastCommitPosition.Value);

                if (!done && slice.IsEndOfStream)
                    Thread.Sleep(1); // we are waiting for server to flush its data
            } while (!done && !ShouldStop);

            if (Verbose) 
                Log.Debug("Catch-up Subscription to {0}: finished reading events, nextReadPosition = {1}.", 
                          IsSubscribedToAll ? "<all>" : StreamId, _nextReadPosition);
        }
 private void ReadEventsInternal(IEventStoreConnection connection, bool resolveLinkTos,
                UserCredentials userCredentials, long? lastCommitPosition, int? lastEventNumber)
 {
     try { 
         connection.ReadAllEventsForwardAsync(_nextReadPosition, ReadBatchSize, resolveLinkTos, userCredentials)
         .ContinueWith(_ =>
         {
             ReadEventsCallback(_, connection, resolveLinkTos, userCredentials, lastCommitPosition, lastEventNumber);
         });
     }
     catch (Exception ex)
     {
         _completion.SetException(ex);
     }
 }
Beispiel #29
0
 protected Task ReadAllForward(string login, string password)
 {
     return(Connection.ReadAllEventsForwardAsync(Position.Start, 1, false,
                                                 login == null && password == null ? null : new UserCredentials(login, password)));
 }
        /// <summary>
        /// Read events until the given position async.
        /// </summary>
        /// <param name="connection">The connection.</param>
        /// <param name="resolveLinkTos">Whether to resolve Link events.</param>
        /// <param name="userCredentials">User credentials for the operation.</param>
        /// <param name="lastCommitPosition">The commit position to read until.</param>
        /// <param name="lastEventNumber">The event number to read until.</param>
        /// <returns></returns>
        protected override Task ReadEventsTillAsync(IEventStoreConnection connection, bool resolveLinkTos,
                        UserCredentials userCredentials, long? lastCommitPosition, int? lastEventNumber)
        {
            return connection.ReadAllEventsForwardAsync(_nextReadPosition, ReadBatchSize, resolveLinkTos, userCredentials)
                .ContinueWith(_ =>
                    {
                        if (_.IsFaulted || _.IsCanceled)
                        {
                            _.Wait(); //force exception to be thrown
                        }

                        if (!ProcessEvents(lastCommitPosition, _.Result) && !ShouldStop)
                        {
                            ReadEventsTillAsync(connection, resolveLinkTos, userCredentials,
                                lastCommitPosition, lastEventNumber);
                        }
                        else if (Verbose)
                        {
                            Log.Debug(
                                "Catch-up Subscription to {0}: finished reading events, nextReadPosition = {1}.",
                                IsSubscribedToAll ? "<all>" : StreamId, _nextReadPosition);
                        }
                    }, TaskContinuationOptions.AttachedToParent);
        }
 protected void ReadAllForward(string login, string password)
 {
     Connection.ReadAllEventsForwardAsync(Position.Start, 1, false,
                                          login == null && password == null ? null : new UserCredentials(login, password))
     .Wait();
 }