예제 #1
0
 public Task <WriteResult> Append(IEnumerable <IDomainEvent> events, Maybe <long> expectedVersion = default)
 {
     return(_store.AppendToStreamAsync(
                Id,
                expectedVersion.OrElse(ExpectedVersion.NoStream),
                events.Select(e => _serializer.Serialize(e, Guid.NewGuid(), _metadataContext.GetMetadata()))));
 }
예제 #2
0
        public static async Task ExecuteAsync <TState>(IEventStore store, ICommand command, Func <TState, IEvent[]> action, Func <IEvent[], Task> pub)
            where TState : class, new()
        {
            if (command.CorrelationId == default(Guid))
            {
                throw new ArgumentException("CorrelationId required");
            }

            var aggregateName = typeof(TState).Name.Replace("State", "Aggregate").ToLower();
            var streamName    = $"{aggregateName}-{command.AggregateId}";
            var happend       = await store.LoadEventStreamAsync(streamName, 0);

            var state  = happend.Events.Rehydrate <TState>();
            var events = action(state);

            events
            .Where(x => x.Meta == null)
            .ForEach(x => x.Meta = new Dictionary <string, string>());

            events
            .ForEach(x => x
                     .Tap(e => e.Meta.AddMetaData(happend.Version + 1, streamName, aggregateName, command))
                     .Tap(e => e.Meta.AddTypeInfo(e))
                     );

            if (events.Any())
            {
                await store.AppendToStreamAsync(streamName, events.Last().GetVersion(), events);
            }

            await pub(events);             //need to always execute due to locks
        }
예제 #3
0
        public async Task <bool> SaveOrder(EventUserInfo eventUserInfo, Order aggregate, OrderSnapshot snapshot = null)
        {
            if (aggregate.Changes.Any())
            {
                var streamId = aggregate.Id.ToString();

                // save all events
                bool savedEvents = await _eventStore.AppendToStreamAsync(eventUserInfo, streamId,
                                                                         aggregate.Version,
                                                                         aggregate.Changes);

                // save snapshot
                if (savedEvents && snapshot != null && _snapshotStore != null)
                {
                    await SaveOrderSnapshot(snapshot);
                }
                return(savedEvents);
            }
            return(true);
        }
예제 #4
0
        public async Task <bool> SaveMeterAsync(Meter meter)
        {
            if (meter.Changes.Any())
            {
                var streamId = $"meter:{meter.MeterId}";

                return(await _eventStore.AppendToStreamAsync(
                           streamId,
                           meter.Version,
                           meter.Changes));
            }

            return(true);
        }
예제 #5
0
        /// <summary>
        /// Commits any pending events previously appended with <see cref="Append{T}"/> to the
        /// <see cref="IEventStore"/> specified by <paramref name="store"/>, and clears the queue of pending events.
        /// </summary>
        /// <param name="store">The <see cref="IEventStore"/> to store events in.</param>
        /// <param name="configuration">The configuration of the aggregate.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>A <see cref="Task{TResult}"/></returns>
        /// <exception cref="InvalidOperationException">
        /// If there are no pending events, previously appended with <see cref="Append{T}"/>, to commit.
        /// </exception>
        /// <remarks>
        /// Intended to be wrapped by a public member on the aggregate, in order to keep the aggregate configuration
        /// private, like so:
        /// <code>
        /// public sealed class Goat : Aggregate&lt;GoatId, Goat&gt;
        /// {
        ///     private static readonly AggregateConfiguration&lt;GoatId, Goat&gt; Configuration =
        ///         new AggregateConfiguration&lt;GoatId, Goat&gt;("goat");
        ///
        ///     public Task CommitAsync(IEventStore store) => CommitAsync(store, Configuration);
        /// }
        /// </code>
        /// </remarks>
        protected internal async Task CommitAsync(
            IEventStore store,
            AggregateConfiguration <TIdentity, TAggregate> configuration,
            CancellationToken cancellationToken = default
            )
        {
            if (_pendingEvents.Count == 0)
            {
                throw new InvalidOperationException("There are no pending events to commit");
            }

            var pendingEvents = _pendingEvents.ToArray();
            await store.AppendToStreamAsync(Id, configuration, _versionNumber, pendingEvents, cancellationToken);

            _versionNumber += _pendingEvents.Count;
            _pendingEvents.Clear();
        }
예제 #6
0
        public static async Task <long> AppendToStreamAsync(this IEventStore store, string streamName, params IEvent[] events)
        {
            var r = await store.LoadEventStreamAsync(streamName, 0); //TODO optimize :)

            return(await store.AppendToStreamAsync(streamName, r.Version, events));
        }