Exemplo n.º 1
0
        private void DispatchMessages(UndispatchedMessages undispatched, List <Envelope <ICommand> > deserializedCommands = null)
        {
            if (undispatched != null)
            {
                if (deserializedCommands == null)
                {
                    deserializedCommands =
                        this._serializer.Deserialize <IEnumerable <Envelope <ICommand> > >(undispatched.Commands).ToList();
                }

                var originalCommandsCount = deserializedCommands.Count;
                try {
                    while (deserializedCommands.Count > 0)
                    {
                        this._commandBus.Send(deserializedCommands.First());
                        deserializedCommands.RemoveAt(0);
                    }
                }
                catch (Exception) {
                    if (originalCommandsCount != deserializedCommands.Count)
                    {
                        undispatched.Commands = this._serializer.Serialize(deserializedCommands);
                        try {
                            this._context.SaveChanges();
                        }
                        catch (DbUpdateConcurrencyException) {
                        }
                    }
                    throw;
                }

                this._context.Set <UndispatchedMessages>().Remove(undispatched);
                this._context.SaveChanges();
            }
        }
        /// <summary>
        ///     Saves the state of the process manager and publishes the commands in a resilient way.
        /// </summary>
        /// <param name="processManager">The instance to save.</param>
        /// <remarks>
        ///     For explanation of the implementation details, see
        ///     <see cref="http://go.microsoft.com/fwlink/p/?LinkID=258557"> Journey chapter 7</see>.
        /// </remarks>
        public void Save(T processManager)
        {
            var entry = context.Entry(processManager);

            if (entry.State == EntityState.Detached)
            {
                context.Set <T>().Add(processManager);
            }

            var commands = processManager.Commands.ToList();
            UndispatchedMessages undispatched = null;

            if (commands.Count > 0)
            {
                // if there are pending commands to send, we store them as undispatched.
                undispatched = new UndispatchedMessages(processManager.Id)
                {
                    Commands = serializer.Serialize(commands)
                };
                context.Set <UndispatchedMessages>().Add(undispatched);
            }

            try {
                retryPolicy.ExecuteAction(() => context.SaveChanges());
            } catch (DbUpdateConcurrencyException e) {
                throw new ConcurrencyException(e.Message, e);
            }

            try {
                DispatchMessages(undispatched, commands);
            } catch (DbUpdateConcurrencyException) {
                // if another thread already dispatched the messages, ignore
                Trace.TraceWarning("Ignoring concurrency exception while marking commands as dispatched for process manager with ID {0} in Save method.", processManager.Id);
            }
        }
Exemplo n.º 3
0
        public void Save(T processManager)
        {
            DbEntityEntry <T> entry = this._context.Entry(processManager);

            if (entry.State == EntityState.Detached)
            {
                this._context.Set <T>().Add(processManager);
            }

            List <Envelope <ICommand> > commands     = processManager.Commands.ToList();
            UndispatchedMessages        undispatched = null;

            if (commands.Count > 0)
            {
                undispatched = new UndispatchedMessages(processManager.Id)
                {
                    Commands = this._serializer.Serialize(commands)
                };
                this._context.Set <UndispatchedMessages>().Add(undispatched);
            }

            try {
                this._context.SaveChanges();
            }
            catch (DbUpdateConcurrencyException e) {
                throw new ConcurrencyException(e.Message, e);
            }

            try {
                this.DispatchMessages(undispatched, commands);
            }
            catch (DbUpdateConcurrencyException) {
                Trace.TraceWarning("Ignoring concurrency exception while marking commands as dispatched for process manager with ID {0} in Save method.", processManager.Id);
            }
        }
        private void DispatchMessages(UndispatchedMessages undispatched, List <Envelope <ICommand> > deserializedCommands = null)
        {
            if (undispatched != null)
            {
                if (deserializedCommands == null)
                {
                    deserializedCommands = this.serializer.Deserialize <IEnumerable <Envelope <ICommand> > >(undispatched.Commands).ToList();
                }

                var originalCommandsCount = deserializedCommands.Count;
                try
                {
                    while (deserializedCommands.Count > 0)
                    {
                        this.commandBus.Send(deserializedCommands.First());
                        deserializedCommands.RemoveAt(0);
                    }
                }
                catch (Exception)
                {
                    // We catch a generic exception as we don't know what implementation of ICommandBus we might be using.
                    if (originalCommandsCount != deserializedCommands.Count)
                    {
                        // if we were able to send some commands, then updates the undispatched messages.
                        undispatched.Commands = this.serializer.Serialize(deserializedCommands);
                        try
                        {
                            this.context.SaveChanges();
                        }
                        catch (DbUpdateConcurrencyException)
                        {
                            // if another thread already dispatched the messages, ignore and surface original exception instead
                        }
                    }

                    throw;
                }

                // we remove all the undispatched messages for this process manager.
                this.context.Set <UndispatchedMessages>().Remove(undispatched);
                this.context.SaveChanges();
                // this.retryPolicy.ExecuteAction(() => this.context.SaveChanges());
            }
        }
Exemplo n.º 5
0
        public T Find(Expression <Func <T, bool> > predicate, bool includeCompleted = false)
        {
            T processManager = null;

            if (!includeCompleted)
            {
                processManager = this._context.Set <T>().Where(predicate.And(x => x.Completed == false)).FirstOrDefault();
            }

            if (processManager == null)
            {
                processManager = this._context.Set <T>().Where(predicate).FirstOrDefault();
            }

            if (processManager != null)
            {
                UndispatchedMessages undispatchedMessages = this._context.Set <UndispatchedMessages>().Find(processManager.Id);
                try {
                    this.DispatchMessages(undispatchedMessages);
                }
                catch (Exception ex) {
                    Trace.TraceWarning(
                        "Concurrency exception while marking commands as dispatched for process manager with ID {0} in Find method.",
                        processManager.Id);

                    this._context.Entry(undispatchedMessages).Reload();
                    undispatchedMessages = this._context.Set <UndispatchedMessages>().Find(processManager.Id);

                    this.DispatchMessages(undispatchedMessages);
                }

                if (!processManager.Completed || includeCompleted)
                {
                    return(processManager);
                }
            }

            return(null);
        }