Ejemplo n.º 1
0
 /// <summary>
 /// Add Elsa Hangfire Services for background processing
 /// </summary>
 /// <param name="timersOptions"></param>
 public static void UseHangfire(this TimersOptions timersOptions)
 {
     timersOptions.Services
     .AddSingleton <IWorkflowScheduler, HangfireWorkflowScheduler>()
     .AddSingleton <ICrontabParser, HangfireCrontabParser>()
     .AddSingleton <JobManager>();
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Add Elsa Quartz services and Quartz services.
        /// </summary>
        /// <param name="timersOptions">The timer options being configured.</param>
        /// <param name="registerQuartz">True to automatically register Quartz services. When false, make sure to register Quartz yourself.</param>
        /// <param name="configureQuartzOptions">When <see cref="registerQuartz"/> is true, you can use this callback to further configure Quartz options.</param>
        /// <param name="configureQuartz">When <see cref="registerQuartz"/> is true, you can use this callback to further configure Quartz.</param>
        /// <param name="configureQuartzHostedService">When <see cref="registerQuartz"/> is true, you can use this callback to further configure the Quartz hosted service.</param>
        public static void UseQuartzProvider(
            this TimersOptions timersOptions,
            bool registerQuartz = true,
            Action <QuartzOptions>?configureQuartzOptions = default,
            Action <IServiceCollectionQuartzConfigurator>?configureQuartz    = default,
            Action <QuartzHostedServiceOptions>?configureQuartzHostedService = default)
        {
            timersOptions.Services
            .AddSingleton <QuartzSchedulerProvider>()
            .AddSingleton <IWorkflowDefinitionScheduler, QuartzWorkflowDefinitionScheduler>()
            .AddSingleton <IWorkflowInstanceScheduler, QuartzWorkflowInstanceScheduler>()
            .AddSingleton <ICrontabParser, QuartzCrontabParser>()
            .AddTransient <RunQuartzWorkflowDefinitionJob>()
            .AddTransient <RunQuartzWorkflowInstanceJob>()
            .AddNotificationHandlers(typeof(ConfigureCronProperty));

            if (registerQuartz)
            {
                if (configureQuartzOptions != null)
                {
                    timersOptions.Services.Configure(configureQuartzOptions);
                }

                timersOptions.Services
                .AddQuartz(configure => ConfigureQuartz(configure, configureQuartz))
                .AddQuartzHostedService(options => ConfigureQuartzHostedService(options, configureQuartzHostedService));
            }
        }
Ejemplo n.º 3
0
 public TimerTriggerAttributeBindingProvider(TimersOptions options, INameResolver nameResolver, ILogger logger, ScheduleMonitor scheduleMonitor)
 {
     _options         = options;
     _nameResolver    = nameResolver;
     _logger          = logger;
     _scheduleMonitor = scheduleMonitor;
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Adds services which are common to temporal activities.  This method is intended for internal use only.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Instead of calling this method directly, when setting up Elsa for temporal (time-based) activities,
        /// developers should make use of one of the implementation-specific add-temporal-activities methods.
        /// Without providing an implementation-specific configuration in <paramref name="configure"/>, this method
        /// will not fully set up the temporal activities.
        /// </para>
        /// </remarks>
        /// <param name="options">Elsa options</param>
        /// <param name="configure">The configuration for temporal activity options</param>
        public static ElsaOptionsBuilder AddCommonTemporalActivities(this ElsaOptionsBuilder options, Action <TimersOptions>?configure = default)
        {
            var timersOptions = new TimersOptions(options.Services);

            configure?.Invoke(timersOptions);

            options.Services
            .AddNotificationHandlers(typeof(UnscheduleTimers))
            .AddHostedService <ScopedBackgroundService <StartJobs> >()
            .AddBookmarkProvider <TimerBookmarkProvider>()
            .AddBookmarkProvider <CronBookmarkProvider>()
            .AddBookmarkProvider <StartAtBookmarkProvider>();

            options
            .AddActivity <Cron>()
            .AddActivity <Timer>()
            .AddActivity <StartAt>()
            .AddActivity <ClearTimer>();

            // Register a consumer to process instructions to schedule activities from bookmarks.
            options.AddCompetingConsumer <ScheduleBookmarkConsumer, ScheduleTemporalBookmark>("ScheduleBookmark");
            options.AddCompetingConsumer <ScheduleTriggerConsumer, ScheduleTemporalTrigger>("ScheduleBookmark");

            return(options);
        }
Ejemplo n.º 5
0
 /// <summary>
 /// Add Elsa Hangfire Services for background processing
 /// </summary>
 /// <param name="timersOptions"></param>
 public static void UseHangfire(this TimersOptions timersOptions)
 {
     timersOptions.Services
     .AddSingleton <IWorkflowDefinitionScheduler, HangfireWorkflowDefinitionScheduler>()
     .AddSingleton <IWorkflowInstanceScheduler, HangfireWorkflowInstanceScheduler>()
     .AddSingleton <ICrontabParser, HangfireCrontabParser>();
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Add Elsa Hangfire Services for background processing and Hangfire services.
        /// </summary>
        /// <remarks>
        /// Use only if Hangfire is not already registered in DI.
        /// </remarks>
        /// <param name="timersOptions">The TimersOptions being configured</param>
        /// <param name="configure">Configure Hangfire settings</param>
        public static void UseHangfire(this TimersOptions timersOptions, Action <IGlobalConfiguration> configure)
        {
            timersOptions.UseHangfire();

            // Add Hangfire services.
            timersOptions.Services.AddHangfire(configure);

            // Add the processing server as IHostedService
            timersOptions.Services.AddHangfireServer();
        }
Ejemplo n.º 7
0
 public TimerListener(TimerTriggerAttribute attribute, TimerSchedule schedule, string timerName, TimersOptions options, ITriggeredFunctionExecutor executor, ILogger logger, ScheduleMonitor scheduleMonitor)
 {
     _attribute = attribute;
     _timerName = timerName;
     _options   = options;
     _executor  = executor;
     _logger    = logger;
     _cancellationTokenSource = new CancellationTokenSource();
     _schedule       = schedule;
     ScheduleMonitor = _attribute.UseMonitor ? scheduleMonitor : null;
 }
        public TimerTriggerBinding(ParameterInfo parameter, TimerTriggerAttribute attribute, TimerSchedule schedule, TimersOptions options, ILogger logger, ScheduleMonitor scheduleMonitor)
        {
            _attribute       = attribute;
            _schedule        = schedule;
            _parameter       = parameter;
            _options         = options;
            _logger          = logger;
            _scheduleMonitor = scheduleMonitor;
            _bindingContract = CreateBindingDataContract();

            MethodInfo methodInfo = (MethodInfo)parameter.Member;

            _timerName = string.Format("{0}.{1}", methodInfo.DeclaringType.FullName, methodInfo.Name);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Add Elsa Hangfire Services for background processing and Hangfire services.
        /// </summary>
        /// <remarks>
        /// Use only if Hangfire is not already registered in DI.
        /// </remarks>
        /// <param name="timersOptions">The TimersOptions being configured</param>
        /// <param name="configure">Configure Hangfire settings</param>
        /// <param name="configureJobServer">Configure Hangfire job server settings</param>
        public static void UseHangfire(this TimersOptions timersOptions, Action <IGlobalConfiguration> configure, Action <IServiceProvider, BackgroundJobServerOptions>?configureJobServer = default)
        {
            timersOptions.UseHangfire();

            var services = timersOptions.Services;

            // Add Hangfire services.
            services.AddHangfire(configure);

            // Add the processing server as IHostedService
            if (configureJobServer != null)
            {
                services.AddHangfireServer(configureJobServer);
            }
            else
            {
                services.AddHangfireServer();
            }
        }
        private void CreateTestListener(string expression, bool useMonitor = true, Action functionAction = null)
        {
            _attribute            = new TimerTriggerAttribute(expression);
            _schedule             = TimerSchedule.Create(_attribute, new TestNameResolver());
            _attribute.UseMonitor = useMonitor;
            _options             = new TimersOptions();
            _mockScheduleMonitor = new Mock <ScheduleMonitor>(MockBehavior.Strict);
            _mockTriggerExecutor = new Mock <ITriggeredFunctionExecutor>(MockBehavior.Strict);
            FunctionResult result = new FunctionResult(true);

            _mockTriggerExecutor.Setup(p => p.TryExecuteAsync(It.IsAny <TriggeredFunctionData>(), It.IsAny <CancellationToken>()))
            .Callback <TriggeredFunctionData, CancellationToken>((mockFunctionData, mockToken) =>
            {
                _triggeredFunctionData = mockFunctionData;
                functionAction?.Invoke();
            })
            .Returns(Task.FromResult(result));
            _logger   = new TestLogger(null);
            _listener = new TimerListener(_attribute, _schedule, _testTimerName, _options, _mockTriggerExecutor.Object, _logger, _mockScheduleMonitor.Object);
        }
        /// <summary>
        /// Adds services which are common to temporal activities.  This method is intended for internal use only.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Instead of calling this method directly, when setting up Elsa for temporal (time-based) activities,
        /// developers should make use of one of the implementation-specific add-temporal-activities methods.
        /// Without providing an implementation-specific configuration in <paramref name="configure"/>, this method
        /// will not fully set up the temporal activities.
        /// </para>
        /// </remarks>
        /// <param name="options">Elsa options</param>
        /// <param name="configure">The configuration for temporal activity options</param>
        public static ElsaOptionsBuilder AddCommonTemporalActivities(this ElsaOptionsBuilder options, Action <TimersOptions>?configure = default)
        {
            var timersOptions = new TimersOptions(options.Services);

            configure?.Invoke(timersOptions);

            options.Services
            .AddNotificationHandlers(typeof(RemoveScheduledTriggers))
            .AddHostedService <ScopedBackgroundService <StartJobs> >()
            .AddBookmarkProvider <TimerBookmarkProvider>()
            .AddBookmarkProvider <CronBookmarkProvider>()
            .AddBookmarkProvider <StartAtBookmarkProvider>();

            options
            .AddActivity <Cron>()
            .AddActivity <Timer>()
            .AddActivity <StartAt>()
            .AddActivity <ClearTimer>();

            return(options);
        }
        public async Task BindAsync_ReturnsExpectedTriggerData()
        {
            ParameterInfo parameter  = GetType().GetMethod("TestTimerJob").GetParameters()[0];
            MethodInfo    methodInfo = (MethodInfo)parameter.Member;
            string        timerName  = string.Format("{0}.{1}", methodInfo.DeclaringType.FullName, methodInfo.Name);

            Mock <ScheduleMonitor> mockScheduleMonitor = new Mock <ScheduleMonitor>(MockBehavior.Strict);
            ScheduleStatus         status = new ScheduleStatus();

            mockScheduleMonitor.Setup(p => p.GetStatusAsync(timerName)).ReturnsAsync(status);

            TimerTriggerAttribute attribute    = parameter.GetCustomAttribute <TimerTriggerAttribute>();
            INameResolver         nameResolver = new TestNameResolver();
            TimerSchedule         schedule     = TimerSchedule.Create(attribute, nameResolver);
            TimersOptions         options      = new TimersOptions();

            ILoggerFactory loggerFactory = new LoggerFactory();

            loggerFactory.AddProvider(new TestLoggerProvider());

            TimerTriggerBinding binding = new TimerTriggerBinding(parameter, attribute, schedule, options, loggerFactory.CreateLogger("Test"), mockScheduleMonitor.Object);

            // when we bind to a non-TimerInfo (e.g. in a Dashboard invocation) a new
            // TimerInfo is created, with the ScheduleStatus populated
            FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None);
            ValueBindingContext    context         = new ValueBindingContext(functionContext, CancellationToken.None);
            TriggerData            triggerData     = (TriggerData)(await binding.BindAsync(string.Empty, context));
            TimerInfo timerInfo = (TimerInfo)(await triggerData.ValueProvider.GetValueAsync());

            Assert.Same(status, timerInfo.ScheduleStatus);

            // when we pass in a TimerInfo that is used
            TimerInfo expected = new TimerInfo(schedule, status);

            triggerData = (TriggerData)(await binding.BindAsync(expected, context));
            timerInfo   = (TimerInfo)(await triggerData.ValueProvider.GetValueAsync());
            Assert.Same(expected, timerInfo);
        }