elsa-workflows / elsa-workflows/elsa-extensions
Hangfire shell features incomplete: HangfireSchedulerShellFeature throws; BackgroundActivity scheduler not wired; UseMemoryStorage false is a no-op
- Dominant language
- C#
- Stars
- 49
- Forks
- 48
- Avg merge
- 21h 35m
- Merged PRs (30d)
- 20
Description
## Summary
The Elsa 3 **shell-feature** path for Hangfire in `Elsa.Scheduling.Hangfire` is not a working substitute for the classic `FeatureBase` path. Enabling these shell features today either crashes or silently fails to swap the core scheduler contracts.
This is separate from the long-running Hangfire *runtime* bugs (#121 duplicates on restart, elsa-core #3110 / #4819 / #7356). Those assume Hangfire is correctly registered; this issue is about the **new shell surface not actually installing** that registration.
## Evidence
### 1. `HangfireSchedulerShellFeature` is a stub
`src/modules/scheduling/Elsa.Scheduling.Hangfire/ShellFeatures/HangfireSchedulerShellFeature.cs`:
```csharp
public void ConfigureServices(IServiceCollection services)
{
throw new NotImplementedException();
}
```
Contrast with the classic path (`HangfireSchedulerFeature`), which wires `SchedulingFeature.WorkflowScheduler` to `HangfireWorkflowScheduler`, and with Quartz’s shell path (`QuartzSchedulerFeature`), which fully registers `IWorkflowScheduler`.
Enabling “Hangfire Workflow Scheduler” in the shell therefore cannot succeed.
### 2. `HangfireBackgroundActivitySchedulerShellFeature` does not replace `IBackgroundActivityScheduler`
`HangfireBackgroundActivitySchedulerShellFeature` only does:
```csharp
services.AddSingleton();
```
It never replaces the `IBackgroundActivityScheduler` registration. Core `WorkflowRuntimeFeature` (shell) still registers:
```csharp
.AddSingleton(BackgroundActivityScheduler) // defaults to LocalBackgroundActivityScheduler
```
The classic path (`HangfireBackgroundActivitySchedulerFeature`) correctly does:
```csharp
Module.Configure(f =>
f.BackgroundActivityScheduler = sp => sp.GetRequiredService());
```
So the shell toggle can look “on” while background activities still run on the local in-process queue.
### 3. `HangfireShellFeature.UseMemoryStorage = false` is a no-op
```csharp
var jobStorage = UseMemoryStorage ? new() : null ?? new MemoryStorage();
```
Both branches resolve to `MemoryStorage`. There is no alternate storage when the setting is false (and no SQL/other provider wiring on the shell feature, unlike the obsolete classic `UseSqlServerStorage` / `UseSqliteStorage` helpers).
## Proposed direction (subtractive / parity)
Prefer **parity with the classic FeatureBase wiring and with Quartz’s shell feature**, not a new abstraction:
1. Implement `HangfireSchedulerShellFeature` the same way `HangfireSchedulerFeature` / `QuartzSchedulerFeature` do: register `HangfireWorkflowScheduler` as `IWorkflowScheduler` (and the Cron descriptor modifier).
2. Wire `HangfireBackgroundActivityScheduler` as `IBackgroundActivityScheduler` (replace Local), matching `HangfireBackgroundActivitySchedulerFeature`.
3. Fix or remove the broken `UseMemoryStorage` setting until a real non-memory storage path exists on the shell feature; do not leave a toggle that cannot change behavior.
4. Optionally rename the misleading file `HangfireBackgroundActivityInvokerFeature.cs` (class is `HangfireBackgroundActivitySchedulerFeature`) while touching this area.
Milestone: leave unset for Triage / Crew Lead.
## Related (do not treat as duplicates)
- elsa-extensions #121 — duplicate Hangfire jobs on restart (runtime idempotency; assumes Hangfire is wired)
- elsa-core #3110, #4819, #7356, #8145 — runtime / architecture of background execution once Hangfire *is* in play
Contributor guide
Research direction
Start with src/modules/scheduling/Elsa.Scheduling.Hangfire/ShellFeatures/HangfireSchedulerShellFeature.cs and compare it with HangfireSchedulerFeature and QuartzSchedulerFeature. Inspect HangfireBackgroundActivitySchedulerShellFeature and HangfireShellFeature for the scheduler registration and UseMemoryStorage behavior. Done means the shell features install the Hangfire scheduler contracts and the storage setting no longer silently has the same effect for both values.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100