Пример #1
0
 public IEnumerable <WorkflowInstanceInfo> GetInstances(WorkflowStatus?filter = null)
 {
     if (null == filter)
     {
         var queryResult = _instanceData.All();
         return(queryResult.Items.EmptyIfNull());
     }
     else
     {
         var qs = new QuerySpecification
         {
             BookMark = new GenericPageBookmark {
                 PageSize = 1000
             },
             Where = new Filter
             {
                 PredicateJoin = PredicateJoin.And,
                 Rules         = new Comparison[]
                 {
                     new Comparison
                     {
                         Data  = filter.Value.EnumName(),
                         Field = "Status",
                         Test  = Test.Equal
                     }
                 }
             }
         };
         var queryResult = _instanceData.Query(qs);
         return(queryResult.Items.EmptyIfNull());
     }
 }
Пример #2
0
        public WorkflowContext(string persistenceContext, string machineContext, string initialState, string repositoryKey)
        {
            _persistenceContext = persistenceContext;
            _machineContext     = machineContext;
            _cachedState        = initialState;

            _machineStateData = Catalog.Preconfigure().ConfigureWorkflowDataRepository <WorkflowMachineState>()
                                .ConfiguredResolve <IDataRepositoryService <WorkflowMachineState,
                                                                            WorkflowMachineState,
                                                                            DataEnvelope <WorkflowMachineState, NoMetadata>,
                                                                            NoMetadata,
                                                                            DatumEnvelope <WorkflowMachineState, NoMetadata>,
                                                                            NoMetadata> >
                                    (repositoryKey);

            WorkflowMachineState current = null;

            var qs = new QuerySpecification
            {
                BookMark = new GenericPageBookmark {
                    PageSize = 100
                },
                Where = new Filter
                {
                    PredicateJoin = PredicateJoin.And,
                    Rules         = new Comparison[]
                    {
                        new Comparison
                        {
                            Data  = _persistenceContext,
                            Field = "Parent",
                            Test  = Test.Equal
                        },
                        new Comparison
                        {
                            Data  = _machineContext,
                            Field = "StateMachine",
                            Test  = Test.Equal
                        }
                    }
                }
            };

            var queryResult = _machineStateData.Query(qs).Items.EmptyIfNull();

            current = queryResult.FirstOrDefault();

            if (null != current)
            {
                _cachedState = current.State;
                _cachedId    = current.Id;
            }
            else
            {
                _cachedId = string.Format("MS{0}-{1}", _persistenceContext, _machineContext);
                ChangeState(_cachedState);
            }
        }
Пример #3
0
        public virtual TSummaryPackageType GetQuery(QuerySpecification qs)
        {
            var retval = _dataRepository.Query(qs);

            if (null == retval)
            {
                throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
            }
            return(retval);
        }
Пример #4
0
        public string GetState(string context)
        {
            var qs = new QuerySpecification
            {
                BookMark = new GenericPageBookmark {
                    PageSize = 100
                },
                Where = new Filter
                {
                    PredicateJoin = PredicateJoin.And,
                    Rules         = new[]
                    {
                        new Comparison
                        {
                            Data  = Id,
                            Field = "Parent",
                            Test  = Test.Equal
                        },
                        new Comparison
                        {
                            Data  = context,
                            Field = "StateMachine",
                            Test  = Test.Equal
                        }
                    }
                }
            };

            var st    = string.Empty;
            var found = _machineStateData.Query(qs).Items;

            if (found.Any())
            {
                st = found.First().State;
            }

            return(st);
        }
Пример #5
0
        public void ProtectedRun()
        {
            DateTime lastException = DateTime.MinValue;

            while (!_ct.IsCancellationRequested)
            {
                try
                {
                    // any wfs fall through the cracks and are asleep but have triggers?
                    IEnumerable <WorkflowInstanceInfo> sleeping = Enumerable.Empty <WorkflowInstanceInfo>();

                    var instancesQuery = new QuerySpecification
                    {
                        BookMark = new GenericPageBookmark {
                            PageSize = 100
                        },
                        Where = new Filter
                        {
                            Rules = new Comparison[]
                            {
                                new Comparison
                                {
                                    Data  = WorkflowStatus.Sleeping.ToString(),
                                    Field = "Status",
                                    Test  = Test.Equal
                                }
                            }
                        }
                    };

                    instancesQuery.BookMark = new GenericPageBookmark {
                        PageSize = 100
                    };


                    while (instancesQuery.BookMark.More)
                    {
                        var qr = _instanceData.Query(instancesQuery);
                        if (qr.Items.Any())
                        {
                            sleeping = sleeping.Concat(qr.Items);
                        }
                    }

                    sleeping = sleeping.ToArray();



                    Parallel.ForEach(sleeping,
                                     nc =>
                    {
                        try
                        {
                            // check for triggers
                            IEnumerable <WorkflowMachineState> hasTriggers = Enumerable.Empty <WorkflowMachineState>();

                            var hasTriggersQuery = new QuerySpecification
                            {
                                BookMark = new GenericPageBookmark {
                                    PageSize = 100
                                },
                                Where = new Filter
                                {
                                    Rules = new Comparison[]
                                    {
                                        new Comparison
                                        {
                                            Field = "Parent",
                                            Data  = nc.Id,
                                            Test  = Test.Equal
                                        }
                                    }
                                }
                            };

                            while (hasTriggersQuery.BookMark.More)
                            {
                                var qr = _machineStateData.Query(hasTriggersQuery);
                                if (qr.Items.Any())
                                {
                                    hasTriggers = hasTriggers.Concat(qr.Items);
                                }
                            }



                            // it has some, try to acquire it
                            if (hasTriggers.Any())
                            {
                                _ct.ThrowIfCancellationRequested();
                                _log.InfoFormat(
                                    "Sleeping workflow {0} has {1} waiting triggers. Waking.", nc.Id,
                                    hasTriggers.Count());

                                TryAcquireWorkflow(nc.Id);
                            }
                        }
                        catch (Exception ex)
                        {
                            _dblog.ErrorFormat("Problem while waking workflow {0}:{2}", nc.Id,
                                               ex.ToString());
                        }
                    });


                    // groom completed and data
                    IEnumerable <WorkflowInstanceInfo> completedInstances = Enumerable.Empty <WorkflowInstanceInfo>();

                    var completedQuery = new QuerySpecification
                    {
                        BookMark = new GenericPageBookmark {
                            PageSize = 100
                        },
                        Where = new Filter
                        {
                            Rules = new Comparison[]
                            {
                                new Comparison
                                {
                                    Data  = WorkflowStatus.Complete.ToString(),
                                    Field = "Status",
                                    Test  = Test.Equal
                                }
                            }
                        }
                    };

                    completedQuery.BookMark = new GenericPageBookmark {
                        PageSize = 100
                    };


                    while (completedQuery.BookMark.More)
                    {
                        var qr = _instanceData.Query(completedQuery);
                        if (qr.Items.Any())
                        {
                            completedInstances = completedInstances.Concat(qr.Items);
                        }
                    }

                    completedInstances = completedInstances.ToArray();



                    Parallel.ForEach(completedInstances,
                                     ci =>
                    {
                        try
                        {
                            _log.InfoFormat("Grooming completed workflow instance {0}", ci.Id);
                            _ct.ThrowIfCancellationRequested();

                            // delete workspaces
                            var workspace = Catalog.Preconfigure()
                                            .Add(WorkspaceLocalConfig.WorkspaceName,
                                                 WorkflowShared.WorkflowInstanceWorkspaceName(ci.Id))
                                            .ConfiguredResolve <IWorkspace>(_workflowWorkspaceKey);


                            workspace.DeleteWorkspace();


                            _ct.ThrowIfCancellationRequested();

                            IEnumerable <WorkflowMachineState> states =
                                Enumerable.Empty <WorkflowMachineState>();

                            var msQuery = new QuerySpecification
                            {
                                BookMark = new GenericPageBookmark {
                                    PageSize = 100
                                },
                                Where = new Filter
                                {
                                    Rules = new Comparison[]
                                    {
                                        new Comparison
                                        {
                                            Data  = ci.Id,
                                            Field = "Parent",
                                            Test  = Test.Equal
                                        }
                                    }
                                }
                            };

                            msQuery.BookMark = new GenericPageBookmark {
                                PageSize = 100
                            };


                            while (msQuery.BookMark.More)
                            {
                                var qr = _machineStateData.Query(msQuery);
                                if (qr.Items.Any())
                                {
                                    states = states.Concat(qr.Items);
                                }
                            }



                            _machineStateData.DeleteBatch(states.ToList());
                            _instanceData.Delete(ci);
                        }
                        catch (Exception ex)
                        {
                            var es = string.Format(
                                "Problem while grooming completed workflow {0}:{1}", ci.Id,
                                ex.ToString());
                            _dblog.Error(es);
                            var on = Catalog.Factory.Resolve <IApplicationAlert>();
                            on.RaiseAlert(ApplicationAlertKind.Unknown, es);
                        }
                    });

                    var chill = TimeSpan.FromMinutes((30.0 * _rndGroomTime.NextDouble()) + 1.0);
                    _log.InfoFormat("Waiting {0} minutes until next sweep cycle.", chill.TotalMinutes);
                    _ct.WaitHandle.WaitOne(chill);
                }
                catch (Exception ex)
                {
                    var es = string.Format("exception running workflow host {0}",
                                           ex.TraceInformation());
                    _dblog.Error(es);

                    if (DateTime.UtcNow - lastException > TimeSpan.FromMinutes(1.0))
                    {
                        _log.TraceException(ex);
                        var alert = Catalog.Factory.Resolve <IApplicationAlert>();
                        alert.RaiseAlert(ApplicationAlertKind.System, es);
                    }
                }
            }
        }
Пример #6
0
        public bool OnStart()
        {
            _listener.Listen(
                new KeyValuePair <Type, Action <object, CancellationToken, IMessageAcknowledge> >(typeof(WakeWorkflowJob), WakeWorkflow),
                new KeyValuePair <Type, Action <object, CancellationToken, IMessageAcknowledge> >(typeof(WorkflowCreate), NewWorkflowInstance),
                new KeyValuePair <Type, Action <object, CancellationToken, IMessageAcknowledge> >(typeof(WorkflowStateMachineRetry), FireRetryMsg),
                new KeyValuePair <Type, Action <object, CancellationToken, IMessageAcknowledge> >(typeof(FireWorkflowTriggerJob), FireTriggerJobMsg));

            _broadcastListener.Listen(new KeyValuePair <Type, Action <object, CancellationToken, IMessageAcknowledge> >(typeof(WorkflowTrigger), DistributeWorkflowTriggers));


            var hostEnvironment = Catalog.Factory.Resolve <IHostEnvironment>();
            var hostId          = hostEnvironment.GetCurrentHostIdentifier(HostEnvironmentConstants.DefaultHostScope);

            var instancesQuery = new QuerySpecification
            {
                BookMark = new GenericPageBookmark {
                    PageSize = 100
                },
                Where = new Filter
                {
                    Rules = new Comparison[]
                    {
                        new Comparison
                        {
                            Data  = WorkflowStatus.Complete.ToString(),
                            Field = "Status",
                            Test  = Test.NotEqual
                        }
                    }
                }
            };

            Task.Factory.StartNew(() =>
            {
                // get this host's chunk of workflow instances to run.
                Random rnd = GoodSeedRandom.Create();

                bool done              = false;
                bool first             = true;
                DateTime lastException = DateTime.MinValue;
                while (!done)
                {
                    try
                    {
                        int acquired = 0;
                        IEnumerable <WorkflowInstanceInfo> instances = Enumerable.Empty <WorkflowInstanceInfo>();
                        instancesQuery.BookMark = new GenericPageBookmark {
                            PageSize = 100
                        };


                        while (instancesQuery.BookMark.More)
                        {
                            var qr = _instanceData.Query(instancesQuery);
                            if (qr.Items.Any())
                            {
                                instances = instances.Concat(qr.Items);
                            }
                        }

                        instances = instances.ToArray();



                        IEnumerable <WorkflowInstanceInfo> tryInstances;

                        // first pass, pick out existing workflows in a pattern less
                        // likely to interfere with other workflow hosts trying to acquire
                        if (first)
                        {
                            int startAt;
                            startAt = rnd.Next(3) * 3;
                            if (startAt > instances.Count())
                            {
                                startAt = rnd.Next(instances.Count() / 3);
                            }

                            tryInstances = instances.TakeEvery(startAt, 3);
                            first        = false;
                        }
                        else
                        {
                            // subsequent passes, be greedy
                            tryInstances = instances;
                        }


                        int waitDur;


                        foreach (var inst in tryInstances)
                        {
                            if (TryAcquireWorkflow(inst.Id) != null)
                            {
                                acquired++;
                                _log.InfoFormat("Host {0} acquired workflow instance {1} ...",
                                                hostId, inst.Id);

                                // give other hosts a little space to take some.
                                waitDur = rnd.Next(160);
                                Thread.Sleep(waitDur);
                            }
                            else
                            {
                                _log.InfoFormat(
                                    "Host {0} could not acquire workflow instance {1} ...", hostId,
                                    inst.Id);
                            }
                        }

                        if (!first && acquired == 0)
                        {
                            done = true;
                        }

                        waitDur = rnd.Next(7654);
                        _log.InfoFormat(
                            "Host {0} acquired {1} pre-existing workflows, waiting {2} milliseconds to try to attain more.",
                            hostId, acquired, waitDur);
                        Thread.Sleep(waitDur);
                    }
                    catch (Exception ex)
                    {
                        var es = string.Format("exception running workflow host {0}",
                                               ex.TraceInformation());
                        _dblog.Error(es);

                        if (DateTime.UtcNow - lastException > TimeSpan.FromMinutes(1.0))
                        {
                            _log.TraceException(ex);
                            var alert = Catalog.Factory.Resolve <IApplicationAlert>();
                            alert.RaiseAlert(ApplicationAlertKind.System, es);
                        }
                    }
                }
            });

            return(true);
        }
Пример #7
0
        private void RunAgent()
        {
            var autoSleepTimeout = DateTime.UtcNow + _initialSleepTimeout;

            var instanceTriggersQuery = new QuerySpecification
            {
                BookMark = new GenericPageBookmark {
                    PageSize = 1000
                },
                Where = new Filter
                {
                    Rules = new Comparison[]
                    {
                        new Comparison
                        {
                            Data  = Id,
                            Field = "InstanceTarget",
                            Test  = Test.Equal
                        }
                    }
                }
            };

            while (_runAgent && !_ct.IsCancellationRequested)
            {
                try
                {
                    // scan triggers
                    IEnumerable <WorkflowTrigger> instTrigs = Enumerable.Empty <WorkflowTrigger>();
                    instanceTriggersQuery.BookMark = new GenericPageBookmark(new GenericPageBookmark {
                        PageSize = 1000
                    });
                    do
                    {
                        var qr = _triggers.Query(instanceTriggersQuery);
                        if (qr.Items.Any())
                        {
                            instTrigs = instTrigs.Concat(qr.Items);
                        }
                        instanceTriggersQuery.BookMark = qr.Bookmark;
                    } while (instanceTriggersQuery.BookMark.More);

                    var myTrigs = instTrigs.ToArray().GroupBy(t => t.Route);

                    _ct.ThrowIfCancellationRequested();

                    if (myTrigs.Any())
                    {
                        var fireTrigs = myTrigs.Where(t => t.Key == TriggerRoutes.FireRoute);
                        foreach (var t in fireTrigs.SelectMany())
                        {
                            try
                            {
                                StateMachines[t.MachineContext].Fire(t.TriggerName);
                            }
                            catch (Exception ex)
                            {
                                _log.Error(ex.TraceInformation());
                            }

                            _triggers.IdDelete(t.Id);



                            _ct.ThrowIfCancellationRequested();
                        }

                        var completeTrigs = myTrigs.Where(t => t.Key == TriggerRoutes.EndRoute);
                        if (completeTrigs.Any())
                        {
                            CompleteWorkflow();

                            _triggers.DeleteBatch(myTrigs.SelectMany().ToList());



                            break;
                        }
                        else
                        {
                            var napTrigs = myTrigs.Where(t => t.Key == TriggerRoutes.NapRoute);
                            if (napTrigs.Any())
                            {
                                _triggers.DeleteBatch(napTrigs.SelectMany().ToList());



                                if (StateMachines.Values.Any(sm => sm.CanActivate))
                                {
                                    // TODO: nap time variable
                                    var nextActivationTime = DateTime.UtcNow + TimeSpan.FromMinutes(60.0);

                                    Sleep(nextActivationTime);
                                }
                                else
                                {
                                    // no activation triggers, so this sleep would be until triggered
                                    Sleep();
                                }

                                break;
                            }
                        }

                        autoSleepTimeout = DateTime.UtcNow + _autoSleepTime;
                    }

                    _bumpEvent.Wait(TimeSpan.FromMinutes(5.0));
                    _bumpEvent.Reset();


                    // auto sleep?
                    if (DateTime.UtcNow > autoSleepTimeout)
                    {
                        //Sleep();
                    }
                }
                catch (OperationCanceledException)
                {
                }
                catch (Exception ex)
                {
                    var es = string.Format("Workflow agent exception: {0}", ex);
                    _log.Error(es);
                    var on = Catalog.Factory.Resolve <IApplicationAlert>();
                    on.RaiseAlert(ApplicationAlertKind.System, es);
                }
            }
        }