public async Task <StreamReadResults> ReadFrom(string streamId, Func <IAmAStoredEvent, bool> predicate = null, Direction direction = Direction.Backwards, CancellationToken cancellationToken = default) { var readResult = client.ReadStreamAsync(direction, streamId, direction == Direction.Backwards ? StreamPosition.End : StreamPosition.Start, resolveLinkTos: true, configureOperationOptions: options => options.TimeoutAfter = TimeSpan.FromSeconds(30), cancellationToken: cancellationToken); bool streamExists = false; try { var readState = await readResult.ReadState; streamExists = readState == ReadState.Ok; } #pragma warning disable 168 catch (StreamDeletedException ex) // This happens when the stream is hard-deleted. We don't want to throw in that case #pragma warning restore 168 { streamExists = false; } if (!streamExists) { return(new StreamReadResults(emptyReadResult, false, StreamPosition.FromInt64(-1))); } predicate ??= _ => true; var lastIndex = (await client.ReadStreamAsync(Direction.Backwards, streamId, revision: StreamPosition.End, maxCount: 1, resolveLinkTos: false).FirstAsync(cancellationToken)).OriginalEventNumber; IAsyncEnumerable <StoredEvent> storedEvents; if (direction == Direction.Backwards) { storedEvents = readResult // Trust me, resharper is wrong in this one. Event can be null // ReSharper disable once ConditionIsAlwaysTrueOrFalse .Where(e => e.Event != null) .Select((e, _) => e.Event.ToStoredEvent(stateFactory)) .TakeWhile(e => e.DeserializedEvent is not EntitySoftDeleted) .Where(e => predicate(e)); } else { storedEvents = readResult // Trust me, resharper is wrong in this one. Event can be null // ReSharper disable once ConditionIsAlwaysTrueOrFalse .Where(e => e.Event != null) .Select((e, c) => e.Event.ToStoredEvent(stateFactory)) .Where(e => predicate(e)); } return(new StreamReadResults(storedEvents, true, lastIndex)); }
private static async Task SubscribeToStream(EventStoreClient client) { #region subscribe-to-stream await client.SubscribeToStreamAsync("some-stream", async (subscription, evnt, cancellationToken) => { Console.WriteLine($"Received event {evnt.OriginalEventNumber}@{evnt.OriginalStreamId}"); await HandleEvent(evnt); }); #endregion subscribe-to-stream #region subscribe-to-stream-from-position await client.SubscribeToStreamAsync( "some-stream", StreamPosition.FromInt64(20), EventAppeared); #endregion subscribe-to-stream-from-position #region subscribe-to-stream-live await client.SubscribeToStreamAsync( "some-stream", StreamPosition.End, EventAppeared); #endregion subscribe-to-stream-live #region subscribe-to-stream-resolving-linktos await client.SubscribeToStreamAsync( "$et-myEventType", StreamPosition.Start, EventAppeared, resolveLinkTos : true); #endregion subscribe-to-stream-resolving-linktos #region subscribe-to-stream-subscription-dropped var checkpoint = StreamPosition.Start; await client.SubscribeToStreamAsync( "some-stream", checkpoint, eventAppeared : async(subscription, evnt, cancellationToken) => { await HandleEvent(evnt); checkpoint = evnt.OriginalEventNumber; }, subscriptionDropped : ((subscription, reason, exception) => { Console.WriteLine($"Subscription was dropped due to {reason}. {exception}"); if (reason != SubscriptionDroppedReason.Disposed) { // Resubscribe if the client didn't stop the subscription Resubscribe(checkpoint); } })); #endregion subscribe-to-stream-subscription-dropped }
/// <summary> /// Reads the events. /// </summary> /// <param name="streamName">Name of the stream.</param> /// <param name="fromVersion">From version.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns></returns> public async Task <List <ResolvedEvent> > ReadEvents(String streamName, Int64 fromVersion, CancellationToken cancellationToken) { this.LogInformation($"About to read events from Stream {streamName} fromVersion is {fromVersion}"); List <ResolvedEvent> resolvedEvents = new List <ResolvedEvent>(); EventStoreClient.ReadStreamResult response; List <ResolvedEvent> events; do { response = this.EventStoreClient.ReadStreamAsync(Direction.Forwards, streamName, StreamPosition.FromInt64(fromVersion), 2, resolveLinkTos: true, cancellationToken: cancellationToken); // Check the read state ReadState readState = await response.ReadState; if (readState == ReadState.StreamNotFound) { this.LogInformation($"Read State from Stream {streamName} is {readState}"); return(null); } events = await response.ToListAsync(cancellationToken); resolvedEvents.AddRange(events); fromVersion += events.Count; } while (events.Any()); this.LogInformation($"About to return {resolvedEvents.Count} events from Stream {streamName}"); return(resolvedEvents); }
/// <summary> /// Event Store Initialize (read events and subscribe at the end) /// </summary> private async Task <bool> Initialize(string stream) { var _init = _position; try { var ec_stream = _client.ReadStreamAsync( Direction.Forwards, stream, StreamPosition.FromInt64(_position), maxCount: 100 ); if (await ec_stream.ReadState == ReadState.StreamNotFound) { await _client.SubscribeToStreamAsync(stream, SubscribeReturn); return(false); } foreach (var vnt in ec_stream.ToEnumerable().AsParallel()) { await SubscribeReturn(null, vnt, CancellationToken.None); } await ec_stream.DisposeAsync(); } catch { } if (_init == _position) { await _client.SubscribeToStreamAsync(stream, StreamPosition.FromInt64(_position), SubscribeReturn); return(false); } return(true); }
protected override async Task <EventSubscription> Subscribe( Checkpoint checkpoint, CancellationToken cancellationToken ) { var subTask = checkpoint.Position == null ? EventStoreClient.SubscribeToStreamAsync( _options.StreamName, HandleEvent, _options.ResolveLinkTos, HandleDrop, _options.ConfigureOperation, _options.Credentials, cancellationToken ) : EventStoreClient.SubscribeToStreamAsync( _options.StreamName, StreamPosition.FromInt64((long)checkpoint.Position), HandleEvent, _options.ResolveLinkTos, HandleDrop, _options.ConfigureOperation, _options.Credentials, cancellationToken ); var sub = await subTask.Ignore(); return(new EventSubscription(SubscriptionId, new Stoppable(() => sub.Dispose()))); async Task HandleEvent(EventStore.Client.StreamSubscription _, ResolvedEvent re, CancellationToken ct) { await Handler(AsReceivedEvent(re), ct).Ignore(); } void HandleDrop(EventStore.Client.StreamSubscription _, SubscriptionDroppedReason reason, Exception?ex) => Dropped(EsdbMappings.AsDropReason(reason), ex); ReceivedEvent AsReceivedEvent(ResolvedEvent re) { var evt = DeserializeData( re.Event.ContentType, re.Event.EventType, re.Event.Data, re.Event.EventStreamId, re.Event.EventNumber ); return(new ReceivedEvent( re.Event.EventId.ToString(), re.Event.EventType, re.Event.ContentType, re.Event.Position.CommitPosition, re.Event.EventNumber, re.Event.EventStreamId, re.Event.EventNumber, re.Event.Created, evt // re.Event.Metadata )); } }
public static StreamPosition AsStreamPosition(this StreamReadPosition position) => StreamPosition.FromInt64(position.Value);
public static StreamPosition AsStreamPosition(this StreamTruncatePosition position) => StreamPosition.FromInt64(position.Value);
public override async IAsyncEnumerable <IDomainEventDescriptor> GetAggregateEvents <TKey>(string aggregateType, TKey id, long afterVersion, [EnumeratorCancellation] CancellationToken cancellationToken) { var streamName = GenerateStreamId(aggregateType, id); ReadStreamResult eventStoreDbEvents; if (afterVersion == -1) { eventStoreDbEvents = EventStoreClient.ReadStreamAsync( Direction.Forwards, streamName, StreamPosition.Start, cancellationToken: cancellationToken); } else { eventStoreDbEvents = EventStoreClient.ReadStreamAsync( Direction.Forwards, streamName, StreamPosition.FromInt64(afterVersion + 1), cancellationToken: cancellationToken); } if (await eventStoreDbEvents.ReadState == ReadState.StreamNotFound) { yield break; } var eventDescriptors = eventStoreDbEvents.Select(@event => { var version = @event.Event.EventNumber.ToInt64(); var bsonData = @event.Event.Data; var bsonMetadata = @event.Event.Metadata; var eventType = @event.Event.EventType; DomainEventDescriptor descriptor; using (var stream = bsonData.AsStream()) using (var reader = new BsonDataReader(stream)) { JsonSerializer serializer = new JsonSerializer(); serializer.TypeNameHandling = TypeNameHandling.All; var domainEvent = serializer.Deserialize <IDomainEvent>(reader); descriptor = DomainEventDescriptor.FromStore(aggregateType, id.ToString(), domainEvent, version, eventType); } using (var stream = bsonMetadata.AsStream()) using (var reader = new BsonDataReader(stream)) { JsonSerializer serializer = new JsonSerializer(); serializer.TypeNameHandling = TypeNameHandling.All; var metadata = serializer.Deserialize <IDictionary <string, string> >(reader); foreach (var keyValue in metadata) { descriptor.Metadata.Add(keyValue.Key, keyValue.Value); } } return(descriptor); }); await foreach (var eventDescriptor in eventDescriptors) { yield return(eventDescriptor); } }
public async Task <IEnumerable <DomainEvent> > GetEvents <T>(Guid id, Int32 eventsPerRequest = 100) where T : AggregateRootWithEvents { String streamName = GetStreamId <T>(id); var encoding = new UTF8Encoding(); var firstEvent = _client.ReadStreamAsync(Direction.Forwards, streamName, StreamPosition.Start, 1); var state = await firstEvent.ReadState; if (state == ReadState.StreamNotFound) { return(Array.Empty <DomainEvent>()); } List <DomainEvent> domainEvents = new(); Int32 streamPosition = 0; while (true) { var partialEvents = _client.ReadStreamAsync(Direction.Forwards, streamName, StreamPosition.FromInt64(streamPosition), eventsPerRequest); var items = await partialEvents.ToListAsync(); if (items.Count == 0) { break; } foreach (var item in items) { EventMeta meta = System.Text.Json.JsonSerializer.Deserialize <EventMeta>(new ReadOnlySpan <Byte>(item.Event.Metadata.ToArray())); String content = encoding.GetString(item.Event.Data.ToArray()); var domainEvent = (DomainEvent)JsonConvert.DeserializeObject(content, Type.GetType(meta.BodyType), _jsonSerializerSettings); domainEvents.Add(domainEvent); } streamPosition += eventsPerRequest; } return(domainEvents); }