コード例 #1
0
        public void Update(DailyTaskId Id, Action <DailyTaskAggregate> execute)
        {
            while (true)
            {
                EventStream        eventStream = _eventStore.LoadEventStream(Id);
                DailyTaskAggregate dailyTask   = new DailyTaskAggregate(eventStream.Events, goalService);
                execute(dailyTask);

                try
                {
                    _eventStore.AppendToStream(Id, eventStream.Version, dailyTask.Changes);
                    return;
                }
                catch (OptimisticConcurrencyException ex)
                {
                    foreach (var dailyTaskEvent in dailyTask.Changes)
                    {
                        foreach (var actualEvent in ex.ActualEvents)
                        {
                            if (ConflictsWith(dailyTaskEvent, actualEvent))
                            {
                                var msg = string.Format("Conflict between {0} and {1}",
                                                        dailyTaskEvent, actualEvent);
                                throw new RealConcurrencyException(msg, ex);
                            }
                        }
                    }
                    _eventStore.AppendToStream(Id, ex.ActualVersion, dailyTask.Changes);
                }
            }
        }
コード例 #2
0
        public Result <object> When(CreateProductCatalog cmd)
        {
            while (true)
            {
                var productCatalog = _factory.Create <ProductCatalogAggregate>(cmd.Id);

                try
                {
                    _eventStore.AppendToStream <ProductCatalogAggregate>(cmd.Id, productCatalog.Version,
                                                                         productCatalog.Changes);
                    return(new Result <object>(null, new List <Exception>()));
                }
                catch (EventStoreConcurrencyException ex)
                {
                    HandleConcurrencyException(ex, productCatalog);
                    return(new Result <object>(null, new List <Exception>()
                    {
                        ex
                    }));
                }
                catch (Exception)
                {
                    throw;
                }
            }
        }
コード例 #3
0
        public void Update(GoalId Id, Action <GoalAggreagate> execute)
        {
            while (true)
            {
                EventStream    eventStream = _eventStore.LoadEventStream(Id);
                GoalAggreagate goal        = new GoalAggreagate(eventStream.Events);
                execute(goal);

                try
                {
                    _eventStore.AppendToStream(Id, eventStream.Version, goal.Changes);
                    return;
                }
                catch (OptimisticConcurrencyException ex)
                {
                    foreach (var goalEvent in goal.Changes)
                    {
                        foreach (var actualEvent in ex.ActualEvents)
                        {
                            if (ConflictsWith(goalEvent, actualEvent))
                            {
                                var msg = string.Format("Conflict between {0} and {1}",
                                                        goalEvent, actualEvent);
                                throw new RealConcurrencyException(msg, ex);
                            }
                        }
                    }
                    _eventStore.AppendToStream(Id, ex.ActualVersion, goal.Changes);
                }
            }
        }
コード例 #4
0
        // method with direct call, as illustrated in the IDDD Book

        // Step 1: LockCustomerForAccountOverdraft method of

        // Customer Application Service is called

        public void LockCustomerForAccountOverdraft(CustomerId customerId, string comment)
        {
            // Step 2.1: Load event stream for Customer, given its id
            var stream = _eventStore.LoadEventStream(customerId);
            // Step 2.2: Build aggregate from event stream
            var customer = new Customer(stream.Events);

            // Step 3: call aggregate method, passing it arguments and pricing domain service
            customer.LockForAccountOverdraft(comment, _pricingService);
            // Step 4: commit changes to the event stream by id
            _eventStore.AppendToStream(customerId, stream.Version, customer.Changes);
        }
コード例 #5
0
        public void Execute <TIdent>(IEventStore eventStorage, TIdent id, Action <TAggregateRoot> execute) where TIdent : IIdentity
        {
            if (eventStorage == null)
            {
                throw new ArgumentNullException("eventStorage");
            }

            if (id == null || id.Equals(default(TIdent)))
            {
                throw new ArgumentException("id is null or default value", "id");
            }

            // Load event stream from the store
            var stream = eventStorage.LoadEventStream(id);

            // create new Customer aggregate from the history
            var aggregate = new TAggregateRoot();

            aggregate.LoadsFromHistory(stream.Events);

            // execute delegated action
            Logger.DebugFormat("Executing Update on aggregate {0}", aggregate);
            execute(aggregate);

            // append resulting changes to the stream, expect the same version loaded before applying ddd logic
            if (aggregate.Changes.Any())
            {
                Logger.DebugFormat("Saving {0} uncommited events on aggregate {1}", aggregate.Changes.Count, aggregate);
                eventStorage.AppendToStream(id, stream.Version, aggregate.Changes);
            }

            Logger.DebugFormat("Finished Update on {0}", aggregate);
        }
 private static async Task AppendEvents(IEventStore eventStore, string streamId, int numberOfEvents)
 {
     for (int i = 0; i < numberOfEvents; i++)
     {
         var newStreamEvent = new NewStreamEvent(Guid.NewGuid(), "MyEvent", "{}");
         await eventStore.AppendToStream(streamId, ExpectedVersion.Any, newStreamEvent);
     }
 }
コード例 #7
0
 public static Task AppendToStream(
     this IEventStore eventStore,
     string streamId,
     int expectedVersion,
     IEnumerable <NewStreamEvent> events)
 {
     return(eventStore.AppendToStream(streamId, expectedVersion, events.ToArray()));
 }
コード例 #8
0
 public static Task AppendToStream(
     this IEventStore eventStore,
     string streamId,
     int expectedVersion,
     NewStreamEvent newStreamEvent)
 {
     return(eventStore.AppendToStream(streamId, expectedVersion, new[] { newStreamEvent }));
 }
コード例 #9
0
ファイル: ItemDetails.cshtml.cs プロジェクト: spinakr/ting
        public void OnPost(Guid itemId, string newLocation)
        {
            var eventStream = _evnetStore.LoadEventStream("items");
            var inventory   = new Inventory(eventStream.Events);

            inventory.UpdateItemLocation(itemId, newLocation);
            _evnetStore.AppendToStream("items", inventory.PendingEvents, eventStream.Version);
        }
コード例 #10
0
        /// <summary>
        /// Extracts changes to the provided aggregate and appends them
        /// to an event stream.
        /// </summary>
        /// <param name="aggregate"></param>
        public async Task Save(TAggregate aggregate)
        {
            var streamName = StreamName(aggregate.Id);
            var changes    = aggregate.GetChanges();

            await _eventStore.AppendToStream(streamName, aggregate.Version, changes, Guid.NewGuid().ToString());

            aggregate.ClearChanges();
        }
コード例 #11
0
        private async Task Append <TAggregate>(TAggregate aggregate, long version)
            where TAggregate : Aggregate
        {
            await eventStore.AppendToStream <TAggregate>(aggregate.Id, aggregate.GetUncommitedChanges(), version);

            logger.LogInformation($"Append the {typeof(TAggregate).Name} aggregate by id: {aggregate.Id} and version {version}.");

            aggregate.Commit();
        }
コード例 #12
0
        private async Task Save(ModeloViewModel viewModel)
        {
            try
            {
                var modelo = viewModel.GetModel();

                try
                {
                    eventStore.AppendToStream(modelo.Codigo, modelo.OriginalVersion, modelo.Changes);

                    //foreach (var @event in modelo.Changes)
                    //{
                    //    await mediator.Send(@event);
                    //}
                }
                catch (EventStoreConcurrencyException ex)
                {
                    foreach (var failedEvent in modelo.Changes)
                    {
                        foreach (var succededEvent in ex.StoreEvents)
                        {
                            if (ConflictsWith(failedEvent, succededEvent))
                            {
                                var message = $"Conflict between ${failedEvent} and {succededEvent}";

                                throw new RealConcurrencyException(ex);
                            }
                        }
                    }

                    eventStore.AppendToStream(modelo.Codigo, ex.StoreVersion, modelo.Changes);
                }

                OnItemSaved(viewModel);

                SetStatus($"Modelo '{modelo.Codigo}' salvo com sucesso.");
            }
            catch (Exception ex)
            {
                viewModel.Error = ex.Message;

                SetStatus(ex.Message);
            }
        }
コード例 #13
0
        /// <summary>
        /// 执行领域事件
        /// </summary>
        public virtual void DoService()
        {
            //1.获得事件流
            var stream = EventStore.LoadEventStream(Entity);

            //2.实体运行领域事件
            Entity.AddEventStream(stream.Events);
            //3.保存事件
            EventStore.AppendToStream(Entity, stream.Version, Entity.Changes);
        }
コード例 #14
0
        /// <inheritdoc />
        public async Task Save <T>(T es)
            where T : class, TEventSourced
        {
            if (es == null)
            {
                return;
            }

            var events = es.GetUncommittedEvents().ToList();

            if (events.Count == 0)
            {
                return;
            }

            var stream = await _streams.Find <T>(es.Id, _timeline.Id) ?? _streams.CreateEmpty(es, _timeline.Id); // _streams.GetOrAdd(es, _timeline.Id);

            if (stream.Version >= 0 && es.Version - events.Count < stream.Version)
            {
                throw new InvalidOperationException($"Stream ( {stream.Key}@{stream.Version} ) is ahead of aggregate root with version {es.Version - events.Count} saving {events.Count} events )");
            }

            foreach (var e in events.Cast <Event>())
            {
                if (e.Timestamp == default)
                {
                    e.Timestamp = _timeline.Now;
                }
                if (e.LocalId == default)
                {
                    e.LocalId = new EventId(Configuration.ReplicaName, e.Timestamp);
                }
                if (e.OriginId == default)
                {
                    e.OriginId = e.LocalId;
                }
                e.Stream   = stream.Key;
                e.Timeline = _timeline.Id;
            }

            await _eventStore.AppendToStream(stream, events);

            if (es is ISaga saga)
            {
                var commands = saga.GetUncommittedCommands();
                foreach (var command in commands)
                {
                    await _bus.CommandAsync(command);
                }
            }
#if USE_ES_CACHE
            _cache[stream.Key] = es;
#endif
        }
コード例 #15
0
        void Update(ICommand <RegistrationId> c, Action <RegistrationAggregate> action)
        {
            var stream = _eventStore.LoadEventStream(c.Id);
            var state  = new RegistrationState(stream.Events);
            var agg    = new RegistrationAggregate(state);

            using (Context.CaptureForThread()) {
                action(agg);
                _eventStore.AppendToStream(c.Id, stream.Version, agg.Changes);
            }
        }
コード例 #16
0
        void Update(ICommand <UserId> c, Action <UserAggregate> action)
        {
            var stream = _store.LoadEventStream(c.Id);
            var state  = new UserState(stream.Events);
            var agg    = new UserAggregate(state);

            using (Context.CaptureForThread()) {
                agg.ThrowOnInvalidStateTransition(c);
                action(agg);
                _store.AppendToStream(c.Id, stream.Version, agg.Changes);
            }
        }
コード例 #17
0
        public CommandEvent When(CreateProductCatalog cmd)
        {
            var productCatalog = _factory.Create <ProductCatalogAggregate>(cmd.Id);

            try
            {
                _eventStore.AppendToStream <ProductCatalogAggregate>(cmd.Id, productCatalog.Version,
                                                                     productCatalog.Changes, productCatalog.DomainEvents.ToArray());

                return(new CommandEvent(OperationStatus.Success));
            }
            catch (EventStoreConcurrencyException ex)
            {
                HandleConcurrencyException(ex, productCatalog);
                return(new CommandEvent(OperationStatus.Success));
            }
            catch (Exception)
            {
                throw;
            }
        }
コード例 #18
0
        void Update(ICommand <SecurityId> c, Action <SecurityAggregate> action)
        {
            var eventStream = _eventStore.LoadEventStream(c.Id);
            var state       = new SecurityState(eventStream.Events);
            var agg         = new SecurityAggregate(state);

            using (Context.CaptureForThread())
            {
                action(agg);
                _eventStore.AppendToStream(c.Id, eventStream.Version, agg.Changes);
            }
        }
コード例 #19
0
        public void SaveModule(Module module)
        {
            if (module.HasNoChanges)
            {
                return;
            }

            DoesModuleExist(module);

            _eventStore.AppendToStream(new EventStream($"module:{module.Id}", module.Version, module.Changes));

            module.Changes.ForEach(@event => _eventPublisher.Publish(@event));
        }
コード例 #20
0
        public IEnumerable <Item> Handle(GetItems query)
        {
            var eventStream = _evnetStore.LoadEventStream("items");
            var inventory   = new Inventory(eventStream.Events);

            if (inventory.Items is null)
            {
                inventory.Init();
                _evnetStore.AppendToStream("items", inventory.PendingEvents, eventStream.Version);
            }

            return(inventory.Items);
        }
コード例 #21
0
        public void Execute <TIdent, TResult, TIdentCreated>(IEventStore eventStorage, TIdent id, Func <TResult, TAggregateRoot> execute, TIdentCreated createId)
            where TIdent : IIdentity
            where TResult : IAggregate, new()
            where TIdentCreated : IIdentity
        {
            if (eventStorage == null)
            {
                throw new ArgumentNullException("eventStorage");
            }

            if (id == null || id.Equals(default(TIdent)))
            {
                throw new ArgumentException("id is null or default value", "id");
            }

            if (createId == null || createId.Equals(default(TIdentCreated)))
            {
                throw new ArgumentException("createid is null or default value", "createId");
            }

            EventStream stream = eventStorage.LoadEventStream(id);

            // create new Customer aggregate from the history
            var aggregate = new TResult();

            aggregate.LoadsFromHistory(stream.Events);

            // execute delegated action
            Logger.DebugFormat("Executing UpdateAndCreateAggregate on aggregate {0}", aggregate);
            TAggregateRoot res = execute(aggregate);

            if (aggregate.Changes.Any())
            {
                throw new Exception("You cannot modify more than one aggregate per command!");
            }

            if (res != null && res.Changes.Any())
            {
                Logger.DebugFormat("Saving {0} uncommited events on result aggregate {1}", res.Changes.Count, res);
                eventStorage.AppendToStream(createId, 0, res.Changes);
                Logger.DebugFormat("Finished Create on {0}", aggregate);
                return;
            }

            throw new InvalidOperationException("No aggregate created on execute");
        }
コード例 #22
0
        public Result Handle(AddNewItemCommand cmd)
        {
            string fileName = null;

            if (cmd.ImageFile is object)
            {
                fileName = SaveFileToDisk(cmd);
            }

            var eventStream = _evnetStore.LoadEventStream("items");
            var inventory   = new Inventory(eventStream.Events);

            inventory.AddNewItem(cmd.ItemName, fileName is null ? "" : $"images/{fileName}");

            _evnetStore.AppendToStream("items", inventory.PendingEvents, eventStream.Version);
            return(Result.Complete());
        }
コード例 #23
0
        private static async Task RunLoadTest(CancellationTokenSource cts, IEventStore eventStore)
        {
            var tasks = new List <Task>();
            int count = -1;

            for (int i = 0; i < Environment.ProcessorCount; i++)
            {
                var taskNumber = i;
                var task       = Task.Run(async() =>
                {
                    while (!cts.IsCancellationRequested)
                    {
                        try
                        {
                            var eventNumber     = Interlocked.Increment(ref count);
                            var newStreamEvents = EventStoreAcceptanceTests
                                                  .CreateNewStreamEvents(eventNumber * 2 + 1, eventNumber * 2 + 2);

                            var info = $"{taskNumber} - {newStreamEvents[0].EventId}," +
                                       $"{newStreamEvents[1].EventId}";

                            Log.Logger.Information($"Begin {info}");
                            await eventStore.AppendToStream(
                                $"stream-1",
                                ExpectedVersion.Any,
                                newStreamEvents,
                                cts.Token);
                            Log.Logger.Information($"End   {info}");
                            Console.Write($"\r{eventNumber*2 + 2}");
                        }
                        catch (Exception ex) when(!(ex is TaskCanceledException))
                        {
                            cts.Cancel();
                            Log.Logger.Error(ex, ex.Message);
                            Console.WriteLine(ex);
                            Console.ReadKey();
                        }
                    }
                }, cts.Token);
                tasks.Add(task);
            }
            await Task.WhenAll(tasks);
        }
コード例 #24
0
            public CloneFlow(string timeline, Time time, IEventStore <T> eventStore)
                : base(Configuration.DataflowOptions)
            {
                _inputBlock = new ActionBlock <IStream>(
                    async s =>
                {
                    var version = await eventStore.GetVersion(s, time);
                    if (version == ExpectedVersion.NoStream)
                    {
                        return;
                    }

                    var clone = s.Branch(timeline, version);
                    await eventStore.AppendToStream(clone);
                    Interlocked.Increment(ref _numberOfStreams);
                }, Configuration.DataflowOptions.ToDataflowBlockOptions(true));     // .ToExecutionBlockOption(true));

                RegisterChild(_inputBlock);
            }
コード例 #25
0
        //Dessa forma, os métodos HasConflict e HandleConcurrencyException podem ser sobrescritos para se adaptar a questões de negócio
        protected virtual void HandleConcurrencyException <TAggregate>(EventStoreConcurrencyException ex, TAggregate root)
            where TAggregate : AggregateRoot <Guid>
        {
            foreach (var changeEvent in root.Changes)
            {
                foreach (var storeEvent in ex.StoreEvents)
                {
                    if (HasConflict(changeEvent, storeEvent))
                    {
                        var msg = string.Format("Conflict between {0} and {1}",
                                                changeEvent, changeEvent);
                        throw new Exception(msg, ex);
                    }
                }
            }

            var actualVersion = root.Version - root.Changes.Count;

            actualVersion += actualVersion;
            _eventStore.AppendToStream <TAggregate>(root.Id, actualVersion, root.Changes, root.DomainEvents.ToArray());
        }
コード例 #26
0
        public void Save <TAggregate>(IAggregateRoot aggregate, int expectedVersion) where TAggregate : IAggregateRoot, new()
        {
            {
                var uncommitedChanges = aggregate.UncommitedChanges;
                if (uncommitedChanges.Any())
                {
                    lock (_lockStorage)
                    {
                        var item = new TAggregate();

                        if (expectedVersion != -1)
                        {
                            item = GetById <TAggregate>(aggregate.Guid);
                            if (item.Version != expectedVersion)
                            {
                                throw new ConcurrencyException($"Aggregate {item.Guid} has been previously modified");
                            }
                        }

                        _eventStore.AppendToStream(uncommitedChanges);
                    }
                }
            }
        }
コード例 #27
0
            public MergeFlow(ITimeline currentBranch, IEventStore <T> eventStore, IStreamLocator streamLocator, bool doMerge)
                : base(Configuration.DataflowOptions)
            {
                _inputBlock = new ActionBlock <IStream>(
                    async s =>
                {
                    var version      = ExpectedVersion.EmptyStream;
                    var parentStream = s.Branch(currentBranch?.Id, ExpectedVersion.EmptyStream);
                    var parent       = s.Parent;
                    while (parent != null && parent.Version > ExpectedVersion.EmptyStream)
                    {
                        parentStream = await streamLocator.Find(parent);
                        version      = parentStream.Version;

                        if (currentBranch != null &&
                            (version > parent.Version && parent.Timeline == currentBranch.Id))
                        {
                            var theseEvents = await eventStore
                                              .ReadStream <IEvent>(parentStream, parent.Version + 1, version - parent.Version)
                                              .Select(e => e.MessageId).ToList();
                            var thoseEvents = await eventStore
                                              .ReadStream <IEvent>(s, parent.Version + 1, version - parent.Version)
                                              .Select(e => e.MessageId).ToList();
                            if (theseEvents.Zip(thoseEvents, (e1, e2) => (e1, e2)).Any(x => x.Item1 != x.Item2))
                            {
                                throw new InvalidOperationException(
                                    $"{currentBranch?.Id} timeline has moved on in the meantime, aborting...( {parentStream.Key} : {version} > {parent.Version} )");
                            }

                            return;
                        }

                        if (s.Version == version)
                        {
                            return;
                        }

                        if (parentStream.Timeline == currentBranch?.Id)
                        {
                            break;
                        }

                        parent = parent.Parent;
                    }

                    if (!doMerge)
                    {
                        return;
                    }

                    Interlocked.Increment(ref _numberOfStreams);

                    var events = await eventStore.ReadStream <IEvent>(s, version + 1, s.Version - version).ToList();
                    foreach (var e in events.OfType <Event>())
                    {
                        e.Stream = parentStream.Key;
                    }

                    Interlocked.Add(ref _numberOfEvents, events.Count);

                    await eventStore.AppendToStream(parentStream, events, false);
                }, Configuration.DataflowOptions.ToDataflowBlockOptions(true));     // .ToExecutionBlockOption(true));

                RegisterChild(_inputBlock);
            }
        public void Handle(User_CreateCommand message)
        {
            var user = new UserAR(message.UserId, message.Name, message.Password);

            _eventStore.AppendToStream(message.UserId, 0, user.Changes);
        }
 public void Save(IAggregateRoot aggregateRoot, IEnumerable <object> uncommitedEvents)
 {
     _eventStore.AppendToStream(aggregateRoot.AggregateId.ToString(), uncommitedEvents);
 }