Quick Start
This takes about five minutes. You’ll submit the same request twice, watch it run once, and read the shared result. You need the taskfused and taskfused-worker commands from the download page.
1. Submit Some Work
Every operation has a name made of four parts: a namespace, a handler, the handler’s version and a key. The example worker has one handler, echo, which hands back its input after a short pause.
taskfused submit -db demo.db -namespace demo -handler echo -version v1 \
-key report-42 -input 'hello' -join
The reply is JSON. Abridged to the parts that matter here:
{"joined": false, "operation": {"id": "op_dfb8e36d419610f064ae4e2ddf8e4914", "state": "queued", ...}}
demo.db didn’t exist, so TaskFused created it. The operation is saved and waiting for a worker.
2. Submit It Again
Run exactly the same command:
{"joined": true, "operation": {"id": "op_dfb8e36d419610f064ae4e2ddf8e4914", "state": "queued", ...}}
Same ID, and joined is now true. No second operation was created. -join says you’re happy to share existing work; without it, TaskFused tells you the operation already exists. If you change the input but keep the key, it refuses with a conflict, because two different jobs must never share a result.
3. Run It
In a second terminal, start the example worker:
taskfused-worker -db demo.db
It prints one line per attempt it runs:
operation=op_dfb8e36d419610f064ae4e2ddf8e4914 attempt=at_88a022b7dd8cb80faba0deae72835e32 number=1 token=1
One attempt, for two requests.
4. Get the Result
Back in the first terminal:
taskfused wait -db demo.db -namespace demo -id op_dfb8e36d419610f064ae4e2ddf8e4914
{"id": "op_dfb8e36d419610f064ae4e2ddf8e4914", "state": "succeeded", "attempt_count": 1,
"result": "aGVsbG8=", ...}
The result is base64, so any bytes fit; aGVsbG8= is hello. Anyone who asks for report-42 from now on gets this stored result straight away, with no new run.
wait stops waiting after 30 seconds by default. Giving up on a wait never cancels the work, and other waiters carry on. To stop the work itself, use taskfused cancel.
5. Watch a Crash
Start the worker with a long job, taskfused-worker -db demo.db -delay 20s, submit a new key, and stop the worker while it runs, with Ctrl+C or by killing the process. Either way it leaves the job unfinished. Start a worker again. Once the old lease has run out, three seconds for the example worker, the new one takes the job over:
taskfused attempts -db demo.db -namespace demo -id op_...
shows the first attempt expired and a second one with a higher token, under the same operation ID. If the first worker came back to life and tried to save its result, the higher token would make TaskFused turn it away.
6. Look at It in a Browser
taskfused serve -db demo.db
Open http://127.0.0.1:8080/ and enter the namespace demo and an operation ID. The page shows the operation’s state, whether its result is there and how big it is, and its first 50 changes. The same server answers JSON on /api/namespaces/demo/...; the reference lists the routes.
7. Use It From Go
The worker and the submitter can be one program or several sharing the file:
store, err := taskfused.Open(ctx, "app.db")
if err != nil {
return err
}
defer store.Close()
worker, err := taskfused.NewWorker(store, taskfused.WorkerOptions{
Namespace: "account-a",
Concurrency: 4,
LeaseDuration: 30 * time.Second,
Handlers: []taskfused.Registration{{
Name: "report", Version: "v1",
Handle: func(ctx context.Context, claim taskfused.Claim) ([]byte, error) {
// claim.Operation.ID is a good idempotency key for outside effects.
return buildReport(ctx, claim.Operation.Input)
},
}},
})
if err != nil {
return err
}
go worker.Run(ctx)
sub, err := store.Submit(ctx, taskfused.Request{
Namespace: "account-a", Handler: "report", Version: "v1",
Key: "october-2026", Input: []byte(`{"month":"2026-10"}`),
JoinExisting: true,
})
if err != nil {
return err
}
done, err := store.Wait(ctx, "account-a", sub.Operation.ID)
done.State says whether it succeeded, failed or was canceled, and done.Result holds the bytes. Install with go get github.com/taskfused/taskfused@latest; it needs CGO and a C compiler.
Next
- Reference: every command, the HTTP routes and the limits.
- How TaskFused was tested.
- The full contract, for the exact rules.