diff --git a/samples/Foundatio.HostingSample/Program.cs b/samples/Foundatio.HostingSample/Program.cs index edbccf63..1cda5105 100644 --- a/samples/Foundatio.HostingSample/Program.cs +++ b/samples/Foundatio.HostingSample/Program.cs @@ -52,7 +52,7 @@ builder.Services.AddJobScheduler(); if (everyMinute) - builder.Services.AddDistributedCronJob("* * * * *", j => j.Name(nameof(EveryMinuteJob))); + builder.Services.AddDistributedCronJob("* * * * *"); if (evenMinutes) builder.Services.AddCronJob("EvenMinutes", "*/2 * * * *", async sp => @@ -67,12 +67,12 @@ if (sample1) builder.Services.AddJob("Sample1", sp => new Sample1Job(sp.GetRequiredService()), o => o.ApplyDefaults().WaitForStartupActions().InitialDelay(TimeSpan.FromSeconds(4))); - builder.Services.AddJob(o => o.WaitForStartupActions().Name(nameof(SampleLockJob))); + builder.Services.AddJob(o => o.WaitForStartupActions()); if (sample2) { builder.Services.AddHealthChecks().AddCheck("Sample2Job"); - builder.Services.AddJob(o => o.WaitForStartupActions().Name(nameof(Sample2Job))); + builder.Services.AddJob(o => o.WaitForStartupActions()); } // if you don't specify priority, actions will automatically be assigned an incrementing priority starting at 0 diff --git a/src/Foundatio.Extensions.Hosting/Jobs/JobHostExtensions.cs b/src/Foundatio.Extensions.Hosting/Jobs/JobHostExtensions.cs index 8c878b60..f1881710 100644 --- a/src/Foundatio.Extensions.Hosting/Jobs/JobHostExtensions.cs +++ b/src/Foundatio.Extensions.Hosting/Jobs/JobHostExtensions.cs @@ -30,7 +30,7 @@ public static IServiceCollection AddJob(this IServiceCollection services, Hos jobOptions.ApplyDefaults(); } - jobOptions.Name ??= typeof(T).FullName; + jobOptions.Name ??= JobOptions.GetDefaultJobName(typeof(T)); jobOptions.JobFactory ??= sp => sp.GetRequiredService(); return new HostedJobService(s, jobOptions, s.GetService()); @@ -41,7 +41,7 @@ public static IServiceCollection AddJob(this IServiceCollection services, Act { var jobOptionsBuilder = new HostedJobOptionsBuilder(); jobOptionsBuilder.ApplyDefaults(); - jobOptionsBuilder.Name(typeof(T).FullName); + jobOptionsBuilder.Name(JobOptions.GetDefaultJobName(typeof(T))); configureJobOptions?.Invoke(jobOptionsBuilder); return services.AddJob(jobOptionsBuilder.Target); } @@ -82,7 +82,7 @@ public static IServiceCollection AddCronJob(this IServiceCollection services, { services.AddTransient(); var jobOptionsBuilder = new ScheduledJobOptionsBuilder(); - jobOptionsBuilder.Name(typeof(T).FullName).CronSchedule(cronSchedule).JobFactory(sp => sp.GetRequiredService()); + jobOptionsBuilder.Name(JobOptions.GetDefaultJobName(typeof(T))).CronSchedule(cronSchedule).JobFactory(sp => sp.GetRequiredService()); configureJobOptions?.Invoke(jobOptionsBuilder); return services.AddCronJob(jobOptionsBuilder.Target); } @@ -133,7 +133,7 @@ public static IServiceCollection AddDistributedCronJob(this IServiceCollectio { services.AddTransient(); var jobOptionsBuilder = new ScheduledJobOptionsBuilder(); - jobOptionsBuilder.Name(typeof(T).FullName).Distributed().CronSchedule(cronSchedule).JobFactory(sp => sp.GetRequiredService()); + jobOptionsBuilder.Name(JobOptions.GetDefaultJobName(typeof(T))).Distributed().CronSchedule(cronSchedule).JobFactory(sp => sp.GetRequiredService()); configureJobOptions?.Invoke(jobOptionsBuilder); return services.AddCronJob(jobOptionsBuilder.Target); } diff --git a/src/Foundatio.Extensions.Hosting/Jobs/JobManager.cs b/src/Foundatio.Extensions.Hosting/Jobs/JobManager.cs index 1ef300d1..e84a6211 100644 --- a/src/Foundatio.Extensions.Hosting/Jobs/JobManager.cs +++ b/src/Foundatio.Extensions.Hosting/Jobs/JobManager.cs @@ -52,7 +52,7 @@ public JobManager(IServiceProvider serviceProvider, ILoggerFactory loggerFactory public void AddOrUpdate(string cronSchedule, Action configure = null) where TJob : class, IJob { - string jobName = typeof(TJob).FullName; + string jobName = JobOptions.GetDefaultJobName(typeof(TJob)); lock (_lock) { var job = Jobs.FirstOrDefault(j => j.Options.Name == jobName); @@ -151,7 +151,7 @@ public void AddOrUpdate(string jobName, string cronSchedule, Action action, Acti public void Remove() where TJob : class, IJob { - string jobName = typeof(TJob).FullName; + string jobName = JobOptions.GetDefaultJobName(typeof(TJob)); lock (_lock) { var job = Jobs.FirstOrDefault(j => j.Options.Name == jobName); @@ -191,7 +191,7 @@ public JobStatus[] GetJobStatus() public async Task RunJobAsync(CancellationToken cancellationToken = default) where TJob : class, IJob { - string jobName = typeof(TJob).FullName; + string jobName = JobOptions.GetDefaultJobName(typeof(TJob)); await RunJobAsync(jobName, cancellationToken).AnyContext(); } diff --git a/src/Foundatio/Extensions/StringExtensions.cs b/src/Foundatio/Extensions/StringExtensions.cs index 97abdd44..08c9d68c 100644 --- a/src/Foundatio/Extensions/StringExtensions.cs +++ b/src/Foundatio/Extensions/StringExtensions.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Text; namespace Foundatio.Extensions; @@ -17,4 +18,26 @@ public static string NormalizePath(this string path) return path; } + + public static string ToSpacedWords(this string text, bool preserveAcronyms = true) + { + if (String.IsNullOrWhiteSpace(text)) + return String.Empty; + + var sb = new StringBuilder(text.Length * 2); + sb.Append(text[0]); + + for (int i = 1; i < text.Length; i++) + { + if (Char.IsUpper(text[i])) + if ((text[i - 1] != ' ' && !Char.IsUpper(text[i - 1])) || + (preserveAcronyms && Char.IsUpper(text[i - 1]) && + i < text.Length - 1 && !Char.IsUpper(text[i + 1]))) + sb.Append(' '); + + sb.Append(text[i]); + } + + return sb.ToString(); + } } diff --git a/src/Foundatio/Jobs/JobOptions.cs b/src/Foundatio/Jobs/JobOptions.cs index 36c745bb..6241b4b9 100644 --- a/src/Foundatio/Jobs/JobOptions.cs +++ b/src/Foundatio/Jobs/JobOptions.cs @@ -1,5 +1,6 @@ using System; using System.Reflection; +using Foundatio.Extensions; using Foundatio.Utility; namespace Foundatio.Jobs; @@ -28,13 +29,7 @@ public static void ApplyDefaults(JobOptions jobOptions, Type jobType) jobOptions.Name = jobAttribute.Name; if (String.IsNullOrEmpty(jobOptions.Name)) - { - string jobName = jobType.Name; - if (jobName.EndsWith("Job")) - jobName = jobName.Substring(0, jobName.Length - 3); - - jobOptions.Name = jobName.ToLower(); - } + jobOptions.Name = GetDefaultJobName(jobType); jobOptions.Description = jobAttribute.Description; jobOptions.RunContinuous = jobAttribute.IsContinuous; @@ -89,6 +84,15 @@ public static JobOptions GetDefaults(Func jobFactory) jobOptions.JobFactory = jobFactory; return jobOptions; } + + public static string GetDefaultJobName(Type type) + { + string jobName = type.Name; + if (jobName.EndsWith("Job")) + jobName = jobName.Substring(0, jobName.Length - 3); + + return jobName.ToSpacedWords(); + } } public static class JobOptionExtensions diff --git a/src/Foundatio/Jobs/JobRunner.cs b/src/Foundatio/Jobs/JobRunner.cs index 4c0deb76..1b8126b6 100644 --- a/src/Foundatio/Jobs/JobRunner.cs +++ b/src/Foundatio/Jobs/JobRunner.cs @@ -208,7 +208,7 @@ public async Task RunAsync(CancellationToken cancellationToken = default) } else if (_options.RunContinuous && _options.InstanceCount == 1) { - await job.RunContinuousAsync(_options.Interval, _options.IterationLimit, cancellationToken).AnyContext(); + await job.RunContinuousAsync(_options, cancellationToken).AnyContext(); } else {