WJb 0.112.0
See the version list below for details.
dotnet add package WJb --version 0.112.0
NuGet\Install-Package WJb -Version 0.112.0
<PackageReference Include="WJb" Version="0.112.0" />
<PackageVersion Include="WJb" Version="0.112.0" />
<PackageReference Include="WJb" />
paket add WJb --version 0.112.0
#r "nuget: WJb, 0.112.0"
#:package WJb@0.112.0
#addin nuget:?package=WJb&version=0.112.0
#tool nuget:?package=WJb&version=0.112.0
⚡ WJb
If you can't explain why a job runs, you don't control your system.
Most background job systems eventually become:
Job
↓
Retry
↓
Pipeline
↓
Middleware
↓
???
Then somebody asks:
- Why did this run?
- Why was it retried?
- Who scheduled the next step?
- Where is that logic?
And nobody can answer in 30 seconds.
WJb
WJb is an explicit background job engine for .NET.
Job
↓
Action
↓
ActionResult
↓
JobCommand
Every step is visible.
Every transition is explicit.
Every workflow is defined in code.
Example
Workflow:
send-email
↓
log
↓
done
public sealed class SendEmailAction : JobAction<EmailInput>
{
public override Task<ActionResult> ExecuteAsync(
EmailInput input,
CancellationToken ct)
{
return Task.FromResult(
ActionResults.Next(
new JobCommand(
"log",
new LogInput
{
Message = $"Email sent to {input.To}"
})));
}
}
public sealed class LogAction : JobAction<LogInput>
{
public override Task<ActionResult> ExecuteAsync(
LogInput input,
CancellationToken ct)
{
Console.WriteLine(input.Message);
return Task.FromResult(
ActionResults.None());
}
}
The workflow is not hidden.
The action decides what happens next.
Performance
WJb is designed to minimize overhead and unnecessary abstractions.
Benchmarks:
👉 https://github.com/UkrGuru/WJb.Demo/tree/main/benchmark
Quick Start
var store = new InMemoryStore();
var wjb = WJbBuilder.Create(
store,
cfg =>
{
cfg.AddAction<SendEmailAction>("send-email");
cfg.AddAction<LogAction>("log");
});
await wjb.EnqueueAsync(
"send-email",
new EmailInput
{
To = "user@test.com"
});
await wjb.ExecuteLoopAsync();
Large Payloads
WJb supports large payloads, but jobs should generally remain small.
Preferred:
var bodyId = await storage.SaveAsync(
htmlStream,
".html");
await wjb.EnqueueAsync(
"send-email",
new
{
To = "user@test.com",
Subject = "Monthly report",
Body = bodyId
});
Instead of:
await wjb.EnqueueAsync(
"send-email",
new
{
To = "user@test.com",
Subject = "Monthly report",
Body = hugeHtmlString
});
WJb does not automatically pack or unpack data.
Store = Jobs
Storage = Large Content
Action = Decides When Storage Is Used
What Makes WJb Different?
✅ Explicit workflows
✅ Explicit retries
✅ Explicit next-step scheduling
✅ Constructor injection
✅ Strongly typed actions
✅ Business logic in code
❌ Hidden pipelines
❌ Hidden orchestration
❌ Workflow magic
Mental Model
Action = Business Logic
ActionResult = Outcome
JobCommand = Next Step
Executor = Runner
Store = Persistence
That's it.
Packages
| Package | Description |
|---|---|
| WJb | Explicit background job engine |
| WJb.UI.Blazor | Monitoring and administration UI |
| WJb.Sql | Commercial SQL Server storage provider |
| WJb.Pro | Commercial features and extensions |
Use WJb If
You want to answer all of these immediately:
- Why did this job run?
- What did it do?
- What will run next?
- Why was it retried?
Support
📧 ukrguru@gmail.com
Background jobs shouldn't be magic.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on WJb:
| Package | Downloads |
|---|---|
|
WJb.UI.Blazor
Free Blazor monitoring and administration UI for WJb. Includes jobs monitoring, actions management, services configuration, payload inspection and action testing. |
GitHub repositories
This package is not used by any popular GitHub repositories.
- Removed JobRecord and simplified internal job model.
- Improved enqueue performance and reduced allocations.
- Migrated payload and result handling to JsonNode.
- Removed legacy { value = ... } wrappers for scalar results.
- Simplified ActionResult processing pipeline.
- Preserved defensive payload copying to prevent accidental mutations.
- Cleaned up and expanded unit test coverage.
- General code cleanup and consistency improvements.