/// <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>(); }
/// <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)); } }
public TimerTriggerAttributeBindingProvider(TimersOptions options, INameResolver nameResolver, ILogger logger, ScheduleMonitor scheduleMonitor) { _options = options; _nameResolver = nameResolver; _logger = logger; _scheduleMonitor = scheduleMonitor; }
/// <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); }
/// <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>(); }
/// <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(); }
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); }
/// <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); }