Пример #1
0
        /// <summary>
        /// Execute a process transaction
        /// Warning: you need to execute this method inside a Transaction (TransactionScope)
        /// this is how you control if the changes will be saved to the db.
        /// @param persMode - persistence mode
        ///
        /// assume we have all process tasks in a single record
        /// so when performing modification, we need to limit our scope to that record (this process instance)
        /// and all messages leaving the process will be handled async
        /// so we divide our messages between in-process and inter-process
        /// inter-process are always async
        /// in-process are sync when they're task control messages
        /// async when they are from send/receive message tasks (hmmm, this doesn't really matter when in proc)
        ///
        /// what about transactions?
        /// - we assume we're already inside a system transaction
        /// - we can get an external db connection. If we don't get it, we need to open it.
        /// - process session
        /// - other components should have an option to be notified about commit - use system.transactions api...
        /// </summary>
        public void RunProcessTransaction(TaskPersistenceMode persMode, Action <ProcessSession> act)
        {
            if (ProcessSession.Current != null)
            {
                act(ProcessSession.Current);
                return;
            }

            Queue <ProcessMessage> outgoing = null;

            InSystemTransaction(() =>
            {
                InDbTransaction(SessionFactory, dbs =>
                {
                    var pess             = TaskPersister.OpenSession(dbs);
                    pess.PersistenceMode = persMode;
                    var ps = new ProcessSession(pess, MessageBus, ServiceResolver);
                    try
                    {
                        ProcessSession.Current = ps;
                        ps.MessageBus          = MessageBus;
                        ps.TaskPersister       = pess;
                        act(ps);
                        PumpMessages(ps);
                        outgoing = ps.AsyncQueue;
                    }
                    finally
                    {
                        ProcessSession.Current = null;
                        ps.Dispose();
                    }
                    pess.SaveChanges();
                    pess.Dispose();
                });
            });

            if (outgoing != null)
            {
                foreach (var pm in outgoing)
                {
                    SendLocalAsyncMessage(pm);
                }
            }
        }
Пример #2
0
        protected void PumpMessages(ProcessSession ps)
        {
            var queue = ps.SyncQueue;

            while (queue.Count > 0)
            {
                var m = queue.Dequeue();
                if (m is TaskExecEvent)
                {
                    var te = m as TaskExecEvent;
                    if (te.FromTaskInstanceId == te.FromProcessInstanceId || InstanceId.IsSameProcessInstance(te.ParentTaskInstanceId, te.FromProcessInstanceId))
                    {
                        DeliverTaskExecEvent(te);
                    }
                    else
                    {
                        MessageBus.Notify(te);
                    }
                }
                else if (m is TaskControlCommand)
                {
                    var tc = m as TaskControlCommand;
                    if (InstanceId.IsSameProcessInstance(tc.FromProcessInstanceId, tc.ToTaskInstanceId))
                    {
                        DeliverTaskControlMessage(tc);
                    }
                    else
                    {
                        MessageBus.Notify(tc);
                    }
                }
                else
                {
                    throw new Exception("Unexpected message in queue");
                }
            }
        }