public async Task AppendAsync(
            IAggregateId aggregateId,
            IReadOnlyList <IDomainEvent> domainEvents,
            long expectedVersion)
        {
            if (domainEvents.Count > 0)
            {
                var connection = await _connectionProvider.GrabConnection();

                var results = await connection.ConditionalAppendToStreamAsync(
                    aggregateId.ToStreamName(_eventStoreName),
                    expectedVersion,
                    domainEvents.Select(e => e.ToEventData()));

                switch (results.Status)
                {
                case ConditionalWriteStatus.Succeeded:
                    break;

                case ConditionalWriteStatus.VersionMismatch:
                    throw new VersionMismatchException(aggregateId.ToStreamName(_eventStoreName), expectedVersion);

                case ConditionalWriteStatus.StreamDeleted:
                    throw new StreamDeletedException(aggregateId.ToStreamName(_eventStoreName));

                default:
                    throw new ArgumentOutOfRangeException(nameof(results.Status), results.Status.ToString());
                }
            }
        }
        public async Task <IReadOnlyList <IDomainEvent> > AsyncLoadAllEventsFor(IAggregateId aggregateId)
        {
            var connection = await _connectionProvider.GrabConnection();

            var resolvedEvents = await connection.ReadAllStreamEventsForward(aggregateId.ToStreamName(_eventStoreName));

            return(resolvedEvents.Select(e => e.Event.ToDomainEvent()).ToList());
        }
 public Task <Result <T> > Get <T>(IAggregateId aggregateId) where T : AggregateRoot, new() =>
 _aggregateCache.TryFetch(aggregateId)
 .Unwrap(
     cachedAggregate => cachedAggregate.TryTakeValue <T>()
     .Unwrap(
         aggregate => Task.FromResult(Result.Ok(aggregate)),
         () => _store.Get <T>(aggregateId)),
     () => _store.Get <T>(aggregateId));
示例#4
0
        public TestCommand(IAggregateId id)
        {
            var c = Guid.NewGuid();

            this.CorrelationId = c;
            this.CausationId   = c;
            AggregateId        = id;
        }
示例#5
0
 /// <summary>
 /// Retrieves existing aggregate from the store and executes the <see cref="aggregateTransformer"/> in
 /// order to pass some command to the aggregate. As a result of <see cref="aggregateTransformer"/> execution
 /// all changes of the aggregate will be persisted in the database.
 /// </summary>
 /// <param name="store"><see cref="IStore"/> instance which is used to transform the aggregate.</param>
 /// <param name="aggregateId">Unique ID of an aggregate.</param>
 /// <param name="aggregateTransformer">Generic transformer function that will be called if aggregate exists.</param>
 /// <returns>Returns success if aggregate has been found and transformer executed without errors.</returns>
 public static Task <Result> Borrow <T>(
     this IStore store,
     IAggregateId aggregateId,
     Func <T, Result <T> > aggregateTransformer)
     where T : AggregateRoot, new()
 {
     return(store.Borrow <T>(aggregateId, aggregate => Task.FromResult(aggregateTransformer(aggregate))));
 }
示例#6
0
 /// <summary>
 /// Borrow method with async aggregate transformer.
 /// </summary>
 public static Task <Result> Borrow <T>(
     this IStore store,
     IAggregateId aggregateId,
     Func <T, Task <Result <T> > > aggregateTransformer)
     where T : AggregateRoot, new() =>
 store.Get <T>(aggregateId)
 .OnSuccess(aggregateTransformer)
 .OnSuccess(aggregate => store.SaveChanges(aggregate))
 .OnFailure(
     AggregateVersionMismatchError,
     () => store.Borrow(aggregateId, aggregateTransformer));
示例#7
0
 public static IEvent AddTestMetaData <TState>(this IEvent @event, IAggregateId id, int version = 0)
 {
     var(aggregateName, streamName) = typeof(TState).Name.AsStreamName(id);
     if (@event.Meta == null)
     {
         @event.Meta = new Dictionary <string, string>();
     }
     @event.Tap(e => e.Meta.AddTypeInfo(e));
     @event.Meta.AddMetaData(version, streamName, aggregateName, new TestCommand(id));
     @event.Meta["test.statetype"] = typeof(TState).AssemblyQualifiedName;
     return(@event);
 }
示例#8
0
        public async Task <Result <T> > Get <T>(IAggregateId aggregateId) where T : AggregateRoot, new()
        {
            var domainEvents = await _eventStoreAppender.AsyncLoadAllEventsFor(aggregateId);

            if (domainEvents.Count > 0)
            {
                var aggregateRoot = ReconstructAggregateFrom <T>(domainEvents);
                return(Ok(aggregateRoot));
            }

            return(Fail <T>(AggregateNotFoundInStore(aggregateId.Id)));
        }
        public Task <Result <T> > Get <T>(IAggregateId aggregateId) where T : AggregateRoot, new()
        {
            if (!_domainEventsPerAggregate.TryGetValue(aggregateId.Id, out var domainEvents))
            {
                return(Task.FromResult(Fail <T>(AggregateNotFoundInStore(aggregateId.Id))));
            }

            var optionalAggregateRoot = ReconstructAggregateFrom <T>(domainEvents);

            return(optionalAggregateRoot.Unwrap(
                       aggregateRoot => Task.FromResult(Ok(aggregateRoot)),
                       () => throw new InvalidOperationException($"Unable to find any events for aggregate with ID '{aggregateId}'.")));
        }
示例#10
0
        public List <IDomainEvent> GetAll(IAggregateId aggregateId)
        {
            var file         = File.ReadAllLines(GetFileName(aggregateId.Value));
            var domainEvents = new List <IDomainEvent>();

            foreach (var line in file)
            {
                var domainEvent = JsonConvert.DeserializeObject <IDomainEvent>(line, _jsonSerializerSettings);

                if (domainEvent == null)
                {
                    continue;
                }

                domainEvents.Add(domainEvent);
            }

            return(domainEvents);
        }
示例#11
0
        //public void Add(EventsWrapper eventsWrapper)
        //{
        //    if (_dictionary.ContainsKey(eventsWrapper.AggregateId))
        //    {
        //        var domainEvents = _dictionary[eventsWrapper.AggregateId];
        //        var sequenceId = domainEvents.Count;
        //        if (sequenceId >= eventsWrapper.SequenceId) throw new SequenceAlreadyStoredException();

        //        domainEvents.AddRange(eventsWrapper.DomainEvents);
        //        return;
        //    }

        //    foreach (var domainEvent in eventsWrapper.DomainEvents)
        //    {
        //        _dictionary.Add(eventsWrapper.AggregateId, new List<IDomainEvent> { domainEvent });
        //    }
        //}

        public void Add(IDomainEvent domainEvent, int sequenceId)
        {
            IAggregateId aggregateId = domainEvent.GetAggregateId();

            if (_dictionary.ContainsKey(aggregateId))
            {
                var domainEvents = _dictionary[aggregateId];
                if (domainEvents.Count >= sequenceId)
                {
                    throw new SequenceAlreadyStoredException();
                }

                domainEvents.Add(domainEvent);
                return;
            }

            _dictionary.Add(aggregateId, new List <IDomainEvent> {
                domainEvent
            });
        }
        public List <IDomainEvent> GetAll(IAggregateId aggregateId)
        {
            var connection = Connection();
            var readEvents = connection.ReadStreamEventsForwardAsync("newstream", 0, 10, true).Result;

            connection.Close();

            List <IDomainEvent> domainEvents = new List <IDomainEvent>();

            foreach (var evt in readEvents.Events)
            {
                var domainEvent = JsonConvert.DeserializeObject <IDomainEvent>(Encoding.UTF8.GetString(evt.Event.Data),
                                                                               _jsonSerializerSettings);
                if (domainEvent == null)
                {
                    continue;
                }

                domainEvents.Add(domainEvent);
            }

            return(domainEvents);
        }
示例#13
0
 public static void Given <TState>(this ITestContext context, IAggregateId id, params EventRecord[] events)
 => context.Given(events.Select(e => EventEnvelope.Create(id.Id, e).AddTestMetaData <TState>(id)).ToArray());
示例#14
0
 public TestEvent(IAggregateId id) : this(id.Id)
 {
 }
 public static string ToStreamName(this IAggregateId aggregateId, string eventStoreName)
 => $"{eventStoreName}|{aggregateId.TypeName}|{aggregateId.Id}";
示例#16
0
 private int GetSequenceId(IAggregateId aggregateId)
 {
     return(File.Exists(GetFileName(aggregateId.Value))
         ? File.ReadAllLines(GetFileName(aggregateId.Value)).Length
         : 0);
 }
示例#17
0
 protected Aggregate(IAggregateId rootId)
 {
     this.RootId = rootId;
 }
示例#18
0
 public int CompareTo(IAggregateId other) => string.Compare(Id, other.Id, StringComparison.Ordinal);
示例#19
0
 public void Clear(IAggregateId aggregateId)
 {
     File.Delete(GetFileName(aggregateId.Value));
 }
示例#20
0
 public static void Given <TState>(this ITestContext context, IAggregateId id, params IEvent[] events)
 => context.Given(events.Select(e => e.AddTestMetaData <TState>(id)).ToArray());
示例#21
0
 public static async Task SaveAsync(this IStateStore stateManager, IAggregateId aggregateId, object state, long version, IEvent[] events, Type type)
 {
     var mi = typeof(IStateStore).GetMethod("SaveAsync").MakeGenericMethod(type);
     await mi.InvokeAsync <bool>(stateManager, d => true, false, aggregateId, state, version, events);
 }
 public void Clear(IAggregateId aggregateId)
 {
     throw new NotImplementedException();
 }
示例#23
0
 public List <IDomainEvent> GetAll(IAggregateId aggregateId)
 {
     return(_dictionary.ContainsKey(aggregateId)
         ? _dictionary[aggregateId]
         : new List <IDomainEvent>());
 }
示例#24
0
 public ItemAddedEvent(IAggregateId aggregateId)
 {
     this.AggregateId = Guid.Parse(aggregateId.ToString());
 }
示例#25
0
 public WaitingOrder(IAggregateId id, int numberColis)
 {
     Id          = id;
     NumberColis = numberColis;
 }
示例#26
0
 public static Task <T> GetAsync <T, TStream>(this IEventStore store, IAggregateId id)
     where T : class, new()
 => store.GetAsync <T>(typeof(TStream).Name.AsStreamName(id).StreamName);
示例#27
0
        public static async Task <(object Value, long Version)> GetAsync(this IStateStore stateManager, Type type, IAggregateId aggregateId)
        {
            var mi = typeof(IStateStore).GetMethod("GetAsync").MakeGenericMethod(type);

            return(await mi.InvokeAsync <(object, long)>(stateManager, d => (d.Item1, d.Item2), true, aggregateId));
        }
示例#28
0
 protected MongoAggregate(IAggregateId rootId)
     : base(rootId)
 {
 }
示例#29
0
 public void Clear(IAggregateId aggregateId)
 {
     _dictionary.Remove(aggregateId);
 }
 public async Task <WorkItemReadModel> Find(IAggregateId id)
 {
     return(await readDatabase.WorkItems.FirstOrDefaultAsync(x => x.Id == id.Value));
 }