Created
January 10, 2019 00:17
-
-
Save arxae/7741bae2c742d8fb3e64abfc89028dd8 to your computer and use it in GitHub Desktop.
Apply to class that executes a job in Hangfire. If a recurring job with this attribute is already running, a new one won't start
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using Hangfire.Client; | |
using Hangfire.Common; | |
using Hangfire.States; | |
using Hangfire.Storage; | |
/// <summary> | |
/// Makes sure that 2 (or more) same jobs will not be run twice at the same time. | |
/// If a job is already running, the new job will be skipped | |
/// </summary> | |
[AttributeUsage(AttributeTargets.All)] | |
public class SkipWhenPreviousJobIsRunningAttribute : JobFilterAttribute, IClientFilter, IApplyStateFilter | |
{ | |
public void OnCreating(CreatingContext filterContext) | |
{ | |
var connection = (JobStorageConnection)filterContext.Connection; | |
// We can't handle old storages | |
if (connection == null) return; | |
// We should run this filter only for background jobs based on | |
// recurring ones | |
if (filterContext.Parameters.ContainsKey("RecurringJobId") == false) return; | |
var recurringJobId = filterContext.Parameters["RecurringJobId"] as string; | |
// RecurringJobId is malformed. This should not happen, but anyway. | |
if (string.IsNullOrWhiteSpace(recurringJobId)) return; | |
var running = connection.GetValueFromHash($"recurring-job:{recurringJobId}", "Running"); | |
if ("yes".Equals(running, StringComparison.OrdinalIgnoreCase)) | |
{ | |
filterContext.Canceled = true; | |
} | |
} | |
public void OnStateApplied(ApplyStateContext context, IWriteOnlyTransaction transaction) | |
{ | |
if (context.NewState is EnqueuedState) | |
{ | |
var recurringJobId = JobHelper.FromJson<string>(context.Connection.GetJobParameter(context.BackgroundJob.Id, "RecurringJobId")); | |
if (string.IsNullOrWhiteSpace(recurringJobId)) return; | |
transaction.SetRangeInHash( | |
$"recurring-job:{recurringJobId}", | |
new[] { new KeyValuePair<string, string>("Running", "yes") }); | |
} | |
else if (context.NewState.IsFinal) | |
{ | |
var recurringJobId = JobHelper.FromJson<string>(context.Connection.GetJobParameter(context.BackgroundJob.Id, "RecurringJobId")); | |
if (string.IsNullOrWhiteSpace(recurringJobId)) return; | |
transaction.SetRangeInHash( | |
$"recurring-job:{recurringJobId}", | |
new[] { new KeyValuePair<string, string>("Running", "no") }); | |
} | |
} | |
public void OnCreated(CreatedContext filterContext) | |
{ | |
// Method intentionally left empty. | |
} | |
public void OnStateUnapplied(ApplyStateContext context, IWriteOnlyTransaction transaction) | |
{ | |
// Method intentionally left empty. | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment