wallet_helper.api module
FastAPI surface: a centralized dedup server (optional [api] extra).
Many clients (processes, hosts, containers) point at one wallet-helper server so the same heavy call is never run twice, even when two identical calls start at almost the same time. The server holds one shared ledger and hands out a lease: the first caller of a key runs the work, everyone else waits and gets that same result when it lands.
Every endpoint accepts either a ready-made key or a namespace plus a
payload (the server hashes it), so both wallet_helper.remote.RemoteLedger
(which sends keys) and a hand-written client (which sends inputs) work.
Protocol (claim, run, submit)
POST /claim. The reply ishit(already computed, useresult),leased(you are the leader, run the work thenPOST /submit), orpending(someone else is running it, wait and claim again).The leader runs the work, then
POST /submitwith the result. On failure it callsPOST /releaseso a waiter can take over. For a long job it callsPOST /extendto keep the lease alive.Followers either re-claim, or call
GET /result/{key}?wait=SECONDSwhich blocks until the result is ready.
There is no endpoint that runs your code: the work stays in your process.
Run it
uvicorn wallet_helper.api:app then talk to it over HTTP (docs at /docs).
- class wallet_helper.api.ClaimRequest(*, key=None, namespace=None, payload=None, token=None, lease_seconds=300.0)[source]
Bases:
RefA claim, with how long the lease is honoured before it can be stolen.
- Parameters:
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class wallet_helper.api.ClearRequest(*, namespace=None)[source]
Bases:
BaseModelA request to clear the store, all of it or one namespace.
- Parameters:
namespace (str | None)
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class wallet_helper.api.EvictRequest(*, max_entries=None, older_than=None)[source]
Bases:
BaseModelA request to prune the store by age and/or a size cap.
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class wallet_helper.api.Ref(*, key=None, namespace=None, payload=None, token=None)[source]
Bases:
BaseModelA reference to a call: a ready
key, or anamespacepluspayload.tokenis the fencing token from aclaim; pass it tosubmit,release, andextendso only the current leader can finish a lease.- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class wallet_helper.api.SubmitRequest(*, key=None, namespace=None, payload=None, token=None, result=None, ttl=None)[source]
Bases:
RefA leader submitting the result it computed, with an optional freshness ttl.
- Parameters:
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- result: Any
- wallet_helper.api.create_app(ledger=None)[source]
Build the app around a SQLite ledger (its atomic lease backs the dedup).
- Parameters:
ledger (wallet_helper.sqlite_ledger.SqliteLedger, optional) – The shared store. Defaults to a
SqliteLedgerat the standard location. A SQLite backend is required because the claim lease relies on its atomic transactions.- Returns:
The configured application.
- Return type:
fastapi.FastAPI