public async Task <IEnumerable <object> > LoadEvents(string stream, int?version = null) { EventStoreClient.ReadStreamResult response; if (version == null || version == -1) { response = _client .ReadStreamAsync(Direction.Forwards, _tenantPrefix + stream, StreamPosition.Start); } else { response = _client .ReadStreamAsync(Direction.Forwards, _tenantPrefix + stream, Convert.ToUInt64(version)); } if (await response.ReadState == ReadState.StreamNotFound) { return(new List <object>()); } return(await response .Select(e => e.Deserialize()) .ToListAsync()); }
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)); }
public async Task <bool> CheckIfAggrerootExists <T>(Guid id) where T : AggregateRootWithEvents { String streamId = GetStreamId <T>(id); var readResult = _client.ReadStreamAsync(Direction.Forwards, streamId, StreamPosition.Start, 1); return((await readResult.ReadState) == ReadState.Ok); }
public async Task <bool> Exists <TAggregate>(Guid id) where TAggregate : Aggregate { var stream = GetStreamName <TAggregate>(id); var read = _client.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, 1); var readState = await read.ReadState; return(readState != ReadState.StreamNotFound); }
private IAsyncEnumerable <StoredEvent> QueryAsync(string streamName, StreamPosition start, long count, CancellationToken ct = default) { var result = client.ReadStreamAsync( Direction.Forwards, streamName, start, count, resolveLinkTos: true, cancellationToken: ct); return(result.Select(x => Formatter.Read(x, StreamPrefix, serializer))); }
public async Task <bool> StreamExists(StreamName stream, CancellationToken cancellationToken) { var read = _client.ReadStreamAsync( Direction.Backwards, stream, StreamPosition.End, 1, cancellationToken: cancellationToken ); var state = await read.ReadState.NoContext(); return(state == ReadState.Ok); }
/// <summary> /// Runs the health check, returning the status of the component being checked. /// </summary> /// <param name="context">A context object associated with the current execution.</param> /// <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken" /> that can be used to cancel the health check.</param> /// <returns> /// A <see cref="T:System.Threading.Tasks.Task`1" /> that completes when the health check has finished, yielding the status of the component being checked. /// </returns> /// <exception cref="Exception">$all stream not found</exception> public async Task <HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) { try { EventStoreClient client = new EventStoreClient(this.EventStoreClientSettings); EventStoreClient.ReadStreamResult readResult = client.ReadStreamAsync(Direction.Forwards, "$all", StreamPosition.Start, userCredentials: this.UserCredentials, resolveLinkTos: true, cancellationToken: cancellationToken); ReadState readState = await readResult.ReadState; if (readState == ReadState.StreamNotFound) { throw new Exception("$all stream not found"); } return(HealthCheckResult.Healthy()); } catch (Exception ex) { return(new HealthCheckResult(context.Registration.FailureStatus, exception: ex)); } }
public static IApplicationBuilder UseStreamMessages(this IApplicationBuilder builder, EventStoreClient eventStore) { return(builder.MapMethods( "/streams/{streamId}/{streamRevision:int}", (HttpMethod.Get, GetStreamMessage))); async ValueTask <Response> GetStreamMessage(HttpContext context) { var streamId = context.Request.GetStreamId(); var streamRevision = context.Request.GetStreamRevision(); try { var @event = await eventStore.ReadStreamAsync(Direction.Forwards, streamId !, StreamPosition.FromStreamRevision(streamRevision !.Value), 1, resolveLinkTos : false, userCredentials : context.GetUserCredentials(), cancellationToken : context.RequestAborted) .Where(e => e.OriginalEvent.EventNumber == streamRevision) .SingleOrDefaultAsync(context.RequestAborted); return(new HALResponse(StreamMessageRepresentation.Instance, new StreamMessageResource( streamId !, streamRevision !.Value, @event)) { StatusCode = @event.OriginalEvent == null ? HttpStatusCode.NotFound : HttpStatusCode.OK }); } catch (StreamNotFoundException) { return(new HALResponse(StreamMessageRepresentation.Instance, new StreamMessageResource( streamId !, streamRevision !.Value)) { StatusCode = HttpStatusCode.NotFound });
public static async Task <T?> AggregateStream <T>( this EventStoreClient eventStore, Guid id, CancellationToken cancellationToken, ulong?fromVersion = null ) where T : class, IProjection { var readResult = eventStore.ReadStreamAsync( Direction.Forwards, StreamNameMapper.ToStreamId <T>(id), fromVersion ?? StreamPosition.Start, cancellationToken: cancellationToken ); // TODO: consider adding extension method for the aggregation and deserialisation var aggregate = (T)Activator.CreateInstance(typeof(T), true) !; await foreach (var @event in readResult) { var eventData = @event.Deserialize(); aggregate.When(eventData !); } return(aggregate); }
public async Task <KeyValuePair <int, GrainState <T> > > ReadStateFromStorage() { _stream = $"{typeof(T).Name}:{ModelVersion()}:{this.GrainId()}"; var stream = _eventStore.ReadStreamAsync( Direction.Forwards, _stream, StreamPosition.Start); var state = new GrainState <T>(); var version = 0; if (await stream.ReadState != ReadState.StreamNotFound) { await foreach (var resolvedEvent in stream) { var json = Encoding.UTF8.GetString(resolvedEvent.Event.Data.Span); try { var eventObj = _eventSerializer.Deserialize(typeof(T), resolvedEvent.Event.EventType, json); state = state.Apply(eventObj); version++; } catch (Exception ex) { _logger.LogCritical(5004, ex, ex.Message); return(new KeyValuePair <int, GrainState <T> >(-1, new GrainState <T>())); } } } return(new KeyValuePair <int, GrainState <T> >(version, state)); }
public async Task <TEventSourcedAggregate?> GetAsync(TId id, CancellationToken token = default) { var streamName = GetStreamName(id); var readStreamResult = _client.ReadStreamAsync(Direction.Forwards, streamName, StreamPosition.Start, cancellationToken: token); if (await readStreamResult.ReadState is ReadState.StreamNotFound) { return(null); } TEventSourcedAggregate?aggregate = null; await foreach (var resolvedEvent in readStreamResult) { var(@event, metadata) = EventStoreSerializer.Deserialize(resolvedEvent.Event); if (RequestContext.RequestId is not null && RequestContext.RequestId == metadata.CausationId) { throw new DuplicateRequestException(RequestContext.RequestId); } aggregate ??= (TEventSourcedAggregate)Activator.CreateInstance(typeof(TEventSourcedAggregate), true) !; aggregate.ApplyEvent(@event); } return(aggregate); }
private static async Task TestReadFromtombstoned(EventStoreClient client) { var idForTombstoneTest = Guid.NewGuid().ToString(); await client.AppendToStreamAsync(idForTombstoneTest, StreamRevision.FromInt64(-1), new[] { new EventData(Uuid.NewUuid(), "TestType", new byte[] { 0x00 }) }); await client.TombstoneAsync(idForTombstoneTest, StreamState.Any); var testResultNonExistent = client.ReadStreamAsync(Direction.Backwards, Guid.NewGuid().ToString(), StreamPosition.End); var testResult = client.ReadStreamAsync(Direction.Backwards, idForTombstoneTest, StreamPosition.End, configureOperationOptions: o => { o.ThrowOnAppendFailure = false; }); var testState = await testResultNonExistent.ReadState; testState = await testResult.ReadState; }
async Task <IEventStore.StreamEvents> IEventStore.GetStreamEventsAsync(string streamName) { var stream = _client.ReadStreamAsync( Direction.Forwards, streamName, StreamPosition.Start); var loadedEvents = new List <LoadedEvent>(); await foreach (var eventObject in stream) { if (!_externalEventTypes.TryGetValue(eventObject.Event.EventType, out var eventType)) { throw new InvalidOperationException("Unknown event type found"); } var externalEvent = (IDomainEvent?)JsonSerializer.Deserialize(eventObject.Event.Data.Span, eventType); if (externalEvent == null) { throw new InvalidOperationException($"Event cannot be null {eventObject.Event.EventType}"); } if (!_eventsConverter.TryConvert(externalEvent, out var internalEvent)) { throw new InvalidOperationException($"Cannot convert event {eventObject.Event.EventType}"); } loadedEvents.Add(new LoadedEvent( eventObject.Event.Created, internalEvent)); } return(new IEventStore.StreamEvents(loadedEvents.Count, loadedEvents)); }
public async Task <bool> Exists(string steamId) { var result = _eventStoreClient.ReadStreamAsync(Direction.Forwards, steamId, StreamPosition.Start, 1); var state = await result.ReadState; return(state == ReadState.Ok); }
public async ValueTask <Optional <TAggregateRoot> > GetById(string identifier, CancellationToken cancellationToken = default) { var streamName = identifier; if (_unitOfWork.TryGet(streamName, out var a) && a is TAggregateRoot aggregate) { return(new Optional <TAggregateRoot>(aggregate)); } try { await using var events = _eventStore.ReadStreamAsync(Direction.Forwards, streamName, StreamPosition.Start, configureOperationOptions: options => options.TimeoutAfter = TimeSpan.FromMinutes(20), cancellationToken: cancellationToken); aggregate = _factory(); var version = await aggregate.LoadFromHistory(events.Select(e => JsonSerializer.Deserialize(e.OriginalEvent.Data.Span, _messageTypeMapper.Map(e.OriginalEvent.EventType), _serializerOptions))); _unitOfWork.Attach(streamName, aggregate, version); return(aggregate); } catch (StreamNotFoundException) { return(Optional <TAggregateRoot> .Empty); } }
static async Task Main(string[] args) { CancellationTokenSource tokenSource = new CancellationTokenSource(); CancellationToken cancellationToken = tokenSource.Token; #region createClient var settings = EventStoreClientSettings .Create("{connectionString}"); var client = new EventStoreClient(settings); #endregion createClient #region createEvent var evt = new TestEvent { EntityId = Guid.NewGuid().ToString("N"), ImportantData = "I wrote my first event!" }; var eventData = new EventData( Uuid.NewUuid(), "TestEvent", JsonSerializer.SerializeToUtf8Bytes(evt) ); #endregion createEvent #region appendEvents await client.AppendToStreamAsync( "some-stream", StreamState.Any, new[] { eventData }, cancellationToken : cancellationToken ); #endregion appendEvents #region overriding-user-credentials await client.AppendToStreamAsync( "some-stream", StreamState.Any, new[] { eventData }, userCredentials : new UserCredentials("admin", "changeit"), cancellationToken : cancellationToken ); #endregion overriding-user-credentials #region readStream var result = client.ReadStreamAsync( Direction.Forwards, "some-stream", StreamPosition.Start, cancellationToken: cancellationToken); var events = await result.ToListAsync(cancellationToken); #endregion readStream }
public static async Task <StreamSize> GetStreamSize( this EventStoreClient client, string stream ) { var read = client.ReadStreamAsync(Direction.Backwards, stream, StreamPosition.End, 1); var last = await read.ToArrayAsync().ConfigureAwait(false); return(new StreamSize(last[0].OriginalEventNumber.ToInt64())); }
private async Task <IReadOnlyCollection <ResolvedEvent> > GetSnapshotStream(string stream, string entityId, string model) { var streamName = model != null ? $"{stream}-{entityId}-{model}-snapshot" : $"{stream}-{entityId}-snapshot"; var state = _client.ReadStreamAsync( Direction.Backwards, streamName, StreamPosition.End, 1); var readState = await state.ReadState; if (readState == ReadState.StreamNotFound) { return(new List <ResolvedEvent>()); } return(await state.ToListAsync()); }
private void ReadStreamOverridingUserCredentials(EventStoreClient client, CancellationToken cancellationToken) { #region overriding-user-credentials var result = client.ReadStreamAsync( Direction.Forwards, "some-stream", StreamPosition.Start, userCredentials: new UserCredentials("admin", "changeit"), cancellationToken: cancellationToken); #endregion overriding-user-credentials }
private static async Task AppendWithConcurrencyCheck(EventStoreClient client) { #region append-with-concurrency-check var clientOneRead = client.ReadStreamAsync( Direction.Forwards, "concurrency-stream", StreamPosition.Start, configureOperationOptions: options => options.ThrowOnAppendFailure = false); var clientOneRevision = (await clientOneRead.LastAsync()).Event.EventNumber.ToUInt64(); var clientTwoRead = client.ReadStreamAsync(Direction.Forwards, "concurrency-stream", StreamPosition.Start); var clientTwoRevision = (await clientTwoRead.LastAsync()).Event.EventNumber.ToUInt64(); var clientOneData = new EventData( Uuid.NewUuid(), "some-event", Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"clientOne\"}") ); await client.AppendToStreamAsync( "no-stream-stream", clientOneRevision, new List <EventData> { clientOneData }); var clientTwoData = new EventData( Uuid.NewUuid(), "some-event", Encoding.UTF8.GetBytes("{\"id\": \"2\" \"value\": \"clientTwo\"}") ); await client.AppendToStreamAsync( "no-stream-stream", clientTwoRevision, new List <EventData> { clientTwoData }); #endregion append-with-concurrency-check }
async ValueTask <List <object> > GetEvents(string streamName, CancellationToken ct) { await using var readResult = _eventStore.ReadStreamAsync( Direction.Forwards, streamName, StreamPosition.Start, cancellationToken: ct ); return(await readResult .Select(@event => @event.Deserialize()) .ToListAsync(ct)); }
private static async Task ReadFromStreamBackwards(EventStoreClient client) { #region reading-backwards var events = client.ReadStreamAsync( Direction.Backwards, "some-stream", StreamPosition.End); await foreach (var e in events) { Console.WriteLine(Encoding.UTF8.GetString(e.Event.Data.ToArray())); } #endregion reading-backwards }
private static async Task ReadFromStream(EventStoreClient client) { #region read-from-stream var events = client.ReadStreamAsync( Direction.Forwards, "some-stream", StreamPosition.Start); #endregion read-from-stream #region iterate-stream await foreach (var @event in events) { Console.WriteLine(Encoding.UTF8.GetString(@event.Event.Data.ToArray())); } #endregion iterate-stream }
public async Task <IEnumerable <object> > LoadEvents(string streamName) { var response = _client .ReadStreamAsync(Direction.Forwards, ToStreamName(streamName), StreamPosition.Start); var readState = await response.ReadState; if (readState == ReadState.StreamNotFound) { return(new List <object>()); } return(await response .Select(e => e.Deserialize() !) .ToListAsync()); }
public async ValueTask <ulong?> Load(string subscriptionId, CancellationToken ct) { var streamName = GetCheckpointStreamName(subscriptionId); var result = eventStoreClient.ReadStreamAsync(Direction.Backwards, streamName, StreamPosition.End, 1, cancellationToken: ct); if (await result.ReadState == ReadState.StreamNotFound) { return(null); } ResolvedEvent? @event = await result.FirstOrDefaultAsync(ct); return(@event?.Deserialize <CheckpointStored>().Position); }
public async Task <TAggregate> GetByIdAsync <TAggregate>(object id) where TAggregate : IAggregate, new() { var aggregate = new TAggregate(); var streamName = $"{aggregate.Identifier}-{id}"; var events = _eventStoreConnection.ReadStreamAsync(Direction.Forwards, streamName, StreamPosition.Start); await foreach (var evt in events) { var payload = DeserializeEvent(evt); aggregate.ApplyEvent(payload); } return(aggregate); }
public async Task <IEnumerable <Event> > ReadStream(string streamName) { var result = _client.ReadStreamAsync(Direction.Forwards, streamName, StreamPosition.Start); var readState = await result.ReadState; if (readState == ReadState.StreamNotFound) { return(new List <Event>()); } var events = (await result.ToListAsync()) .Select(EventSerializer.Deserialize) .ToList(); return(events); }
public EventStoreAggregate(EventStoreClient eventStore, string stream = InterfaceConst.ESPrime) { _eventStore = eventStore; _stream = stream; var result = _eventStore.ReadStreamAsync(Direction.Forwards, _stream, StreamPosition.Start); if (result.ReadState.Result == ReadState.StreamNotFound) { return; } foreach (var vnt in result.ToEnumerable()) { Events.Add(vnt.To <T>()); } }
private async Task <TAggregate> GetByIdOrDefaultAsync <TAggregate>(string aggregateId, int version) where TAggregate : class, IAggregateRoot, new() { if (version <= 0) { throw new InvalidOperationException("Cannot get version <= 0"); } var streamName = $"{typeof(TAggregate).Name}:{aggregateId}"; TAggregate aggregate = new TAggregate { Version = -1 }; RedisValue value = await Policies.RedisValueFallbackPolicy.ExecuteAsync(() => _cache.StringGetAsync(streamName)); if (value.HasValue) { aggregate = JsonSerializer.Deserialize <TAggregate>(value); } long sliceStart = aggregate.Version + 1; EventStoreClient.ReadStreamResult stream = _eventStoreClient.ReadStreamAsync(Direction.Forwards, streamName, StreamPosition.FromInt64(sliceStart)); if (await stream.ReadState == ReadState.StreamNotFound) { return(null); } await foreach (var @event in stream) { object eventObject = DeserializeEvent(@event.Event.Metadata, @event.Event.Data); Type applyType = typeof(IApply <>).MakeGenericType(eventObject.GetType()); var isAssignableFrom = applyType.IsAssignableFrom(aggregate.GetType()); if (isAssignableFrom) { ((dynamic)aggregate).Apply((dynamic)eventObject); } aggregate.Version++; } aggregate.Context = _context; return(aggregate); }
public static async Task <ulong?> GetPositionToSubscribe(this EventStoreClient client, string stream) { ulong?startPosition = null; try { var last = await client.ReadStreamAsync( Direction.Backwards, stream, StreamPosition.End, 1 ).ToArrayAsync(); startPosition = last[0].OriginalEventNumber; } catch (StreamNotFound) { } return(startPosition); }