Skip to content

Commit 7a84bc1

Browse files
committed
- add ability to inject clock for 'UtcNow' resolving
1 parent ba2de54 commit 7a84bc1

File tree

57 files changed

+894
-702
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+894
-702
lines changed

src/Hangfire.AspNetCore/BackgroundJobServerHostedService.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public class BackgroundJobServerHostedService : IHostedService, IDisposable
1515
{
1616
private readonly BackgroundJobServerOptions _options;
1717
private readonly JobStorage _storage;
18+
private readonly IClock _clock;
1819
private readonly IEnumerable<IBackgroundProcess> _additionalProcesses;
1920
private readonly IBackgroundJobFactory _factory;
2021
private readonly IBackgroundJobPerformer _performer;
@@ -24,17 +25,19 @@ public class BackgroundJobServerHostedService : IHostedService, IDisposable
2425

2526
public BackgroundJobServerHostedService(
2627
[NotNull] JobStorage storage,
28+
[NotNull] IClock clock,
2729
[NotNull] BackgroundJobServerOptions options,
2830
[NotNull] IEnumerable<IBackgroundProcess> additionalProcesses)
2931
#pragma warning disable 618
30-
: this(storage, options, additionalProcesses, null, null, null)
32+
: this(storage, clock, options, additionalProcesses, null, null, null)
3133
#pragma warning restore 618
3234
{
3335
}
3436

3537
[Obsolete("This constructor uses an obsolete constructor overload of the BackgroundJobServer type that will be removed in 2.0.0.")]
3638
public BackgroundJobServerHostedService(
3739
[NotNull] JobStorage storage,
40+
[NotNull] IClock clock,
3841
[NotNull] BackgroundJobServerOptions options,
3942
[NotNull] IEnumerable<IBackgroundProcess> additionalProcesses,
4043
[CanBeNull] IBackgroundJobFactory factory,
@@ -43,6 +46,7 @@ public BackgroundJobServerHostedService(
4346
{
4447
_options = options ?? throw new ArgumentNullException(nameof(options));
4548
_storage = storage ?? throw new ArgumentNullException(nameof(storage));
49+
_clock = clock ?? throw new ArgumentNullException(nameof(clock));
4650

4751
_additionalProcesses = additionalProcesses;
4852

@@ -55,9 +59,9 @@ public Task StartAsync(CancellationToken cancellationToken)
5559
{
5660
_processingServer = _factory != null && _performer != null && _stateChanger != null
5761
#pragma warning disable 618
58-
? new BackgroundJobServer(_options, _storage, _additionalProcesses, null, null, _factory, _performer, _stateChanger)
62+
? new BackgroundJobServer(_options, _storage, _clock, _additionalProcesses, null, null, _factory, _performer, _stateChanger)
5963
#pragma warning restore 618
60-
: new BackgroundJobServer(_options, _storage, _additionalProcesses);
64+
: new BackgroundJobServer(_options, _storage, _clock, _additionalProcesses);
6165

6266
return Task.CompletedTask;
6367
}

src/Hangfire.AspNetCore/Dashboard/AspNetCoreDashboardContext.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
// This file is part of Hangfire.
22
// Copyright © 2016 Sergey Odinokov.
3-
//
3+
//
44
// Hangfire is free software: you can redistribute it and/or modify
5-
// it under the terms of the GNU Lesser General Public License as
6-
// published by the Free Software Foundation, either version 3
5+
// it under the terms of the GNU Lesser General Public License as
6+
// published by the Free Software Foundation, either version 3
77
// of the License, or any later version.
8-
//
8+
//
99
// Hangfire is distributed in the hope that it will be useful,
1010
// but WITHOUT ANY WARRANTY; without even the implied warranty of
1111
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1212
// GNU Lesser General Public License for more details.
13-
//
14-
// You should have received a copy of the GNU Lesser General Public
13+
//
14+
// You should have received a copy of the GNU Lesser General Public
1515
// License along with Hangfire. If not, see <http://www.gnu.org/licenses/>.
1616

1717
using System;
@@ -26,9 +26,10 @@ public sealed class AspNetCoreDashboardContext : DashboardContext
2626
{
2727
public AspNetCoreDashboardContext(
2828
[NotNull] JobStorage storage,
29+
[NotNull] IClock clock,
2930
[NotNull] DashboardOptions options,
30-
[NotNull] HttpContext httpContext)
31-
: base(storage, options)
31+
[NotNull] HttpContext httpContext)
32+
: base(storage, clock, options)
3233
{
3334
if (httpContext == null) throw new ArgumentNullException(nameof(httpContext));
3435

src/Hangfire.AspNetCore/Dashboard/AspNetCoreDashboardMiddleware.cs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
// This file is part of Hangfire.
2-
// Copyright © 2016 Sergey Odinokov.
3-
//
2+
// Copyright 2016 Sergey Odinokov.
3+
//
44
// Hangfire is free software: you can redistribute it and/or modify
5-
// it under the terms of the GNU Lesser General Public License as
6-
// published by the Free Software Foundation, either version 3
5+
// it under the terms of the GNU Lesser General Public License as
6+
// published by the Free Software Foundation, either version 3
77
// of the License, or any later version.
8-
//
8+
//
99
// Hangfire is distributed in the hope that it will be useful,
1010
// but WITHOUT ANY WARRANTY; without even the implied warranty of
1111
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1212
// GNU Lesser General Public License for more details.
13-
//
14-
// You should have received a copy of the GNU Lesser General Public
13+
//
14+
// You should have received a copy of the GNU Lesser General Public
1515
// License along with Hangfire. If not, see <http://www.gnu.org/licenses/>.
1616

1717
using System;
@@ -28,31 +28,35 @@ public class AspNetCoreDashboardMiddleware
2828
{
2929
private readonly RequestDelegate _next;
3030
private readonly JobStorage _storage;
31+
private readonly IClock _clock;
3132
private readonly DashboardOptions _options;
3233
private readonly RouteCollection _routes;
3334

3435
public AspNetCoreDashboardMiddleware(
3536
[NotNull] RequestDelegate next,
3637
[NotNull] JobStorage storage,
38+
[NotNull] IClock clock,
3739
[NotNull] DashboardOptions options,
3840
[NotNull] RouteCollection routes)
3941
{
4042
if (next == null) throw new ArgumentNullException(nameof(next));
4143
if (storage == null) throw new ArgumentNullException(nameof(storage));
44+
if (clock == null) throw new ArgumentNullException(nameof(clock));
4245
if (options == null) throw new ArgumentNullException(nameof(options));
4346
if (routes == null) throw new ArgumentNullException(nameof(routes));
4447

4548
_next = next;
4649
_storage = storage;
50+
_clock = clock;
4751
_options = options;
4852
_routes = routes;
4953
}
5054

5155
public async Task Invoke(HttpContext httpContext)
5256
{
53-
var context = new AspNetCoreDashboardContext(_storage, _options, httpContext);
57+
var context = new AspNetCoreDashboardContext(_storage, _clock, _options, httpContext);
5458
var findResult = _routes.FindDispatcher(httpContext.Request.Path.Value);
55-
59+
5660
if (findResult == null)
5761
{
5862
await _next.Invoke(httpContext);
@@ -96,4 +100,4 @@ public async Task Invoke(HttpContext httpContext)
96100
await findResult.Item1.Dispatch(context);
97101
}
98102
}
99-
}
103+
}

src/Hangfire.AspNetCore/HangfireApplicationBuilderExtensions.cs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
// This file is part of Hangfire.
22
// Copyright © 2016 Sergey Odinokov.
3-
//
3+
//
44
// Hangfire is free software: you can redistribute it and/or modify
5-
// it under the terms of the GNU Lesser General Public License as
6-
// published by the Free Software Foundation, either version 3
5+
// it under the terms of the GNU Lesser General Public License as
6+
// published by the Free Software Foundation, either version 3
77
// of the License, or any later version.
8-
//
8+
//
99
// Hangfire is distributed in the hope that it will be useful,
1010
// but WITHOUT ANY WARRANTY; without even the implied warranty of
1111
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1212
// GNU Lesser General Public License for more details.
13-
//
14-
// You should have received a copy of the GNU Lesser General Public
13+
//
14+
// You should have received a copy of the GNU Lesser General Public
1515
// License along with Hangfire. If not, see <http://www.gnu.org/licenses/>.
1616

1717
using System;
@@ -33,7 +33,8 @@ public static IApplicationBuilder UseHangfireDashboard(
3333
[NotNull] this IApplicationBuilder app,
3434
[NotNull] string pathMatch = "/hangfire",
3535
[CanBeNull] DashboardOptions options = null,
36-
[CanBeNull] JobStorage storage = null)
36+
[CanBeNull] JobStorage storage = null,
37+
[CanBeNull] IClock clock = null)
3738
{
3839
if (app == null) throw new ArgumentNullException(nameof(app));
3940
if (pathMatch == null) throw new ArgumentNullException(nameof(pathMatch));
@@ -43,12 +44,13 @@ public static IApplicationBuilder UseHangfireDashboard(
4344
var services = app.ApplicationServices;
4445

4546
storage = storage ?? services.GetRequiredService<JobStorage>();
47+
clock = clock ?? services.GetRequiredService<IClock>();
4648
options = options ?? services.GetService<DashboardOptions>() ?? new DashboardOptions();
4749
options.TimeZoneResolver = options.TimeZoneResolver ?? services.GetService<ITimeZoneResolver>();
4850

4951
var routes = app.ApplicationServices.GetRequiredService<RouteCollection>();
5052

51-
app.Map(new PathString(pathMatch), x => x.UseMiddleware<AspNetCoreDashboardMiddleware>(storage, options, routes));
53+
app.Map(new PathString(pathMatch), x => x.UseMiddleware<AspNetCoreDashboardMiddleware>(storage, clock, options, routes));
5254

5355
return app;
5456
}
@@ -57,16 +59,18 @@ public static IApplicationBuilder UseHangfireServer(
5759
[NotNull] this IApplicationBuilder app,
5860
[CanBeNull] BackgroundJobServerOptions options = null,
5961
[CanBeNull] IEnumerable<IBackgroundProcess> additionalProcesses = null,
60-
[CanBeNull] JobStorage storage = null)
62+
[CanBeNull] JobStorage storage = null,
63+
[CanBeNull] IClock clock = null)
6164
{
6265
if (app == null) throw new ArgumentNullException(nameof(app));
63-
66+
6467
HangfireServiceCollectionExtensions.ThrowIfNotConfigured(app.ApplicationServices);
6568

6669
var services = app.ApplicationServices;
6770
var lifetime = services.GetRequiredService<IApplicationLifetime>();
6871

6972
storage = storage ?? services.GetRequiredService<JobStorage>();
73+
clock = clock ?? services.GetRequiredService<IClock>();
7074
options = options ?? services.GetService<BackgroundJobServerOptions>() ?? new BackgroundJobServerOptions();
7175
additionalProcesses = additionalProcesses ?? services.GetServices<IBackgroundProcess>();
7276

@@ -76,9 +80,9 @@ public static IApplicationBuilder UseHangfireServer(
7680

7781
var server = HangfireServiceCollectionExtensions.GetInternalServices(services, out var factory, out var stateChanger, out var performer)
7882
#pragma warning disable 618
79-
? new BackgroundJobServer(options, storage, additionalProcesses, null, null, factory, performer, stateChanger)
83+
? new BackgroundJobServer(options, storage, clock, additionalProcesses, null, null, factory, performer, stateChanger)
8084
#pragma warning restore 618
81-
: new BackgroundJobServer(options, storage, additionalProcesses);
85+
: new BackgroundJobServer(options, storage, clock, additionalProcesses);
8286

8387
lifetime.ApplicationStopping.Register(() => server.SendStop());
8488
lifetime.ApplicationStopped.Register(() => server.Dispose());

src/Hangfire.AspNetCore/HangfireServiceCollectionExtensions.cs

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
// This file is part of Hangfire.
22
// Copyright © 2016 Sergey Odinokov.
3-
//
3+
//
44
// Hangfire is free software: you can redistribute it and/or modify
5-
// it under the terms of the GNU Lesser General Public License as
6-
// published by the Free Software Foundation, either version 3
5+
// it under the terms of the GNU Lesser General Public License as
6+
// published by the Free Software Foundation, either version 3
77
// of the License, or any later version.
8-
//
8+
//
99
// Hangfire is distributed in the hope that it will be useful,
1010
// but WITHOUT ANY WARRANTY; without even the implied warranty of
1111
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1212
// GNU Lesser General Public License for more details.
13-
//
14-
// You should have received a copy of the GNU Lesser General Public
13+
//
14+
// You should have received a copy of the GNU Lesser General Public
1515
// License along with Hangfire. If not, see <http://www.gnu.org/licenses/>.
1616

1717
using System;
@@ -27,6 +27,7 @@
2727
using Microsoft.Extensions.Logging;
2828
#if NETSTANDARD2_0
2929
using Microsoft.Extensions.Hosting;
30+
3031
#endif
3132

3233
namespace Hangfire
@@ -46,10 +47,11 @@ public static IServiceCollection AddHangfire(
4647
{
4748
if (services == null) throw new ArgumentNullException(nameof(services));
4849
if (configuration == null) throw new ArgumentNullException(nameof(configuration));
49-
50+
5051
// ===== Configurable services =====
5152

5253
services.TryAddSingletonChecked(_ => JobStorage.Current);
54+
services.TryAddSingletonChecked(_ => SystemClock.Current);
5355
services.TryAddSingletonChecked(_ => JobActivator.Current);
5456
services.TryAddSingletonChecked(_ => DashboardRoutes.Routes);
5557
services.TryAddSingletonChecked<IJobFilterProvider>(_ => JobFilterProviders.Providers);
@@ -64,18 +66,19 @@ public static IServiceCollection AddHangfire(
6466

6567
// ===== Client services =====
6668

67-
// NOTE: these, on the other hand, need to be double-checked to be sure configuration block was executed,
69+
// NOTE: these, on the other hand, need to be double-checked to be sure configuration block was executed,
6870
// in case of a client-only scenario with all configurables above replaced with custom implementations.
6971

7072
services.TryAddSingletonChecked<IBackgroundJobClient>(x =>
7173
{
7274
if (GetInternalServices(x, out var factory, out var stateChanger, out _))
7375
{
74-
return new BackgroundJobClient(x.GetRequiredService<JobStorage>(), factory, stateChanger);
76+
return new BackgroundJobClient(x.GetRequiredService<JobStorage>(), x.GetRequiredService<IClock>(), factory, stateChanger);
7577
}
7678

7779
return new BackgroundJobClient(
7880
x.GetRequiredService<JobStorage>(),
81+
x.GetRequiredService<IClock>(),
7982
x.GetRequiredService<IJobFilterProvider>());
8083
});
8184

@@ -85,23 +88,25 @@ public static IServiceCollection AddHangfire(
8588
{
8689
return new RecurringJobManager(
8790
x.GetRequiredService<JobStorage>(),
91+
x.GetRequiredService<IClock>(),
8892
factory,
8993
x.GetRequiredService<ITimeZoneResolver>());
9094
}
9195

9296
return new RecurringJobManager(
9397
x.GetRequiredService<JobStorage>(),
98+
x.GetRequiredService<IClock>(),
9499
x.GetRequiredService<IJobFilterProvider>(),
95100
x.GetRequiredService<ITimeZoneResolver>());
96101
});
97102

98103

99-
// IGlobalConfiguration serves as a marker indicating that Hangfire's services
104+
// IGlobalConfiguration serves as a marker indicating that Hangfire's services
100105
// were added to the service container (checked by IApplicationBuilder extensions).
101-
//
102-
// Being a singleton, it also guarantees that the configuration callback will be
106+
//
107+
// Being a singleton, it also guarantees that the configuration callback will be
103108
// executed just once upon initialization, so there's no need to double-check that.
104-
//
109+
//
105110
// It should never be replaced by another implementation !!!
106111
// AddSingleton() will throw an exception if it was already registered
107112

@@ -127,10 +132,10 @@ public static IServiceCollection AddHangfire(
127132
// do configuration inside callback
128133

129134
configuration(serviceProvider, configurationInstance);
130-
135+
131136
return configurationInstance;
132137
});
133-
138+
134139
return services;
135140
}
136141

@@ -145,6 +150,7 @@ public static IServiceCollection AddHangfireServer([NotNull] this IServiceCollec
145150

146151
var options = provider.GetService<BackgroundJobServerOptions>() ?? new BackgroundJobServerOptions();
147152
var storage = provider.GetService<JobStorage>() ?? JobStorage.Current;
153+
var clock = provider.GetService<IClock>() ?? SystemClock.Current;
148154
var additionalProcesses = provider.GetServices<IBackgroundProcess>();
149155

150156
options.Activator = options.Activator ?? provider.GetService<JobActivator>();
@@ -156,7 +162,7 @@ public static IServiceCollection AddHangfireServer([NotNull] this IServiceCollec
156162
#pragma warning disable 618
157163
return new BackgroundJobServerHostedService(
158164
#pragma warning restore 618
159-
storage, options, additionalProcesses, factory, performer, stateChanger);
165+
storage, clock, options, additionalProcesses, factory, performer, stateChanger);
160166
});
161167

162168
return services;
@@ -186,7 +192,7 @@ internal static bool GetInternalServices(
186192
}
187193

188194
private static void TryAddSingletonChecked<T>(
189-
[NotNull] this IServiceCollection serviceCollection,
195+
[NotNull] this IServiceCollection serviceCollection,
190196
[NotNull] Func<IServiceProvider, T> implementationFactory)
191197
where T : class
192198
{
@@ -211,4 +217,4 @@ internal static void ThrowIfNotConfigured(IServiceProvider serviceProvider)
211217
}
212218
}
213219
}
214-
}
220+
}

0 commit comments

Comments
 (0)