public async Task <IReadOnlyList <StoredEvent> > QueryAsync(string streamName, long streamPosition = 0) { var commits = await Collection.Find( Filter.And( Filter.Eq(EventStreamField, streamName), Filter.Gte(EventStreamOffsetField, streamPosition - 1))) .Sort(Sort.Ascending(TimestampField)).ToListAsync(); var result = new List <StoredEvent>(); foreach (var commit in commits) { var eventStreamOffset = (int)commit.EventStreamOffset; var commitTimestamp = commit.Timestamp; var commitOffset = 0; foreach (var e in commit.Events) { eventStreamOffset++; if (eventStreamOffset >= streamPosition) { var eventData = e.ToEventData(); var eventToken = new StreamPosition(commitTimestamp, commitOffset, commit.Events.Length); result.Add(new StoredEvent(eventToken, eventStreamOffset, eventData)); } } } return(result); }
public async IAsyncEnumerable <StoredEvent> QueryAllAsync(string?streamFilter = null, string?position = null, int take = int.MaxValue, [EnumeratorCancellation] CancellationToken ct = default) { StreamPosition lastPosition = position; var filterDefinition = CreateFilter(streamFilter, lastPosition); var find = Collection.Find(filterDefinition) .Limit(take).Sort(Sort.Ascending(TimestampField).Ascending(EventStreamField)); var taken = 0; await foreach (var current in find.ToAsyncEnumerable(ct)) { foreach (var @event in current.Filtered(lastPosition)) { yield return(@event); taken++; if (taken == take) { break; } } } }
private async Task QueryAsync(Func <StoredEvent, Task> callback, StreamPosition lastPosition, SqlQuerySpec query, EventPredicate filterExpression, CancellationToken ct = default) { using (Profiler.TraceMethod <CosmosDbEventStore>()) { await documentClient.QueryAsync(collectionUri, query, async commit => { var eventStreamOffset = (int)commit.EventStreamOffset; var commitTimestamp = commit.Timestamp; var commitOffset = 0; foreach (var @event in commit.Events) { eventStreamOffset++; if (commitOffset > lastPosition.CommitOffset || commitTimestamp > lastPosition.Timestamp) { var eventData = @event.ToEventData(); if (filterExpression(eventData)) { var eventToken = new StreamPosition(commitTimestamp, commitOffset, commit.Events.Length); await callback(new StoredEvent(commit.EventStream, eventToken, eventStreamOffset, eventData)); } } commitOffset++; } }, ct); } }
private async Task QueryAsync(Func <StoredEvent, Task> callback, StreamPosition lastPosition, EventFilter filterDefinition, EventPredicate filterExpression, CancellationToken ct = default) { using (Profiler.TraceMethod <MongoEventStore>()) { await Collection.Find(filterDefinition, options : Batching.Options).Sort(Sort.Ascending(TimestampField)).ForEachPipelineAsync(async commit => { var eventStreamOffset = (int)commit.EventStreamOffset; var commitTimestamp = commit.Timestamp; var commitOffset = 0; foreach (var @event in commit.Events) { eventStreamOffset++; if (commitOffset > lastPosition.CommitOffset || commitTimestamp > lastPosition.Timestamp) { var eventData = @event.ToEventData(); if (filterExpression(eventData)) { var eventToken = new StreamPosition(commitTimestamp, commitOffset, commit.Events.Length); await callback(new StoredEvent(commit.EventStream, eventToken, eventStreamOffset, eventData)); } } commitOffset++; } }, ct); } }
private Task QueryAsync(Func <StoredEvent, Task> callback, StreamPosition lastPosition, FilterDefinition <MongoEventCommit> filter, CancellationToken ct) { return(Collection.Find(filter).Sort(Sort.Ascending(TimestampField)).ForEachPipelineAsync(async commit => { var eventStreamOffset = (int)commit.EventStreamOffset; var commitTimestamp = commit.Timestamp; var commitOffset = 0; foreach (var e in commit.Events) { eventStreamOffset++; if (commitOffset > lastPosition.CommitOffset || commitTimestamp > lastPosition.Timestamp) { var eventData = e.ToEventData(); var eventToken = new StreamPosition(commitTimestamp, commitOffset, commit.Events.Length); await callback(new StoredEvent(eventToken, eventStreamOffset, eventData)); commitOffset++; } } }, ct)); }
public async Task GetEventsAsync(Func <StoredEvent, Task> callback, string streamFilter = null, string position = null, CancellationToken cancellationToken = default(CancellationToken)) { Guard.NotNull(callback, nameof(callback)); StreamPosition lastPosition = position; var filter = CreateFilter(streamFilter, lastPosition); await Collection.Find(filter).Sort(Sort.Ascending(TimestampField)).ForEachAsync(async commit => { var eventStreamOffset = (int)commit.EventStreamOffset; var commitTimestamp = commit.Timestamp; var commitOffset = 0; foreach (var e in commit.Events) { eventStreamOffset++; if (commitOffset > lastPosition.CommitOffset || commitTimestamp > lastPosition.Timestamp) { var eventData = e.ToEventData(); var eventToken = new StreamPosition(commitTimestamp, commitOffset, commit.Events.Length); await callback(new StoredEvent(eventToken, eventStreamOffset, eventData)); commitOffset++; } } }, cancellationToken); }
private static EventFilter CreateFilter(string?streamFilter, StreamPosition streamPosition) { var filters = new List <EventFilter>(); AppendByPosition(streamPosition, filters); AppendByStream(streamFilter, filters); return(Filter.And(filters)); }
public static StreamPosition ToPosition(this long version) { if (version <= 0) { return(StreamPosition.Start); } return(StreamPosition.FromInt64(version)); }
private static EventFilter CreateFilter(string property, object value, StreamPosition streamPosition) { var filters = new List <EventFilter>(); AppendByPosition(streamPosition, filters); AppendByProperty(property, value, filters); return(Filter.And(filters)); }
public Task QueryAsync(Func <StoredEvent, Task> callback, string streamFilter = null, string position = null, CancellationToken ct = default(CancellationToken)) { Guard.NotNull(callback, nameof(callback)); StreamPosition lastPosition = position; var filter = CreateFilter(streamFilter, lastPosition); return(QueryAsync(callback, lastPosition, filter, ct)); }
public static SqlQuerySpec CreateByProperty(string property, object value, StreamPosition streamPosition) { var filters = new List <string>(); var parameters = new SqlParameterCollection(); filters.ForPosition(parameters, streamPosition); filters.ForProperty(parameters, property, value); return(BuildQuery(filters, parameters)); }
private static void AddPositionFilter(StreamPosition streamPosition, List <FilterDefinition <MongoEventCommit> > filters) { if (streamPosition.IsEndOfCommit) { filters.Add(Filter.Gt(TimestampField, streamPosition.Timestamp)); } else { filters.Add(Filter.Gte(TimestampField, streamPosition.Timestamp)); } }
public static SqlQuerySpec CreateByFilter(string?streamFilter, StreamPosition streamPosition, string sortOrder, long take) { var filters = new List <string>(); var parameters = new SqlParameterCollection(); filters.ForPosition(parameters, streamPosition); filters.ForRegex(parameters, streamFilter); return(BuildQuery(filters, parameters, sortOrder, take)); }
public Task QueryAsync(Func <StoredEvent, Task> callback, string?streamFilter = null, string?position = null, CancellationToken ct = default) { Guard.NotNull(callback); StreamPosition lastPosition = position; var filterDefinition = CreateFilter(streamFilter, lastPosition); var filterExpression = CreateFilterExpression(null, null); return(QueryAsync(callback, lastPosition, filterDefinition, filterExpression, ct)); }
private static void AppendByPosition(StreamPosition streamPosition, List <EventFilter> filters) { if (streamPosition.IsEndOfCommit) { filters.Add(Filter.Gt(TimestampField, streamPosition.Timestamp)); } else { filters.Add(Filter.Gte(TimestampField, streamPosition.Timestamp)); } }
public static FilterDefinition <MongoEventCommit> ByPosition(StreamPosition streamPosition) { if (streamPosition.IsEndOfCommit) { return(Builders <MongoEventCommit> .Filter.Gt(x => x.Timestamp, streamPosition.Timestamp)); } else { return(Builders <MongoEventCommit> .Filter.Gte(x => x.Timestamp, streamPosition.Timestamp)); } }
private static EventFilter CreateFilter(string?streamFilter, StreamPosition streamPosition) { var byPosition = FilterExtensions.ByPosition(streamPosition); var byStream = FilterExtensions.ByStream(streamFilter); if (byStream != null) { return(Filter.And(byPosition, byStream)); } return(byPosition); }
public Task QueryAsync(Func <StoredEvent, Task> callback, string streamFilter = null, string position = null, CancellationToken ct = default) { Guard.NotNull(callback, nameof(callback)); ThrowIfDisposed(); StreamPosition lastPosition = position; var filterDefinition = FilterBuilder.CreateByFilter(streamFilter, lastPosition); var filterExpression = FilterBuilder.CreateExpression(null, null); return(QueryAsync(callback, lastPosition, filterDefinition, filterExpression, ct)); }
public Task QueryAsync(Func <StoredEvent, Task> callback, string property, object value, string?position = null, CancellationToken ct = default) { Guard.NotNull(callback); Guard.NotNullOrEmpty(property); Guard.NotNull(value); StreamPosition lastPosition = position; var filterDefinition = CreateFilter(property, value, lastPosition); var filterExpression = CreateFilterExpression(property, value); return(QueryAsync(callback, lastPosition, filterDefinition, filterExpression, ct)); }
private async Task QueryAsync(Func <StoredEvent, Task> callback, StreamPosition position, EventFilter filter, CancellationToken ct = default) { using (Profiler.TraceMethod <MongoEventStore>()) { await Collection.Find(filter, options : Batching.Options).Sort(Sort.Ascending(TimestampField)).ForEachPipedAsync(async commit => { foreach (var @event in commit.Filtered(position)) { await callback(@event); } }, ct); } }
private IAsyncEnumerable <StoredEvent> QueryReverseAsync(string streamName, StreamPosition start, long count, CancellationToken ct = default) { var result = client.ReadStreamAsync( Direction.Backwards, streamName, start, count, resolveLinkTos: true, cancellationToken: ct); return(result.Select(x => Formatter.Read(x, StreamPrefix, serializer))); }
private async Task QueryCurrentAsync(string?streamFilter, StreamPosition lastPosition) { BsonDocument?resumeToken = null; var start = lastPosition.Timestamp.Timestamp > 0 ? lastPosition.Timestamp.Timestamp - 30 : SystemClock.Instance.GetCurrentInstant().Minus(Duration.FromSeconds(30)).ToUnixTimeSeconds(); var changePipeline = Match(streamFilter); var changeStart = new BsonTimestamp((int)start, 0); while (!stopToken.IsCancellationRequested) { var changeOptions = new ChangeStreamOptions(); if (resumeToken != null) { changeOptions.StartAfter = resumeToken; } else { changeOptions.StartAtOperationTime = changeStart; } using (var cursor = eventStore.TypedCollection.Watch(changePipeline, changeOptions, stopToken.Token)) { var isRead = false; await cursor.ForEachAsync(async change => { if (change.OperationType == ChangeStreamOperationType.Insert) { foreach (var storedEvent in change.FullDocument.Filtered(lastPosition)) { await eventSubscriber.OnEventAsync(this, storedEvent); } } isRead = true; }, stopToken.Token); resumeToken = cursor.GetResumeToken(); if (!isRead) { await Task.Delay(1000); } } } }
public Task QueryAsync(Func <StoredEvent, Task> callback, string property, object value, string position = null, CancellationToken ct = default) { Guard.NotNull(callback, nameof(callback)); Guard.NotNullOrEmpty(property, nameof(property)); Guard.NotNull(value, nameof(value)); ThrowIfDisposed(); StreamPosition lastPosition = position; var filterDefinition = FilterBuilder.CreateByProperty(property, value, lastPosition); var filterExpression = FilterBuilder.CreateExpression(property, value); return(QueryAsync(callback, lastPosition, filterDefinition, filterExpression, ct)); }
public async Task <IReadOnlyList <StoredEvent> > QueryLatestAsync(string streamName, int count) { Guard.NotNullOrEmpty(streamName, nameof(streamName)); ThrowIfDisposed(); if (count <= 0) { return(EmptyEvents); } using (Profiler.TraceMethod <CosmosDbEventStore>()) { var query = FilterBuilder.ByStreamNameDesc(streamName, count); var result = new List <StoredEvent>(); await documentClient.QueryAsync(collectionUri, query, commit => { var eventStreamOffset = (int)commit.EventStreamOffset; var commitTimestamp = commit.Timestamp; var commitOffset = 0; foreach (var @event in commit.Events) { eventStreamOffset++; var eventData = @event.ToEventData(); var eventToken = new StreamPosition(commitTimestamp, commitOffset, commit.Events.Length); result.Add(new StoredEvent(streamName, eventToken, eventStreamOffset, eventData)); } return(Task.CompletedTask); }); IEnumerable <StoredEvent> ordered = result.OrderBy(x => x.EventStreamNumber); if (result.Count > count) { ordered = ordered.Skip(result.Count - count); } return(ordered.ToList()); } }
public async Task <IReadOnlyList <StoredEvent> > QueryLatestAsync(string streamName, int count) { Guard.NotNullOrEmpty(streamName); if (count <= 0) { return(EmptyEvents); } using (Profiler.TraceMethod <MongoEventStore>()) { var commits = await Collection.Find( Filter.Eq(EventStreamField, streamName)) .Sort(Sort.Descending(TimestampField)).Limit(count).ToListAsync(); var result = new List <StoredEvent>(); foreach (var commit in commits) { var eventStreamOffset = (int)commit.EventStreamOffset; var commitTimestamp = commit.Timestamp; var commitOffset = 0; foreach (var @event in commit.Events) { eventStreamOffset++; var eventData = @event.ToEventData(); var eventToken = new StreamPosition(commitTimestamp, commitOffset, commit.Events.Length); result.Add(new StoredEvent(streamName, eventToken, eventStreamOffset, eventData)); } } IEnumerable <StoredEvent> ordered = result.OrderBy(x => x.EventStreamNumber); if (result.Count > count) { ordered = ordered.Skip(result.Count - count); } return(ordered.ToList()); } }
public async IAsyncEnumerable <StoredEvent> QueryAllReverseAsync(string?streamFilter = null, Instant timestamp = default, long take = long.MaxValue, [EnumeratorCancellation] CancellationToken ct = default) { if (take <= 0) { yield break; } StreamPosition lastPosition = timestamp; var filterDefinition = CreateFilter(streamFilter, lastPosition); var find = Collection.Find(filterDefinition, options: Batching.Options) .Limit((int)take).Sort(Sort.Descending(TimestampField).Ascending(EventStreamField)); var taken = 0; using (var cursor = await find.ToCursorAsync(ct)) { while (taken < take && await cursor.MoveNextAsync(ct)) { foreach (var current in cursor.Current) { foreach (var @event in current.Filtered(lastPosition).Reverse()) { yield return(@event); taken++; if (taken == take) { break; } } if (taken == take) { break; } } } } }
public static StreamPosition ToPosition(this string?position, bool inclusive) { if (string.IsNullOrWhiteSpace(position)) { return(StreamPosition.Start); } if (long.TryParse(position, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedPosition)) { if (!inclusive) { parsedPosition++; } return(StreamPosition.FromInt64(parsedPosition)); } return(StreamPosition.Start); }
public async Task QueryAsync(Func <StoredEvent, Task> callback, string?streamFilter = null, string?position = null, CancellationToken ct = default) { Guard.NotNull(callback, nameof(callback)); ThrowIfDisposed(); StreamPosition lastPosition = position; var filterDefinition = FilterBuilder.CreateByFilter(streamFilter, lastPosition); var filterExpression = FilterBuilder.CreateExpression(null, null); using (Profiler.TraceMethod <CosmosDbEventStore>()) { await documentClient.QueryAsync(collectionUri, filterDefinition, async commit => { var eventStreamOffset = (int)commit.EventStreamOffset; var commitTimestamp = commit.Timestamp; var commitOffset = 0; foreach (var @event in commit.Events) { eventStreamOffset++; if (commitOffset > lastPosition.CommitOffset || commitTimestamp > lastPosition.Timestamp) { var eventData = @event.ToEventData(); if (filterExpression(eventData)) { var eventToken = new StreamPosition(commitTimestamp, commitOffset, commit.Events.Length); await callback(new StoredEvent(commit.EventStream, eventToken, eventStreamOffset, eventData)); } } commitOffset++; } }, ct); } }
public async Task <IReadOnlyList <StoredEvent> > QueryAsync(string streamName, long streamPosition = 0) { Guard.NotNullOrEmpty(streamName); using (Profiler.TraceMethod <MongoEventStore>()) { var commits = await Collection.Find( Filter.And( Filter.Eq(EventStreamField, streamName), Filter.Gte(EventStreamOffsetField, streamPosition - MaxCommitSize))) .Sort(Sort.Ascending(TimestampField)).ToListAsync(); var result = new List <StoredEvent>(); foreach (var commit in commits) { var eventStreamOffset = (int)commit.EventStreamOffset; var commitTimestamp = commit.Timestamp; var commitOffset = 0; foreach (var @event in commit.Events) { eventStreamOffset++; if (eventStreamOffset >= streamPosition) { var eventData = @event.ToEventData(); var eventToken = new StreamPosition(commitTimestamp, commitOffset, commit.Events.Length); result.Add(new StoredEvent(streamName, eventToken, eventStreamOffset, eventData)); } } } return(result); } }
public static IEnumerable <StoredEvent> Filtered(this MongoEventCommit commit, long streamPosition) { var eventStreamOffset = commit.EventStreamOffset; var commitTimestamp = commit.Timestamp; var commitOffset = 0; foreach (var @event in commit.Events) { eventStreamOffset++; if (eventStreamOffset >= streamPosition) { var eventData = @event.ToEventData(); var eventPosition = new StreamPosition(commitTimestamp, commitOffset, commit.Events.Length); yield return(new StoredEvent(commit.EventStream, eventPosition, eventStreamOffset, eventData)); } commitOffset++; } }