Ogha — durable execution for Python
Write ordinary Python. It survives crashes, restarts, deploys, and month-long waits. You split your code into steps (units of real work) and workflows (compositions of them); Ogha records every step and replays it faithfully after any failure, so a multi-step process finishes even if a worker dies halfway through. No retry loops, no idempotency tables, no state machines to hand-build.
Alpha. The API is stable in shape (nine methods); details may still change before 1.0.
import ogha
@ogha.step(retry=ogha.RetryPolicy(max_attempts=5), pivot=True)
def charge(order, amount):
return payments.charge(order["card"], amount) # runs once; recorded
@ogha.workflow
async def checkout(ctx, order):
total = await ctx.call(validate, order)
receipt = await ctx.call(charge, order, total) # survives a crash right here
return receipt
Install
pip install ogha # Python 3.10+
Run the engine
Ogha ships as one container that carries the engine, storage, and a live
dashboard. Pull it (public, no login) and open http://localhost:8080:
docker run -p 8080:8080 public.ecr.aws/h6s8i3h8/ogha:0.1.2-obf \
--storage=postgres --dsn="postgres://…" --auth-disabled
A ready-to-use docker compose (engine + PostgreSQL) is in the getting-started
guide below.
Upgrading an existing project is one script — it verifies PyPI, the docs' pinned compose, and the registry agree on the release, then swaps the engine (health-checked, auto-rollback) and optionally this SDK in the same move:
curl -fsSL -O https://coding2fun.in/ogha/update.sh && chmod +x update.sh
./update.sh --apply --sdk .venv/bin/python
The nine methods
Everything a workflow can do is nine methods on ctx:
| Method | What it does |
|---|---|
ctx.call(fn, …) |
run a step durably |
ctx.rpc(svc, m) |
durably call a service you can't import |
ctx.spawn(wf) |
start a child workflow — its own run |
ctx.join(*h, until=) |
wait on many: all / any / quorum(n) |
ctx.sleep(s) |
durable sleep, seconds to months |
ctx.wait(name) |
wait for the outside world (a webhook) |
ctx.gate(action) |
a fail-closed human approval |
ctx.emit(event) |
a milestone on the run's timeline |
ctx.cancel(h?) |
cooperatively cancel a child or the run |
Retries, timeouts, and saga compensation are declared on the step
(retry=, compensate_with=, pivot=), not scattered through the workflow.
A worker
A worker is a long-running process that executes your steps; importing your module registers them.
import ogha, myapp # importing registers @step / @workflow
client = ogha.connect("http://localhost:8080")
ogha.Worker(client, target="python://checkout", concurrency=8).run()
Submit work and return immediately:
run = client.submit("checkout", data, target="python://checkout")
Or use the synchronous caller convenience, which submits the same durable run and waits for its terminal record:
result = client.execute(
"checkout",
data,
target="python://checkout",
wait_timeout_s=30,
)
execute is not a third workflow mode. The workflow still runs on an
async_sticky or async_distributed worker, continues if this caller
disconnects, and is not canceled when wait_timeout_s expires.
Cron schedules
Run a workflow on a schedule the engine fires — occurrences keep firing and dedupe by their deterministic run id even while every worker is down:
@ogha.scheduled("0 6 * * *", context={"report": "kpi"}) # 5-field cron, UTC
@ogha.workflow(name="reports.daily")
async def reports_daily(ctx, param):
at = ogha.scheduled_time(ctx) # this occurrence, replay-safe
return await ctx.call(build_report, param["report"], at.isoformat())
The worker serving the workflow creates the schedule at startup. To change a
live schedule, edit the fields and bump revision= — the update is
revision-guarded, so a rolling deploy converges instead of flapping:
@ogha.scheduled("0 7 * * *", context={"report": "kpi"}, revision=2)
Programmatic management mirrors it: client.create_schedule(...),
client.update_schedule(..., revision=n), client.get_schedule(id),
client.list_schedules(), client.delete_schedule(id).
Documentation
- Overview & the nine methods: https://coding2fun.in/ogha
- Getting started (full example): https://coding2fun.in/ogha/python
License
Apache License 2.0. See LICENSE.
Metadata
Release files for ogha 0.1.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ogha-0.1.4.tar.gz | 53.3 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ogha-0.1.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 114.0 kB
Release files / ogha-0.1.4.tar.gz
| Download URL | ogha-0.1.4.tar.gz |
|---|---|
| Size | 53.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d215ce2934e509e950e5ac71b743ef453d3d80613e8352742c1b03229f349ed5
|
|
BLAKE2b-256 checksum How to use checksums |
4b5468ce9e0c10ba0ce11637a9b959b16bbb7d05b62f974a529d7644422c2730
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.25
|
Release files / ogha-0.1.4-py3-none-any.whl
| Download URL | ogha-0.1.4-py3-none-any.whl |
|---|---|
| Size | 60.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e3f6e31e3a21800b7fd8dd914c8a38a00acc199c857241aaf4ecc4f4ba867691
|
|
BLAKE2b-256 checksum How to use checksums |
92ac372ac5c5e983e84d998642ebb63688440fa2a6361ff1d11371f95e61eaa1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.25
|
Security for ogha 0.1.4
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.