FabulousScheduler.Core
5.1.0
dotnet add package FabulousScheduler.Core --version 5.1.0
NuGet\Install-Package FabulousScheduler.Core -Version 5.1.0
<PackageReference Include="FabulousScheduler.Core" Version="5.1.0" />
<PackageVersion Include="FabulousScheduler.Core" Version="5.1.0" />
<PackageReference Include="FabulousScheduler.Core" />
paket add FabulousScheduler.Core --version 5.1.0
#r "nuget: FabulousScheduler.Core, 5.1.0"
#:package FabulousScheduler.Core@5.1.0
#addin nuget:?package=FabulousScheduler.Core&version=5.1.0
#tool nuget:?package=FabulousScheduler.Core&version=5.1.0
Core (FabulousScheduler.Core)
FabulousScheduler.Core holds the pieces both subsystems share. There is no scheduling logic
in here, only the contracts (IJob, IJobScheduler, IJobOk, IJobFail) and the
JobResult<TOk, TFail> type.
If you want the big picture first, read General concepts.
📖 Contents
IJob <a id="ijob" />
FabulousScheduler.Core.Interfaces.IJob is the identity every job carries. It also implements
IDisposable and IAsyncDisposable.
| Member | Type | Meaning |
|---|---|---|
ID |
Guid |
Unique id, generated when the job is created. |
Name |
string |
A readable name. If you don't pass one, it defaults to "anonymous". |
LastExecute |
DateTime? |
When the job last ran, success or not. null until the first run. |
LastSuccessExecute |
DateTime? |
When the job last ran successfully. null until the first success. |
Each subsystem has its own interface on top of IJob:
IRecurringJobaddsCategory,State,SleepDuration,TotalRun,TotalFailandExecuteAsync(). See Recurring.md.IQueueJobaddsState,TotalRun,Attempts,ExecuteAsync()andResetState(). See QueueBased.md.
IJobScheduler <a id="ijobscheduler" />
FabulousScheduler.Core.Interfaces.IJobScheduler is the smallest scheduler contract. It
implements IDisposable.
public interface IJobScheduler : IDisposable
{
void RunScheduler(); // start the scheduler
}
IRecurringJobScheduler and IQueueJobScheduler both extend it and add a JobResultEvent
(with a JobResultEventHandler delegate) that fires after every run, using the job and result
types of their subsystem.
IJobOk / IJobFail <a id="results" />
These are the two markers a result can hold. Each one exposes the job ID and nothing else.
The real payload (a message, a reason, the original exception) lives on the concrete types that
each subsystem ships.
public interface IJobOk { Guid ID { get; } }
public interface IJobFail { Guid ID { get; } }
| Subsystem | Ok type | Fail type | Extra members on the fail type |
|---|---|---|---|
| Recurring | Recurring.Result.JobOk |
Recurring.Result.JobFail |
Reason (JobFailEnum), Message, Exception? |
| Queue | Queue.Result.JobOk |
Queue.Result.JobFail |
Reason (QueueJobFailEnum), Message, Exception? |
Both JobFail types are plain result objects. When a job fails, you read the reason, the
message and (if there was one) the original exception off the object. You never throw it.
JobResult<TOk, TFail> <a id="jobresult" />
FabulousScheduler.Core.Types.JobResult<TOk, TFail> (where TOk : IJobOk,
where TFail : IJobFail) is a tiny either/or value. It carries a success value or a failure
value, one of the two, and it does not use exceptions to signal which.
Creating a result
You rarely call a constructor. A JobOk or a JobFail converts into a result on its own:
JobResult<JobOk, JobFail> ok = new JobOk(id); // becomes a success
JobResult<JobOk, JobFail> fail = new JobFail(reason, id, "msg"); // becomes a failure
Inspecting
| Member | Type | Meaning |
|---|---|---|
IsSuccess |
bool |
true when it holds a TOk. |
IsFail |
bool |
true when it holds a TFail. |
JobID |
Guid |
The job's ID, whatever the outcome. |
GetFail() |
TFail? |
The failure, or null on success. |
Consuming
| Method | Returns | What it's for |
|---|---|---|
Do(Action<TOk> success, Action<TFail> failure) |
void |
a side effect per branch |
Match<TResult>(Func<TOk,TResult> success, Func<TFail,TResult> failure) |
TResult |
turn both branches into one value |
Match<TResult,TFailResult>(Func<TOk?,TFail?,(TResult,TFailResult)> f) |
(TResult, TFailResult) |
a low-level tuple projection |
MatchAsync<TResult>(Func<TOk,Task<TResult>>, Func<TFail,Task<TResult>>) |
Task<TResult> |
the async version of Match |
// A side effect per branch
result.Do(
success: ok => Console.WriteLine("{0} succeeded", ok.JobID),
failure: fail => Console.WriteLine("{0} failed: {1}", fail.JobID, fail.Message)
);
// Map to a value
string msg = result.Match(
success: ok => $"{ok.JobID} succeeded",
failure: fail => $"{fail.JobID} failed: {fail.Message}"
);
// Async
int code = await result.MatchAsync(
success: async ok => { await Task.Yield(); return 0; },
failure: async fail => { await Task.Yield(); return 1; }
);
One thing to watch: every JobResult is a class, so it allocates. With a lot of jobs per second
that adds up. There are numbers for it in Benchmarks.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. 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. |
-
net8.0
- No dependencies.
NuGet packages (2)
Showing the top 2 NuGet packages that depend on FabulousScheduler.Core:
| Package | Downloads |
|---|---|
|
FabulousScheduler.Cron
Write your self recurring jobs |
|
|
FabulousScheduler.Queue
Write your self queue-based jobs |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 5.1.0 | 166 | 8/1/2026 |
| 5.0.1 | 181 | 6/18/2026 |
| 5.0.0 | 166 | 6/18/2026 |
| 4.0.0 | 357 | 3/20/2025 |
| 3.1.3 | 10,116 | 6/14/2024 |
| 3.1.0 | 11,954 | 2/3/2024 |
| 3.0.1 | 317 | 1/27/2024 |
| 2.2.7 | 683 | 1/17/2024 |
| 2.2.6 | 293 | 1/17/2024 |
| 2.2.5 | 307 | 1/17/2024 |
| 2.2.4 | 277 | 1/17/2024 |
| 2.2.3 | 317 | 1/12/2024 |
| 2.2.2 | 307 | 1/9/2024 |
| 2.2.1 | 300 | 1/8/2024 |
| 2.1.6 | 353 | 1/2/2024 |
| 2.1.5 | 360 | 1/1/2024 |
| 2.1.2 | 454 | 1/1/2024 |