Hey, I saw the filter someone created which stopped new tasks from being created if one already exists. I needed something different where I would delete an existing job and replace it with a new one.
I filter on the job type and arguments passed. For this use-case, we only care about scheduled jobs. If one is already running, I ignore it… Here you go:
namespace Keg.Web.Filters
{
using System;
using System.Linq;
using Hangfire;
using Hangfire.Client;
using Hangfire.Common;
using Hangfire.States;
using Hangfire.Storage;
public class ReplaceScheduledJobFilter: JobFilterAttribute, IClientFilter
{
public void OnCreating(CreatingContext filterContext)
{
var connection = filterContext.Connection;
var storageConnection = connection as JobStorageConnection;
if (storageConnection == null)
{
return;
}
var currentArgs = filterContext.Job.Args.Select(Convert.ToString);
var jobIdsToRemove = storageConnection
.GetAllItemsFromSet("schedule")
.Select(jobId => new
{
Id = jobId,
JobData = storageConnection.GetJobData(jobId),
})
.Where(dataset => dataset.JobData.Job.Type == filterContext.Job.Type)
.Where(dataset =>
currentArgs.Intersect(dataset.JobData.Job.Args.Select(Convert.ToString)).Any())
.Select(dataset => dataset.Id);
var client = new BackgroundJobClient(JobStorage.Current);
foreach (var jobId in jobIdsToRemove)
{
client.ChangeState(jobId, new DeletedState { Reason = "[ReplaceScheduledJobFilter]" }, ScheduledState.StateName);
}
}
public void OnCreated(CreatedContext filterContext)
{
}
}
}
Let me know if there is a way to improve this. I need an API to select all the JobData
in a single query instead of potentially doing hundreds/thousands of queries.