Skip to content

Commit

Permalink
Merge branch 'master' into Additional-query-to-get-jobs-by-id
Browse files Browse the repository at this point in the history
  • Loading branch information
hyper987654321 authored Feb 3, 2023
2 parents bc97589 + b6f3fc4 commit e4e811b
Show file tree
Hide file tree
Showing 12 changed files with 129 additions and 115 deletions.
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
License
========

Copyright © 2022 Hangfire OÜ.
Copyright © 2023 Hangfire OÜ.

Hangfire software is an open-source software that is multi-licensed under the terms of the licenses listed in this file. Recipients may choose the terms under which they are want to use or distribute the software, when all the preconditions of a chosen license are satisfied.

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ In order to give the community time to respond and upgrade we strongly urge you
License
--------

Copyright © 2022 Hangfire OÜ.
Copyright © 2023 Hangfire OÜ.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
Expand Down
2 changes: 1 addition & 1 deletion nuspecs/Hangfire.Core.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ An easy and reliable way to perform fire-and-forget, delayed and recurring, long
Backed by Redis, SQL Server, SQL Azure or MSMQ. This is a .NET alternative to Sidekiq, Resque and Celery.
https://www.hangfire.io/
</description>
<copyright>Copyright © 2013-2022 Hangfire OÜ</copyright>
<copyright>Copyright © 2013-2023 Hangfire OÜ</copyright>
<tags>Hangfire OWIN Long-Running Background Fire-And-Forget Delayed Recurring Tasks Jobs Scheduler Threading Queues</tags>
<releaseNotes>https://www.hangfire.io/blog/

Expand Down
2 changes: 1 addition & 1 deletion nuspecs/Hangfire.NetCore.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<licenseUrl>https://raw.github.com/HangfireIO/Hangfire/master/LICENSE.md</licenseUrl>
<description>.NET Core's Worker Service host support for Hangfire (background job system for ASP.NET applications).</description>
<copyright>Copyright © 2019-2022 Hangfire OÜ</copyright>
<copyright>Copyright © 2019-2023 Hangfire OÜ</copyright>
<tags>hangfire netcore</tags>
<releaseNotes>https://www.hangfire.io/blog/

Expand Down
2 changes: 1 addition & 1 deletion nuspecs/Hangfire.SqlServer.MSMQ.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<licenseUrl>https://raw.github.com/HangfireIO/Hangfire/master/LICENSE.md</licenseUrl>
<description>MSMQ queues support for SQL Server job storage implementation for Hangfire (background job system for ASP.NET applications).</description>
<copyright>Copyright © 2014-2022 Hangfire OÜ</copyright>
<copyright>Copyright © 2014-2023 Hangfire OÜ</copyright>
<tags>Hangfire SqlServer MSMQ</tags>
<releaseNotes>https://www.hangfire.io/blog/

Expand Down
13 changes: 9 additions & 4 deletions src/Hangfire.Core/Common/CancellationTokenExtentions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ namespace Hangfire.Common
{
public static class CancellationTokenExtentions
{
private static readonly ILog Logger = LogProvider.GetLogger(typeof(CancellationTokenExtentions));

/// <summary>
/// Returns a class that contains a <see cref="EventWaitHandle"/> that is set, when
/// the given <paramref name="cancellationToken"/> is canceled. This method is based
Expand Down Expand Up @@ -72,8 +70,15 @@ public static bool Wait(this CancellationToken cancellationToken, TimeSpan timeo
timeout >= timeoutThreshold &&
stopwatch.Elapsed < elapsedThreshold)
{
Logger.Error($"Actual wait time for non-canceled token was '{stopwatch.Elapsed}' instead of '{timeout}', wait result: {waitResult}, using protective wait. Please report this to Hangfire developers.");
Thread.Sleep(protectionTime);
try
{
var logger = LogProvider.GetLogger(typeof(CancellationTokenExtentions));
logger.Error($"Actual wait time for non-canceled token was '{stopwatch.Elapsed}' instead of '{timeout}', wait result: {waitResult}, using protective wait. Please report this to Hangfire developers.");
}
finally
{
Thread.Sleep(protectionTime);
}
}

return waitResult;
Expand Down
12 changes: 9 additions & 3 deletions src/Hangfire.Core/Processing/TaskExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ namespace Hangfire.Processing
{
internal static class TaskExtensions
{
private static readonly ILog Logger = LogProvider.GetLogger(typeof(TaskExtensions));
private static readonly Type[] EmptyTypes = new Type[0];
private static readonly WaitHandle InvalidWaitHandleInstance = new InvalidWaitHandle();

Expand Down Expand Up @@ -58,8 +57,15 @@ public static bool WaitOne([NotNull] this WaitHandle waitHandle, TimeSpan timeou
timeout >= timeoutThreshold &&
stopwatch.Elapsed < elapsedThreshold)
{
Logger.Error($"Actual wait time for non-canceled token was '{stopwatch.Elapsed}' instead of '{timeout}', wait result: {waitResult}, using protective wait. Please report this to Hangfire developers.");
Thread.Sleep(protectionTime);
try
{
var logger = LogProvider.GetLogger(typeof(TaskExtensions));
logger.Error($"Actual wait time for non-canceled token was '{stopwatch.Elapsed}' instead of '{timeout}', wait result: {waitResult}, using protective wait. Please report this to Hangfire developers.");
}
finally
{
Thread.Sleep(protectionTime);
}
}

token.ThrowIfCancellationRequested();
Expand Down
32 changes: 18 additions & 14 deletions src/Hangfire.Core/Server/AspNetShutdownDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ namespace Hangfire.Server
{
internal static class AspNetShutdownDetector
{
private static readonly ILog Logger = LogProvider.GetLogger(typeof(AspNetShutdownDetector));
private static readonly TimeSpan CheckForShutdownTimerInterval = TimeSpan.FromMilliseconds(250);
private static readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();

Expand Down Expand Up @@ -121,7 +120,7 @@ private static void EnsureInitialized()
}
catch (Exception ex) when (ex.IsCatchableExceptionType())
{
Logger.ErrorException("Failed to initialize shutdown triggers for ASP.NET application.", ex);
GetLogger().ErrorException("Failed to initialize shutdown triggers for ASP.NET application.", ex);
}
}

Expand Down Expand Up @@ -155,15 +154,15 @@ private static void CheckForAppDomainShutdown(object state)
}
catch (Exception ex) when (ex.IsCatchableExceptionType())
{
Logger.ErrorException(
GetLogger().ErrorException(
"An exception occurred while checking for ASP.NET shutdown, will not able to do the checks properly.",
ex);
}
}

private static void Cancel(string reason)
{
Logger.Info($"ASP.NET application is shutting down: {reason}.");
GetLogger().Info($"ASP.NET application is shutting down: {reason}.");

try
{
Expand All @@ -174,7 +173,7 @@ private static void Cancel(string reason)
}
catch (AggregateException ag)
{
Logger.ErrorException("One or more exceptions were thrown during app pool shutdown: ", ag);
GetLogger().ErrorException("One or more exceptions were thrown during app pool shutdown: ", ag);
}
}

Expand All @@ -189,12 +188,12 @@ private static void RegisterForStopListeningEvent(ref bool success)
if (stopEvent == null) return;

stopEvent.AddEventHandler(null, new EventHandler(StopListening));
Logger.Debug("HostingEnvironment.StopListening shutdown trigger initialized successfully.");
GetLogger().Debug("HostingEnvironment.StopListening shutdown trigger initialized successfully.");
success = true;
}
catch (Exception ex) when (ex.IsCatchableExceptionType())
{
Logger.DebugException("Unable to initialize HostingEnvironment.StopListening shutdown trigger", ex);
GetLogger().DebugException("Unable to initialize HostingEnvironment.StopListening shutdown trigger", ex);
}
}

Expand All @@ -215,7 +214,7 @@ private static void InitializeShutdownReason(ref bool success)

_shutdownReasonFunc = ShutdownReasonFunc;

Logger.Debug("HostingEnvironment.ShutdownReason shutdown trigger initialized successfully.");
GetLogger().Debug("HostingEnvironment.ShutdownReason shutdown trigger initialized successfully.");
success = true;

string ShutdownReasonFunc()
Expand All @@ -231,15 +230,15 @@ string ShutdownReasonFunc()
}
catch (Exception ex) when (ex.IsCatchableExceptionType())
{
Logger.TraceException("Unable to call the HostingEnvironment.ShutdownReason property due to an exception.", ex);
GetLogger().TraceException("Unable to call the HostingEnvironment.ShutdownReason property due to an exception.", ex);
}

return null;
}
}
catch (Exception ex) when (ex.IsCatchableExceptionType())
{
Logger.DebugException("Unable to initialize HostingEnvironment.ShutdownReason shutdown trigger", ex);
GetLogger().DebugException("Unable to initialize HostingEnvironment.ShutdownReason shutdown trigger", ex);
}
}

Expand All @@ -255,12 +254,12 @@ private static void InitializeMgdHasConfigChanged(ref bool success)

_checkConfigChangedFunc = (Func<bool>)Delegate.CreateDelegate(typeof(Func<bool>), methodInfo);

Logger.Debug("UnsafeIISMethods.MgdHasConfigChanged shutdown trigger initialized successfully.");
GetLogger().Debug("UnsafeIISMethods.MgdHasConfigChanged shutdown trigger initialized successfully.");
success = true;
}
catch (Exception ex) when (ex.IsCatchableExceptionType())
{
Logger.DebugException("Unable to initialize UnsafeIISMethods.MgdHasConfigChanged shutdown trigger", ex);
GetLogger().DebugException("Unable to initialize UnsafeIISMethods.MgdHasConfigChanged shutdown trigger", ex);
}
}

Expand All @@ -282,12 +281,12 @@ private static void InitializeDisposingHttpRuntime(ref bool success)

_disposingHttpRuntime = () => disposingHttpRuntime(theRuntime());

Logger.Debug("HttpRuntime._disposingHttpRuntime shutdown trigger initialized successfully.");
GetLogger().Debug("HttpRuntime._disposingHttpRuntime shutdown trigger initialized successfully.");
success = true;
}
catch (Exception ex)
{
Logger.DebugException("Unable to initialize HttpRuntime._disposingHttpRuntime shutdown trigger", ex);
GetLogger().DebugException("Unable to initialize HttpRuntime._disposingHttpRuntime shutdown trigger", ex);
}
}

Expand All @@ -305,5 +304,10 @@ private static Func<object, T> CreateGetFieldDelegate<T>(FieldInfo fieldInfo, Ty
return Expression.Lambda<Func<object, T>>(fieldExp, instExp).Compile();
}
#endif

private static ILog GetLogger()
{
return LogProvider.GetLogger(typeof(AspNetShutdownDetector));
}
}
}
10 changes: 10 additions & 0 deletions src/Hangfire.NetCore/AspNetCore/AspNetCoreJobActivatorScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ public override object Resolve(Type type)

public override void DisposeScope()
{
#if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1
if (_serviceScope is IAsyncDisposable asyncDisposable)
{
// Service scope disposal is triggered inside a dedicated background thread,
// while Task result is being set in CLR's Thread Pool, so no deadlocks on
// wait should happen.
asyncDisposable.DisposeAsync().ConfigureAwait(false).GetAwaiter().GetResult();
return;
}
#endif
_serviceScope.Dispose();
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/Hangfire.SqlServer/SqlServerConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -472,11 +472,11 @@ public override void AnnounceServer(string serverId, ServerContext context)
{
connection.Execute(
$@";merge [{_storage.SchemaName}].Server with (holdlock) as Target
using (VALUES (@id, @data, @heartbeat)) as Source (Id, Data, Heartbeat)
using (VALUES (@id, @data, sysutcdatetime())) as Source (Id, Data, Heartbeat)
on Target.Id = Source.Id
when matched then update set Data = Source.Data, LastHeartbeat = Source.Heartbeat
when not matched then insert (Id, Data, LastHeartbeat) values (Source.Id, Source.Data, Source.Heartbeat);",
new { id = serverId, data = SerializationHelper.Serialize(data), heartbeat = DateTime.UtcNow },
new { id = serverId, data = SerializationHelper.Serialize(data) },
commandTimeout: _storage.CommandTimeout);
});
}
Expand All @@ -501,8 +501,8 @@ public override void Heartbeat(string serverId)
_storage.UseConnection(_dedicatedConnection, connection =>
{
var affected = connection.Execute(
$@"update [{_storage.SchemaName}].Server set LastHeartbeat = @now where Id = @id",
new { now = DateTime.UtcNow, id = serverId },
$@"update [{_storage.SchemaName}].Server set LastHeartbeat = sysutcdatetime() where Id = @id",
new { id = serverId },
commandTimeout: _storage.CommandTimeout);

if (affected == 0)
Expand All @@ -520,8 +520,8 @@ public override int RemoveTimedOutServers(TimeSpan timeOut)
}

return _storage.UseConnection(_dedicatedConnection, connection => connection.Execute(
$@"delete s from [{_storage.SchemaName}].Server s with (readpast, readcommitted) where LastHeartbeat < @timeOutAt",
new { timeOutAt = DateTime.UtcNow.Add(timeOut.Negate()) },
$@"delete s from [{_storage.SchemaName}].Server s with (readpast, readcommitted) where LastHeartbeat < dateadd(ms, @timeoutMsNeg, sysutcdatetime())",
new { timeoutMsNeg = timeOut.Negate().TotalMilliseconds },
commandTimeout: _storage.CommandTimeout));
}

Expand Down
Loading

0 comments on commit e4e811b

Please sign in to comment.