# Hangfire.RedisStackExchange.ForkEnhanced **Repository Path**: 992582781/Hangfire.RedisStackExchange.ForkEnhanced ## Basic Information - **Project Name**: Hangfire.RedisStackExchange.ForkEnhanced - **Description**: Enhanced fork of Hangfire.Redis.StackExchange. Hangfire Redis Storage Based on Redis.StackExchange.基于 1.12.0 全面重构,包含 17 项 P0/P1 Bug 修复、事务原子性保障、全链路 NRE 加固、294 个测试用例 100% 覆盖。向后完全兼容,建议所有生产环境升级。 - **Primary Language**: C# - **License**: LGPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-09-04 - **Last Updated**: 2026-09-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Fork\.Hangfire\.Redis\.StackExchange\.Enhanced Documentation **⚠️ Important Version \& Maintenance Statement**: The open\-source component **Hangfire\.Redis\.StackExchange** is licensed under LGPL\-3\.0, free of charge and available for commercial use\. The upstream repository is not formally archived, but functional development has effectively stalled\. The original maintainer only merges a small number of emergency hotfixes, ignores most production boundary bugs, and no longer accepts community PRs or issue feedback\. This project is an enhanced fork based on the original open\-source codebase\. It fully inherits the original open\-source license and maintains full compatibility with all native usage methods\. It deeply refactors and optimizes the original source code, fixes various production\-level defects including Redis network jitter exceptions, stuck and piled\-up jobs, duplicate execution, and cluster lock conflicts\. Multiple enterprise\-grade enhanced features are added and continuously maintained\. It provides \.NET developers with a free, commercially available, non\-binding production\-level Hangfire Redis storage solution with significantly higher stability and availability than the original upstream package\. ## ✨ Core Enhancements \& Bug Fixes \(vs Original Version\) - **Network Fault Tolerance Enhancement**: Fix background process crashes caused by instantaneous Redis disconnection and network jitter\. All `IBackgroundProcess` background processes are isolated from each other\. Single process failure will not affect the overall job scheduling, with automatic retry and recovery capability\. - **Dirty Key Fault Tolerance Protection**: Provide degradation and fault tolerance for corrupted, malformed, or mismatched Redis keys/hashes\. Prevent worker process crashes caused by invalid Redis data and ensure long\-term service stability\. - **Optimized Pub\-Sub Queue Wake\-up**: Implement queue\-targeted message wake\-up to avoid the global broadcast thundering herd problem\. Retain polling fallback mechanism without relying on Pub\-Sub message reliability, supporting cluster rolling upgrades\. - **Controllable Timeout Job Strategy**: New configuration `SkipRequeueOnTimeout`\. Supports custom processing logic for timeout/crashed orphan jobs to avoid infinite re\-queuing and duplicate execution risks\. - **Job Contention Pressure Optimization**: Add random jitter strategy for job fetching, relieve instantaneous job competition pressure in multi\-instance clusters, and balance cluster load evenly\. - **Distributed Lock Refactoring**: Optimize boundary logic for distributed lock renewal, preemption and release\. Solve native defects such as lock timeout, accidental release, and lock contention conflicts\. - **Transaction \& Lua Script Hardening**: Improve transaction atomicity for List\-based queue operations\. Fix native script execution exceptions and transaction commit conflicts to enhance overall data consistency\. ## Installation NuGet installation command: ```bash dotnet add package Fork.Hangfire.Redis.StackExchange.Enhanced ``` ## Basic Configuration ### 1\. Minimal Quick Configuration Suitable for local testing and simple business scenarios, uses original default parameters: ```csharp using Hangfire; using Hangfire.Redis.StackExchange; builder.Services.AddHangfire(configuration => configuration .UseRedisStorage("redis://localhost:6379")); ``` ### 2\. Production Recommended Full Configuration Enable enhanced features, custom database and timeout strategies for production cluster environments: ```csharp using Hangfire; using Hangfire.Redis.StackExchange; builder.Services.AddHangfire(configuration => configuration .UseRedisStorage("redis://localhost:6379", new RedisStorageOptions { Prefix = "MyApp:", Db = 11, UseTransactions = true, InvisibilityTimeout = TimeSpan.FromMinutes(30), FetchTimeout = TimeSpan.FromMinutes(3), ExpiryCheckInterval = TimeSpan.FromHours(1), SkipRequeueOnTimeout = false, EnableFetchJitter = true, FetchJitterMaxMs = 300 })); ``` ## Worker Cluster \& Queue Configuration ### Basic Service Configuration Supports custom worker concurrency, independent business queues, service heartbeat detection, scheduled task polling, node timeout judgment, adapting to standalone and multi\-instance cluster production architectures: ```csharp builder.Services.AddHangfireServer(options => { // Custom listening queues for business isolation options.Queues = new[] { "calculateshiftdata", "default" }; // Current instance worker concurrency count options.WorkerCount = 1; // Scheduled task polling interval options.SchedulePollingInterval = TimeSpan.FromSeconds(1); // Service heartbeat reporting interval options.HeartbeatInterval = TimeSpan.FromSeconds(10); // Node timeout threshold, regarded as offline after timeout options.ServerTimeout = TimeSpan.FromSeconds(30); }); ``` ### Enqueue Jobs to Specific Queues Support multi\-queue business isolation to avoid mutual blocking between different businesses: ```csharp // Enqueue to custom business queue BackgroundJob.Enqueue("calculateshiftdata", x => x.Calculate(1)); // Enqueue to default queue BackgroundJob.Enqueue("default", x => x.Execute(1)); ``` ### Worker Implementation Specification All task execution methods must return Task and support asynchronous business logic: ```csharp public class ShiftDataWorker { public async Task Calculate(int id) { Console.WriteLine($"Processing shift data id={id}"); await Task.Delay(100); } } public class DefaultWorker { public Task Execute(int id) { Console.WriteLine($"Executing job id={id}"); return Task.CompletedTask; } } ``` ## Dashboard Integration Native support for Hangfire visual dashboard without extra configuration, enabling full lifecycle task monitoring: ```csharp var app = builder.Build(); // Enable Hangfire Dashboard app.UseHangfireDashboard(); app.MapHangfireDashboard("/hangfire"); // Redirect root path to dashboard app.MapGet("/", () => Results.Redirect("/hangfire")); app.Run(); ``` Access URL: `YourDomain/hangfire` The dashboard supports real\-time monitoring of service node status, queue load, full task lifecycle records \(queued, succeeded, failed, deleted, retried\), cron job configuration and running logs, providing comprehensive visual scheduling monitoring\. ## Test API Examples Simple test APIs for quickly verifying queue enqueue, task scheduling and batch execution capabilities: ```csharp // Batch enqueue custom queue jobs app.MapPost("/enqueue", (string queue = "calculateshiftdata", int count = 1) => { var jobIds = new List(); for (int i = 0; i < count; i++) { var jobId = BackgroundJob.Enqueue(queue, x => x.Calculate(i)); jobIds.Add(jobId); } return Results.Ok(new { queue, count, jobIds }); }); // Batch enqueue default queue jobs app.MapPost("/enqueue-default", (int count = 1) => { var jobIds = new List(); for (int i = 0; i < count; i++) { var jobId = BackgroundJob.Enqueue("default", x => x.Execute(i)); jobIds.Add(jobId); } return Results.Ok(new { queue = "default", count, jobIds }); }); ``` ## Transaction Capability Description ### Core Features - Improve transaction atomicity for queue operations such as `ListTrim` and `ListRemove` to ensure batch data consistency - All transaction operations are executed in batches at the `Commit()` stage to reduce network IO overhead - Compatible with non\-transaction operations via`_directOperations` mechanism to adapt to various Redis runtime scenarios ### Usage Notes - `UseTransactions = true` \(enabled by default\): All queue and task modification operations are wrapped in Redis transactions to guarantee atomicity - When Redis network is unstable, disable transactions temporarily \(`UseTransactions = false`\) to avoid transaction blocking failures ## RedisStorageOptions Full Configuration Reference |Property|Type|Default|Description| |---|---|---|---| |Prefix|string|"\{hangfire\}:"|Global Redis key prefix for multi\-project isolation| |Db|int|0|Specify Redis database index| |UseTransactions|bool|true|Enable Redis transaction to ensure atomic task operations| |InvisibilityTimeout|TimeSpan|30 min|Job lock timeout; timed\-out jobs will be re\-queued by default| |FetchTimeout|TimeSpan|3 min|Worker polling interval when queue is empty| |ExpiryCheckInterval|TimeSpan|1 hour|Interval for cleaning expired and completed job data| |SucceededListSize|int|499|Max retained records for succeeded jobs| |DeletedListSize|int|499|Max retained records for deleted jobs| |LifoQueues|string\[\]|\[\]|Queues that apply Last\-In\-First\-Out strategy| |RemoveFromQueue|bool|false|Enable atomic Lua queue removal logic for higher task state stability| |SkipRequeueOnTimeout|bool|false|Core enhanced config: timeout/crashed jobs will be marked as failed instead of re\-queued, eliminating duplicate execution| |EnableFetchJitter|bool|false|Enable job fetch jitter to relieve cluster task contention pressure| |FetchJitterMaxMs|int|300|Maximum jitter milliseconds, effective only when EnableFetchJitter is true| ## Redis Connection String Format ```bash # Local basic connection redis://localhost:6379 # With SSL & password authentication redis://localhost:6379,ssl=false,password=yourpassword # With account password & specified database redis://user:password@localhost:6379,db=11 ``` ## Full Runnable Demo ```csharp using Hangfire; using Hangfire.Redis.StackExchange; var builder = WebApplication.CreateBuilder(args); // Register enhanced Redis storage builder.Services.AddHangfire(configuration => configuration .UseRedisStorage("redis://localhost:6379", new RedisStorageOptions { Prefix = "PlantDataService:", Db = 11, UseTransactions = true, SkipRequeueOnTimeout = false, EnableFetchJitter = true })); // Register Hangfire server builder.Services.AddHangfireServer(options => { options.Queues = new[] { "calculateshiftdata", "default" }; options.WorkerCount = 1; }); var app = builder.Build(); // Enable dashboard app.UseHangfireDashboard(); app.MapHangfireDashboard("/hangfire"); app.MapGet("/", () => Results.Redirect("/hangfire")); // Test enqueue api app.MapPost("/enqueue", (string queue = "calculateshiftdata", int count = 1) => { var jobIds = new List(); for (int i = 0; i < count; i++) { var jobId = BackgroundJob.Enqueue(queue, x => x.Calculate(i)); jobIds.Add(jobId); } return Results.Ok(new { queue, count, jobIds }); }); app.Run(); // Worker implementation public class ShiftDataWorker { public async Task Calculate(int id) { Console.WriteLine($"[ShiftDataWorker] Processing shift data id={id}"); await Task.Delay(100); } } public class DefaultWorker { public Task Execute(int id) { Console.WriteLine($"[DefaultWorker] Executing job id={id}"); return Task.CompletedTask; } } ``` ## License This project fully inherits the original **LGPL\-3\.0** open\-source license\. It is open\-source, free for commercial use, without additional copyright binding\. Users can freely use, modify and distribute the project in compliance with the LGPL\-3\.0 license terms\.