/// <summary> /// Named Stream Reader /// i.e. [StreamName] /// </summary> /// <param name="streamName">An exact stream name.</param> /// <param name="checkpoint">The starting point to read from.</param> /// <param name="count">The count of items to read</param> /// <param name="readBackwards">Read the stream backwards</param> /// <returns>Returns true if any events were read from the stream</returns> public virtual bool Read( string streamName, long?checkpoint = null, long?count = null, bool readBackwards = false) { var eventsRead = false; if (checkpoint != null) { Ensure.Nonnegative((long)checkpoint, nameof(checkpoint)); } if (count != null) { Ensure.Positive((long)count, nameof(count)); } if (!ValidateStreamName(streamName)) { throw new ArgumentException("Stream not found.", streamName); } _cancelled = false; firstEventRead = false; StreamName = streamName; long sliceStart = checkpoint ?? (readBackwards ? -1 : 0); long remaining = count ?? long.MaxValue; StreamEventsSlice currentSlice; do { var page = remaining < ReadPageSize ? remaining: ReadPageSize; currentSlice = !readBackwards ? _streamStoreConnection.ReadStreamForward(streamName, sliceStart, page) : _streamStoreConnection.ReadStreamBackward(streamName, sliceStart, page); if (!(currentSlice is StreamEventsSlice)) { return(false); } remaining -= currentSlice.Events.Length; sliceStart = currentSlice.NextEventNumber; Array.ForEach(currentSlice.Events, EventRead); } while (!currentSlice.IsEndOfStream && !_cancelled && remaining != 0); return(eventsRead); }
/// <summary> /// Named Stream Reader /// i.e. [StreamName] /// </summary> /// <param name="streamName">An exact stream name.</param> /// <param name="completionCheck">Read will block until true to ensure processing has completed, use '()=> true' to continue without blocking. If cancellation or timeout is required it should be implemented in the completion method</param> /// <param name="checkpoint">The event number of the last received event. Reading will start with the next event.</param> /// <param name="count">The count of items to read</param> /// <param name="readBackwards">Read the stream backwards</param> /// <returns>Returns true if any events were read from the stream</returns> public virtual bool Read( string streamName, Func <bool> completionCheck, long?checkpoint = null, long?count = null, bool readBackwards = false) { if (checkpoint != null) { Ensure.Nonnegative((long)checkpoint, nameof(checkpoint)); } if (count != null) { Ensure.Positive((long)count, nameof(count)); } if (!ValidateStreamName(streamName)) { throw new ArgumentException("Stream not found.", streamName); } _cancelled = false; FirstEventRead = false; StreamName = streamName; long sliceStart; if (checkpoint is null) { sliceStart = readBackwards ? -1 : 0; } else { sliceStart = checkpoint.Value + (readBackwards ? -1 : 1); } long remaining = count ?? long.MaxValue; StreamEventsSlice currentSlice; do { var page = remaining < ReadPageSize ? remaining : ReadPageSize; currentSlice = !readBackwards ? _streamStoreConnection.ReadStreamForward(streamName, sliceStart, page) : _streamStoreConnection.ReadStreamBackward(streamName, sliceStart, page); if (!(currentSlice is StreamEventsSlice)) { break; } if (currentSlice.Events.Length > 0) { FirstEventRead = true; } remaining -= currentSlice.Events.Length; sliceStart = currentSlice.NextEventNumber; Array.ForEach(currentSlice.Events, EventRead); } while (!currentSlice.IsEndOfStream && !_cancelled && remaining != 0); if (FirstEventRead && completionCheck != null) { SpinWait.SpinUntil(() => { try { return(completionCheck()); } catch { return(true); } }); } return(FirstEventRead); }