Exemple #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)
                {
                    // 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.SerializeToString(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.retryPolicy.ExecuteAction(() => this.context.SaveChanges());
            }
        }
Exemple #2
0
        /// <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 = this.context.Entry(processManager);

            if (entry.State == EntityState.Detached)
            {
                this.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 = this.serializer.SerializeToString(commands)
                };
                this.context.Set <UndispatchedMessages>().Add(undispatched);
            }

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

            try
            {
                this.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);
            }
        }