Skip to content

Instantly share code, notes, and snippets.

@odinserj
Created August 21, 2018 15:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save odinserj/795765787b7900d00e61a8d1c8d495f8 to your computer and use it in GitHub Desktop.
Save odinserj/795765787b7900d00e61a8d1c8d495f8 to your computer and use it in GitHub Desktop.
using System;
using System.Threading.Tasks;
using Hangfire;
using Hangfire.Common;
using Hangfire.States;
using Hangfire.Storage;
using Microsoft.Owin.Hosting;
using Owin;
namespace ConsoleApp71
{
// You can use this filter to shorted the expiration time for jobs that are
// in the Failed -> Deleted state transition. Otherwise they will be expired
// in 24 hours by default.
public class ImmediateDeletionAttribute : JobFilterAttribute, IApplyStateFilter
{
public void OnStateApplied(ApplyStateContext context, IWriteOnlyTransaction transaction)
{
if (context.OldStateName == FailedState.StateName)
{
context.JobExpirationTimeout = TimeSpan.Zero;
}
}
public void OnStateUnapplied(ApplyStateContext context, IWriteOnlyTransaction transaction)
{
}
}
public class ThrowingService
{
[ImmediateDeletion, AutomaticRetry(Attempts = 0)]
public void ThrowingMethod()
{
throw new PlatformNotSupportedException();
}
public void DeleteStepByStep()
{
const int batchCount = 1000;
var storage = JobStorage.Current;
var monitoring = storage.GetMonitoringApi();
var stateChanger = new BackgroundJobStateChanger();
var failedJobs = monitoring.FailedJobs(0, batchCount);
if (failedJobs == null || failedJobs.Count == 0)
{
return;
}
using (var connection = storage.GetConnection())
{
foreach (var failedJob in failedJobs)
{
stateChanger.ChangeState(new StateChangeContext(
storage,
connection,
failedJob.Key,
new DeletedState { Reason = "Removed automatically" },
FailedState.StateName
));
}
}
if (failedJobs.Count == batchCount)
{
BackgroundJob.Enqueue<ThrowingService>(x => x.DeleteStepByStep());
}
}
}
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseHangfireDashboard("");
app.UseHangfireServer();
}
}
class Program
{
static void Main(string[] args)
{
GlobalConfiguration.Configuration
.UseRedisStorage()
.UseFilter(new ImmediateDeletionAttribute());
Parallel.For(0, 1000000, _ => { BackgroundJob.Enqueue<ThrowingService>(x => x.ThrowingMethod()); });
// Uncommend the following line once all the jobs are in the failed state
// to start the deletion process.
//BackgroundJob.Enqueue<ThrowingService>(x => x.DeleteStepByStep());
using (WebApp.Start<Startup>("http://localhost:12345"))
{
Console.ReadLine();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment