Persistence

11.1 Storage

A service SHOULD keep its state in an embedded SQLite database. A suggested set of tables:

Table Content
service_config Service identity and configuration.
clients Paired clients, token hashes and scopes.
models Model metadata and content digests.
responses Stored responses.
tasks Asynchronous tasks.
task_events The event log of each task, with sequence numbers.
idempotency_keys Idempotency keys, request digests and results.

Model files MUST stay outside the database. The database holds only metadata and content digests.

Table names and layouts are an implementation choice. What clients can observe, and what has to interoperate, is the behavior in the next two sections.

11.2 Rules

Whatever storage a service uses, it:

  • MUST persist a task before it returns 202 Accepted.
  • MUST update event sequence numbers and task status in the same transaction.
  • MUST make the cancel transition atomic, to avoid the race of a task that is cancelled and then completed.
  • SHOULD keep finished tasks and events for a configurable retention period.
  • MUST NOT delete unfinished tasks during log cleanup.
  • MUST, at startup, scan the leftover queued, loading, running and cancelling tasks, and apply the restart policy of each (section 7.5).

11.3 Recovery at startup

The table shows the state a leftover task is moved to, by its on_restart policy:

State found at startup fail retry resume
queued failed queued queued
loading failed queued queued
running failed queued running, continuing from the snapshot
cancelling cancelled cancelled cancelled

A task moved to failed gets the error code server_restarted and a response.failed event. A task moved to cancelled gets a response.cancelled event. The new state and its event are written in one transaction (section 11.2).