Ejemplo n.º 1
0
        public WorkflowCatalog()
        {
            _wfConfig = Catalog.Factory.Resolve <IConfig>(SpecialFactoryContexts.Routed);
            var host = WorkflowShared.GetMessageQueueHost(_wfConfig);

            WorkflowShared.DeclareWorkflowExchanges(host, _wfConfig[WorkflowConfiguration.WorkflowMessagingKey]);



            _instanceData = Catalog.Preconfigure().ConfigureWorkflowDataRepository <WorkflowInstanceInfo>()
                            .ConfiguredResolve <IDataRepositoryService <WorkflowInstanceInfo,
                                                                        WorkflowInstanceInfo,
                                                                        DataEnvelope <WorkflowInstanceInfo, NoMetadata>,
                                                                        NoMetadata,
                                                                        DatumEnvelope <WorkflowInstanceInfo, NoMetadata>,
                                                                        NoMetadata> >
                                (_wfConfig[WorkflowConfiguration.WorkflowDataRepositoryKey]);



            _sender = Catalog.Preconfigure()
                      .Add(MessagePublisherLocalConfig.HostConnectionString, host)
                      .Add(MessagePublisherLocalConfig.ExchangeName, WorkflowShared.WorkflowExchange)
                      .ConfiguredResolve <IMessagePublisher>(_wfConfig[WorkflowConfiguration.WorkflowMessagingKey]);
        }
Ejemplo n.º 2
0
 private static IDistributedMutex ConstructLock(string instanceId)
 {
     return(Catalog.Preconfigure()
            .Add(DistributedMutexLocalConfig.Name, WorkflowShared.WorkflowInstanceLockName(instanceId))
            .Add(DistributedMutexLocalConfig.UnusedExpirationSeconds, 60)
            .ConfiguredResolve <IDistributedMutex>());
 }
Ejemplo n.º 3
0
        private void Initialize(WorkflowHost host, string templateData)
        {
            _log   = ClassLogger.Create(GetType());
            _dblog = DebugOnlyLogger.Create(_log);

            _host = host;


            _workspaceContainerName = WorkflowShared.WorkflowInstanceWorkspaceName(Id);

            Workspace = Catalog.Preconfigure()
                        .Add(WorkspaceLocalConfig.WorkspaceName, _workspaceContainerName)
                        .ConfiguredResolve <IWorkspace>(_workflowWorkspaceKey);


            if (null == _wfLock)
            {
                _wfLock = ConstructLock(Id);
            }



            SpecifyUsingTemplate(templateData);

            var instance = new WorkflowInstanceInfo
            {
                Id                 = Id,
                TemplateName       = Name,
                LastActivity       = DateTime.UtcNow,
                NextActivationTime = DateTime.UtcNow,
                Status             = WorkflowStatus.Active.ToString(),
            };

            _instanceData.Store(instance);
        }
Ejemplo n.º 4
0
        /// <summary>
        ///   Try to lock and host a pre-existing workflow.
        /// </summary>
        /// <param name="workflowId"> </param>
        /// <returns> </returns>
        private WorkflowAgent TryAcquireWorkflow(string workflowId)
        {
            WorkflowAgent acquired = null;
            var           wfMutex  = Catalog.Preconfigure()
                                     .Add(DistributedMutexLocalConfig.Name, WorkflowShared.WorkflowInstanceLockName(workflowId))
                                     .ConfiguredResolve <IDistributedMutex>();

            if (wfMutex.Open())
            {
                try
                {
                    var wftemp = GetWorkflowTemplate(workflowId);
                    if (!string.IsNullOrWhiteSpace(wftemp))
                    {
                        acquired = WorkflowAgent.AcquireSleepingOnLocked(wfMutex, this, workflowId, _ct, wftemp, _workflowDataRepositoryKey, _workflowMessagingKey, _workflowWorkspaceKey);
                        if (null != acquired)
                        {
                            if (_agents.TryAdd(workflowId, acquired))
                            {
                                acquired.Start();
                            }
                            else
                            {
                                _dblog.WarnFormat("Strange: locked workflow {0} but couldn't add it", workflowId);
                            }
                        }
                    }
                }
                catch (SynchronizationLockException)
                {
                    _dblog.InfoFormat("Synchronization lock exception while trying to acquire {0}", workflowId);
                    wfMutex.Release();
                }
                catch (WorkflowTemplateException wfex)
                {
                    var es = string.Format("Error loading template for workflow! {0}: {1}", workflowId, wfex);
                    _log.Error(es);
                    var on = Catalog.Factory.Resolve <IApplicationAlert>();
                    on.RaiseAlert(ApplicationAlertKind.Unknown, es);
                    wfMutex.Release();
                }
                catch (Exception ex)
                {
                    var es = string.Format("Error while acquiring workflow, {0}", ex);
                    _log.Error(es);
                    var on = Catalog.Factory.Resolve <IApplicationAlert>();
                    on.RaiseAlert(ApplicationAlertKind.Unknown, es);
                    wfMutex.Release();
                }
            }
            else
            {
                _dblog.InfoFormat("Could not lock {0}", workflowId);
            }

            return(acquired);
        }
Ejemplo n.º 5
0
 public void OnStop()
 {
     try
     {
         _agents.Values.ForEach(a => a.Stop());
         _listener.Dispose();
         _broadcastListener.Dispose();
         WorkflowShared.RemoveQueueFromWorkflowExchange(_queueConnection, _hostId, _workflowMessagingKey);
         WorkflowShared.RemoveQueueFromWorkflowBroadcast(_queueConnection, WorkflowShared.WorkflowFanoutExchange, _workflowMessagingKey);
     }
     catch (Exception ex)
     {
         _dblog.WarnFormat("Exception while stopping workflow host: {0}", ex.ToString());
     }
 }
Ejemplo n.º 6
0
        public Workflow(string instance)
        {
            var cf = Catalog.Factory.Resolve <IConfig>(SpecialFactoryContexts.Routed);

            var host = WorkflowShared.GetMessageQueueHost(cf);

            WorkflowShared.DeclareWorkflowExchanges(host, cf[WorkflowConfiguration.WorkflowMessagingKey]);
            _instance = instance;


            _machineStateData = Catalog.Preconfigure().ConfigureWorkflowDataRepository <WorkflowMachineState>()
                                .ConfiguredResolve <IDataRepositoryService <WorkflowMachineState,
                                                                            WorkflowMachineState,
                                                                            DataEnvelope <WorkflowMachineState, NoMetadata>,
                                                                            NoMetadata,
                                                                            DatumEnvelope <WorkflowMachineState, NoMetadata>,
                                                                            NoMetadata> >
                                    (cf[WorkflowConfiguration.WorkflowDataRepositoryKey]);

            _instanceData = Catalog.Preconfigure().ConfigureWorkflowDataRepository <WorkflowInstanceInfo>()
                            .ConfiguredResolve <IDataRepositoryService <WorkflowInstanceInfo,
                                                                        WorkflowInstanceInfo,
                                                                        DataEnvelope <WorkflowInstanceInfo, NoMetadata>,
                                                                        NoMetadata,
                                                                        DatumEnvelope <WorkflowInstanceInfo, NoMetadata>,
                                                                        NoMetadata> >
                                (cf[WorkflowConfiguration.WorkflowDataRepositoryKey]);

            _triggers = Catalog.Preconfigure().ConfigureWorkflowDataRepository <WorkflowTrigger>()
                        .ConfiguredResolve <IDataRepositoryService <WorkflowTrigger,
                                                                    WorkflowTrigger,
                                                                    DataEnvelope <WorkflowTrigger, NoMetadata>,
                                                                    NoMetadata,
                                                                    DatumEnvelope <WorkflowTrigger, NoMetadata>,
                                                                    NoMetadata> >
                            (cf[WorkflowConfiguration.WorkflowDataRepositoryKey]);

            _sender = Catalog.Preconfigure()
                      .Add(MessagePublisherLocalConfig.HostConnectionString, host)
                      .Add(MessagePublisherLocalConfig.ExchangeName, WorkflowShared.WorkflowFanoutExchange)
                      .ConfiguredResolve <IMessagePublisher>(cf[WorkflowConfiguration.WorkflowMessagingKey]);

            _workspaceKey = cf[WorkflowConfiguration.WorkflowWorkspaceKey];

            RefreshInstanceInfo();
        }
Ejemplo n.º 7
0
        public WorkflowHost()
        {
            var cf = Catalog.Factory.Resolve <IConfig>(SpecialFactoryContexts.Routed);

            _queueConnection = WorkflowShared.GetMessageQueueHost(cf);



            _wfTemplates = Catalog.Preconfigure()
                           .Add(BlobContainerLocalConfig.ContainerName, WFHostContainerName)
                           .Add(BlobContainerLocalConfig.OptionalAccess, EntityAccess.Private)
                           .Add(BlobContainerLocalConfig.OptionalContentType, "application/json")
                           .ConfiguredResolve <IFilesContainer>();

            _stringResources = Catalog.Factory.Resolve <StringResourcesCache>();

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

            WorkflowShared.DeclareWorkflowExchanges(_queueConnection, cf[WorkflowConfiguration.WorkflowMessagingKey]);
            WorkflowShared.AttachQueueToWorkflowExchange(_queueConnection, _hostId, cf[WorkflowConfiguration.WorkflowMessagingKey]);
            WorkflowShared.AttachedQueueToWorkflowBroadcast(_queueConnection, _hostId, cf[WorkflowConfiguration.WorkflowMessagingKey]);

            _publisher = Catalog.Preconfigure()
                         .Add(MessagePublisherLocalConfig.HostConnectionString, _queueConnection)
                         .Add(MessagePublisherLocalConfig.ExchangeName, WorkflowShared.WorkflowExchange)
                         .ConfiguredResolve <IMessagePublisher>(cf[WorkflowConfiguration.WorkflowMessagingKey]);

            _broadcaster = Catalog.Preconfigure()
                           .Add(MessagePublisherLocalConfig.HostConnectionString, _queueConnection)
                           .Add(MessagePublisherLocalConfig.ExchangeName, WorkflowShared.WorkflowFanoutExchange)
                           .ConfiguredResolve <IMessagePublisher>(cf[WorkflowConfiguration.WorkflowMessagingKey]);

            _listener = Catalog.Preconfigure()
                        .Add(MessageListenerLocalConfig.HostConnectionString, _queueConnection)
                        .Add(MessageListenerLocalConfig.ExchangeName, WorkflowShared.WorkflowExchange)
                        .Add(MessageListenerLocalConfig.QueueName, _hostId)
                        .ConfiguredResolve <IMessageListener>(cf[WorkflowConfiguration.WorkflowMessagingKey]);

            _broadcastListener = Catalog.Preconfigure()
                                 .Add(MessageListenerLocalConfig.HostConnectionString, _queueConnection)
                                 .Add(MessageListenerLocalConfig.ExchangeName, WorkflowShared.WorkflowFanoutExchange)
                                 .Add(MessageListenerLocalConfig.QueueName, _hostId)
                                 .ConfiguredResolve <IMessageListener>(cf[WorkflowConfiguration.WorkflowMessagingKey]);

            _machineStateData = Catalog.Preconfigure().ConfigureWorkflowDataRepository <WorkflowMachineState>()
                                .ConfiguredResolve <IDataRepositoryService <WorkflowMachineState,
                                                                            WorkflowMachineState,
                                                                            DataEnvelope <WorkflowMachineState, NoMetadata>,
                                                                            NoMetadata,
                                                                            DatumEnvelope <WorkflowMachineState, NoMetadata>,
                                                                            NoMetadata> >
                                    (cf[WorkflowConfiguration.WorkflowDataRepositoryKey]);

            _instanceData = Catalog.Preconfigure().ConfigureWorkflowDataRepository <WorkflowInstanceInfo>()
                            .ConfiguredResolve <IDataRepositoryService <WorkflowInstanceInfo,
                                                                        WorkflowInstanceInfo,
                                                                        DataEnvelope <WorkflowInstanceInfo, NoMetadata>,
                                                                        NoMetadata,
                                                                        DatumEnvelope <WorkflowInstanceInfo, NoMetadata>,
                                                                        NoMetadata> >
                                (cf[WorkflowConfiguration.WorkflowDataRepositoryKey]);

            _triggers = Catalog.Preconfigure().ConfigureWorkflowDataRepository <WorkflowTrigger>()
                        .ConfiguredResolve <IDataRepositoryService <WorkflowTrigger,
                                                                    WorkflowTrigger,
                                                                    DataEnvelope <WorkflowTrigger, NoMetadata>,
                                                                    NoMetadata,
                                                                    DatumEnvelope <WorkflowTrigger, NoMetadata>,
                                                                    NoMetadata> >
                            (cf[WorkflowConfiguration.WorkflowDataRepositoryKey]);


            _workflowDataRepositoryKey = cf[WorkflowConfiguration.WorkflowDataRepositoryKey];
            _workflowMessagingKey      = cf[WorkflowConfiguration.WorkflowMessagingKey];
            _workflowWorkspaceKey      = cf[WorkflowConfiguration.WorkflowWorkspaceKey];
        }
Ejemplo n.º 8
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);
                    }
                }
            }
        }