Пример #1
0
        /// <inheritdoc />
        public async Task Handle(RetroactiveCommand <TCommand> iCommand)
        {
            if (iCommand.Timestamp == default)
            {
                iCommand.StoreInLog = false;
                await _handler.Handle(iCommand.Command);

                return;
            }

            _log.StopWatch.Start($"{nameof(RetroactiveCommandHandler<TCommand>)}");
            iCommand.Command.Timestamp    = iCommand.Timestamp;
            iCommand.Command.UseTimestamp = true;
            var time = iCommand.Timestamp;

            _log.StopWatch.Start("GetChanges_1");
            var changes = await _retroactive.GetChanges(iCommand.Command, time);

            _log.StopWatch.Stop("GetChanges_1");

            if (changes.Count == 0)
            {
                _log.StopWatch.Stop($"{nameof(RetroactiveCommandHandler<TCommand>)}");
                iCommand.StoreInLog = false;
                return;
            }

            _log.StopWatch.Start("TryInsert_1");
            var invalidEvents = await _retroactive.TryInsert(changes, time);

            _log.StopWatch.Stop("TryInsert_1");

            if (invalidEvents.Count > 0)
            {
                var commands = await RollbackEvents(invalidEvents);

                changes = await _retroactive.GetChanges(iCommand.Command, time);

                await _retroactive.TryInsert(changes, time);

                foreach (var c in commands)
                {
                    _log.Debug($"Replaying command {c.GetType().GetFriendlyName()} with timestamp {c.Timestamp}");
                    await _retroactive.ReplayCommand(c);
                }
            }

            await _commandLog.AppendCommand(iCommand.Command);

            iCommand.EventType = iCommand.Command.EventType;
            _messageQueue.Alert(new InvalidateProjections());
            _log.StopWatch.Stop($"{nameof(RetroactiveCommandHandler<TCommand>)}");
        }
Пример #2
0
        /// <inheritdoc />
        /// <summary>
        /// Wrap the handler and redirect all exception to <see cref="IErrorLog"/>
        /// </summary>
        public async Task Handle(T command)
        {
            _log.Trace($"{command.GetType().Name}", this);
            var timeline = _timeline.Id;

            if (!(command is IRetroactiveCommand) && command.Timestamp == default)
            {
                command.Timestamp = _timeline.Now;
            }
            if (command.LocalId == default)
            {
                command.LocalId = new EventId(Configuration.ReplicaName, command.Timestamp);
            }
            if (command.OriginId == default)
            {
                command.OriginId = new EventId(Configuration.ReplicaName, command.Timestamp);
            }
            command.Timeline = timeline;

            try
            {
                await _handler.Handle(command);

                if (command.StoreInLog && !command.Pure)
                {
                    await _commandLog.AppendCommand(command);
                }
            }
            catch (Exception e)
            {
                _errorLog.Add(e);

                // check that we didn't end up on wrong timeline
                if (_timeline.Id != timeline)
                {
                    var tException = new InvalidOperationException($"Execution started on {timeline} but ended on {_timeline.Id}");
                    _errorLog.Add(tException);

                    // throw tException;
                    await _branchManager.Branch(timeline);
                }

                await _commandLog.AddFailedCommand(command);
            }
        }