/// <summary> /// Returns multiple events from a given stream. /// If all the events do not exist, as many as can be found will be returned. /// </summary> /// <param name="stream">The stream name.</param> /// <param name="fromEventNumber">The event number to start from (inclusive).</param> /// <param name="numberOfEvents">The number of events to return.</param> /// <returns></returns> public async Task <IList <Message> > GetAsync(string stream, int fromEventNumber, int numberOfEvents) { var eventStreamSlice = await _eventStore.ReadStreamEventsForwardAsync(stream, fromEventNumber, numberOfEvents, true); return(eventStreamSlice.Events.Select(e => EventStoreMessageReader.ConvertEventToMessage(e.Event, stream)).ToList()); }
/// <summary> /// Returns messages that have yet to be dispatched /// </summary> /// <param name="millSecondsSinceSent">How long ago as the message sent?</param> /// <param name="pageSize">How many messages to return at once?</param> /// <param name="pageNumber">Which page number of messages</param> /// <param name="args">Additional parameters required for search, if any</param> /// <returns>A list of messages that are outstanding for dispatch</returns> public async Task <IEnumerable <Message> > OutstandingMessagesAsync( double millSecondsSinceSent, int pageSize = 100, int pageNumber = 1, Dictionary <string, object> args = null, CancellationToken cancellationToken = default) { var stream = GetStreamFromArgs(args); var sentBefore = DateTime.UtcNow.AddMilliseconds(millSecondsSinceSent * -1); var fromEventNumber = pageSize * (pageNumber - 1); var eventStreamSlice = await _eventStore.ReadStreamEventsBackwardAsync(stream, fromEventNumber, pageSize, true); var messages = eventStreamSlice.Events .Where(e => e.Event.Created <= sentBefore) .Select(e => EventStoreMessageReader.ConvertEventToMessage(e.Event, stream)) .ToList(); HashSet <Guid> dispatchedIds = new HashSet <Guid>(); List <Message> outstandingMessages = new List <Message>(); foreach (var message in messages) { var dispatchedAt = message.Header.Bag.ContainsKey(Globals.DispatchedAtKey) ? message.Header.Bag[Globals.DispatchedAtKey] as string : null; if (dispatchedAt is null) { outstandingMessages.Add(message); continue; } var previousEventId = message.Header.Bag[Globals.PreviousEventIdKey] as string; if (!Guid.TryParse(previousEventId, out Guid eventId)) { continue; } if (!dispatchedIds.Contains(eventId)) { dispatchedIds.Add(eventId); continue; } outstandingMessages.Add(message); } return(outstandingMessages.Where(om => !dispatchedIds.Contains(om.Id))); }
public async Task <IList <Message> > GetAsync( int pageSize = 100, int pageNumber = 1, Dictionary <string, object> args = null, CancellationToken cancellationToken = default) { string stream = GetStreamFromArgs(args); var fromEventNumber = pageSize * (pageNumber - 1); var eventStreamSlice = await _eventStore.ReadStreamEventsForwardAsync(stream, fromEventNumber, pageSize, true); return(eventStreamSlice.Events.Select(e => EventStoreMessageReader.ConvertEventToMessage(e.Event, stream)).ToList()); }
/// <summary> /// Update a message to show it is dispatched /// </summary> /// <param name="id">The id of the message to update</param> /// <param name="dispatchedAt">When was the message dispatched, defaults to UTC now</param> /// <param name="args">Additional parameters required for search, if any</param> /// <param name="cancellationToken">Allows the sender to cancel the request pipeline. Optional</param> public async Task MarkDispatchedAsync(Guid id, DateTime?dispatchedAt = null, Dictionary <string, object> args = null, CancellationToken cancellationToken = default) { var stream = GetStreamFromArgs(args); StreamEventsSlice slice; var startPos = (long)StreamPosition.End; long? nextEventNumber = null; RecordedEvent resolvedEvent; bool found = false; do { slice = await _eventStore.ReadStreamEventsBackwardAsync(stream, startPos, 100, true); startPos = slice.NextEventNumber; if (nextEventNumber is null) { nextEventNumber = (await _eventStore.ReadStreamEventsBackwardAsync(stream, StreamPosition.End, 1, true)).LastEventNumber; } resolvedEvent = slice.Events.FirstOrDefault(e => e.Event.EventId == id).Event; if (resolvedEvent != null) { found = true; } } while (!found && !slice.IsEndOfStream); if (resolvedEvent is null) { return; } var message = EventStoreMessageReader.ConvertEventToMessage(resolvedEvent, stream, dispatchedAt, nextEventNumber.Value); var eventData = EventStoreMessageWriter.CreateEventData(message); await _eventStore.AppendToStreamAsync(stream, nextEventNumber.Value, eventData); }