# Corfedo Work

> Background work for .NET that lives in your database and commits in your transactions.

Wojciech Wentland · https://blog.wentland.io/projects/corfedo-work/

Status: alpha · License: Apache-2.0 · Source: https://github.com/corfedo/corfedo-work

You request work in the same transaction as the change that needs it, so a rollback leaves nothing behind. There is
no broker, no scheduler process and no second database. PostgreSQL is supported today.

```csharp
await using var transaction = await connection.BeginTransactionAsync(ct);
// INSERT INTO users ...
await jobs.RequestAsync(transaction, Jobs.Welcome, new WelcomeArgs(42), cancellationToken: ct);
await transaction.CommitAsync(ct);   // no commit, no job
```

## How it works

- A row with a lease. A worker claims a due row and holds it for a short lease, renewed while it runs. If the
  worker dies, the lease expires and another replica picks the row up. No cleanup job resets stuck work.
- A fence on every write. Each claim gets a new fence number. A worker that lost its lease can no longer commit,
  even if it keeps running.
- A wake-up at commit. When a transaction that makes work due commits, the processes that run it are notified.
  Polling stays as a slow fallback.

Jobs, cron schedules, leases on your own tables, reconciliation and signals are built on those three. Each works
alone: signals need no framework tables, and leases need no jobs.

## The problems it is for

- A job ran before the row it needed was committed, or a rollback left the job behind.
- A killed pod left a job "processing" until someone reset it.
- A worker whose lock had expired kept writing after another worker took over.
- Two replicas both ran the nightly cron job.
- One tenant's backlog starved every other tenant.
- A status column in your table drifted from the job framework's own state.

## What it is not

- Not exactly-once. Work runs at least once. Fencing protects writes to the same database; an email or an HTTP call
  cannot be taken back, so handlers deduplicate them with the run's stable execution ID.
- Not a message bus, and not a workflow engine that replays code.
- No dashboard. Status, history and incidents are APIs and OpenTelemetry signals.

## Status

Alpha: the API can still change. Install it from NuGet with `dotnet add package Corfedo.Work.PostgreSql`. The core
and the PostgreSQL store are trimming and Native AOT compatible. Coming from Hangfire, Quartz.NET or TickerQ? The
[repository on GitHub](https://github.com/corfedo/corfedo-work) has a migration guide for each, along with the
getting-started guide and the design documents.
