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 override StreamMetadata Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { int? maxCount = null; TimeSpan? maxAge = null, cacheControl = null; StreamPosition?truncateBefore = null; StreamAcl? acl = null; using var stream = new MemoryStream(); using var customMetadataWriter = new Utf8JsonWriter(stream); if (reader.TokenType != JsonTokenType.StartObject) { throw new InvalidOperationException(); } customMetadataWriter.WriteStartObject(); while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { break; } if (reader.TokenType != JsonTokenType.PropertyName) { throw new InvalidOperationException(); } switch (reader.GetString()) { case SystemMetadata.MaxCount: if (!reader.Read()) { throw new InvalidOperationException(); } maxCount = reader.GetInt32(); break; case SystemMetadata.MaxAge: if (!reader.Read()) { throw new InvalidOperationException(); } var int64 = reader.GetInt64(); maxAge = TimeSpan.FromSeconds(int64); break; case SystemMetadata.CacheControl: if (!reader.Read()) { throw new InvalidOperationException(); } cacheControl = TimeSpan.FromSeconds(reader.GetInt64()); break; case SystemMetadata.TruncateBefore: if (!reader.Read()) { throw new InvalidOperationException(); } var value = reader.GetInt64(); truncateBefore = value == long.MaxValue ? StreamPosition.End : StreamPosition.FromInt64(value); break; case SystemMetadata.Acl: if (!reader.Read()) { throw new InvalidOperationException(); } acl = StreamAclJsonConverter.Instance.Read(ref reader, typeof(StreamAcl), options); break; default: customMetadataWriter.WritePropertyName(reader.GetString() !); reader.Read(); switch (reader.TokenType) { case JsonTokenType.Comment: customMetadataWriter.WriteCommentValue(reader.GetComment()); break; case JsonTokenType.String: customMetadataWriter.WriteStringValue(reader.GetString()); break; case JsonTokenType.Number: customMetadataWriter.WriteNumberValue(reader.GetDouble()); break; case JsonTokenType.True: case JsonTokenType.False: customMetadataWriter.WriteBooleanValue(reader.GetBoolean()); break; case JsonTokenType.Null: reader.Read(); customMetadataWriter.WriteNullValue(); break; default: throw new ArgumentOutOfRangeException(); } break; } } customMetadataWriter.WriteEndObject(); customMetadataWriter.Flush(); stream.Position = 0; return(new StreamMetadata(maxCount, maxAge, truncateBefore, cacheControl, acl, JsonDocument.Parse(stream))); }
public static StreamPosition ParseStreamPosition(this ReadOnlyMemory <byte> json) { var checkPoint = json.ParseJson <string>(); return(StreamPosition.FromInt64(int.Parse(checkPoint))); }