public async Task <bool> MoveNextAsync() { if (_buffer.Count > 0) { _buffer.Dequeue(); if (_buffer.Count > 0) { return(true); } } if (_isEndOfStream) { return(false); } // Why the 'while'? If the stream was soft-deleted in the past it starts at an event with number != 0. // So the first read operation returns 0 events, but reports the actual start position of the stream // (currentSlice.NextEventNumber). Then, a second read is required to actually read the first few events. while (_buffer.Count == 0 && !_isEndOfStream) { var currentSlice = await _connection.ReadStreamEventsForwardAsync(_streamName, _startPosition, PageSize, false); foreach (var eventData in currentSlice.Events) { try { var ev = eventData.Event.ToIEvent().MigrateToLatestVersion(); _buffer.Enqueue(ev); } catch (ArgumentException e) { EventParsingFailed?.Invoke(this, new EventParsingFailedArgs(eventData, e)); } } _startPosition = currentSlice.NextEventNumber; _isEndOfStream = currentSlice.IsEndOfStream; } return(_buffer.Count > 0); }
private Task OnEventAppeared(EventStoreCatchUpSubscription _, ResolvedEvent resolvedEvent) { try { // Note regarding migration: // Event types may change over time (properties get added/removed etc.) // Whenever an event has multiple versions, an event of an obsolete type should be transformed to an event // of the latest version, so that ApplyEvent(...) only has to deal with events of the current version. var ev = resolvedEvent.Event.ToIEvent().MigrateToLatestVersion(); _handler?.Invoke(ev); } catch (Exception e) { EventParsingFailed?.Invoke(this, new EventParsingFailedArgs(resolvedEvent, e)); } return(Task.CompletedTask); }