Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,26 @@ from runtime import App, Service

pricing = Service("pricing", max_slots=20)

@pricing.action("pricing.quote") # one executant, returns a value

@pricing.action("pricing.quote") # one executant, returns a value
async def quote(ctx, params):
return {"total": round(19.99 * params["qty"], 2)}

@pricing.event("order.placed") # every subscriber gets a copy

@pricing.event("order.placed") # every subscriber gets a copy
async def note_order(ctx, params):
print(f"order {params['id']}")

@pricing.every("500ms") # runs on a schedule

@pricing.every("500ms") # runs on a schedule
async def tick(ctx):
total = await ctx.call("pricing.quote", qty=3)
print(f"quote: {total}")


app = App(redis=os.environ.get("REDIS_URL", "redis://localhost:6379/0"))
app.include(pricing)
app.start() # blocking; logs the topology first
app.start() # blocking; logs the topology first
```

## The three verbs
Expand Down Expand Up @@ -94,20 +98,24 @@ API client — once at boot, and closes it on shutdown.
```python
from contextlib import asynccontextmanager


@asynccontextmanager
async def store(config):
db = await connect(config["dsn"])
try:
yield {"db": db} # → ctx.resources["db"]
yield {"db": db} # → ctx.resources["db"]
finally:
await db.close()


warehouse = Service("warehouse", max_slots=8, lifespan=store)


@warehouse.action("order.fulfil")
async def fulfil(ctx, params):
await ctx.resources["db"].fulfil(params["id"])


app.include(warehouse, config={"dsn": "postgres://…"})
```

Expand Down
14 changes: 9 additions & 5 deletions doc/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,20 @@ producers, the resources they share, the budget they compete for.
```python
catalog = Service("catalog", max_slots=1, lifespan=prestashop_clients)

@catalog.action("catalog.sync") # others call or dispatch this

@catalog.action("catalog.sync") # others call or dispatch this
async def sync(ctx, params): ...

@catalog.event("product.updated") # reacts to someone else's announcement

@catalog.event("product.updated") # reacts to someone else's announcement
async def on_update(ctx, params): ...

@catalog.every("5m") # scheduled

@catalog.every("5m") # scheduled
async def reconcile(ctx): ...

@catalog.once(delay="30s") # once, after boot

@catalog.once(delay="30s") # once, after boot
async def warm_cache(ctx): ...
```

Expand All @@ -43,7 +47,7 @@ in the handler body).
async def prestashop_clients(config):
client = await connect(config["dsn"])
try:
yield {"db": client} # → ctx.resources["db"]
yield {"db": client} # → ctx.resources["db"]
finally:
await client.close()
```
Expand Down
2 changes: 2 additions & 0 deletions doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ from runtime import App, Service

pricing = Service("pricing", max_slots=4)


@pricing.action("pricing.quote")
async def quote(ctx, params):
return {"total": 19.99 * params["qty"]}


app = App(redis="redis://localhost:6379/0")
app.include(pricing)
app.start()
Expand Down
22 changes: 12 additions & 10 deletions doc/messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ body it may be about to discard.

```python
class Envelope(BaseModel):
v: int = 3 # envelope version
id: str # message id
rid: str # request id — shared by one origin's descendants
lvl: int = 0 # call depth; gates max_depth
v: int = 3 # envelope version
id: str # message id
rid: str # request id — shared by one origin's descendants
lvl: int = 0 # call depth; gates max_depth
kind: Literal["call", "dispatch", "event"]
name: str
caller: str | None = None # the action/event whose handler sent this
reply: str | None = None # reply channel — set only for kind="call"
dl: int | None = None # absolute deadline, epoch MILLISECONDS
meta: dict = {} # user metadata; propagated
task: str | None = None # task id — set only for kind="dispatch"
caller: str | None = None # the action/event whose handler sent this
reply: str | None = None # reply channel — set only for kind="call"
dl: int | None = None # absolute deadline, epoch MILLISECONDS
meta: dict = {} # user metadata; propagated
task: str | None = None # task id — set only for kind="dispatch"
```

All times in this runtime are epoch **milliseconds**, with no exceptions. Mixing
Expand Down Expand Up @@ -116,8 +116,9 @@ class Quote(BaseModel):
sku: str
qty: int = 1


@pricing.action("pricing.quote", params=Quote)
async def quote(ctx, params): # params: Quote
async def quote(ctx, params): # params: Quote
return 19.99 * params.qty
```

Expand Down Expand Up @@ -152,6 +153,7 @@ Subclass for domain failures — the code is all it takes:
class OutOfStock(ActionError):
CODE = "OUT_OF_STOCK"


raise OutOfStock("no stock", data={"sku": sku})
```

Expand Down
4 changes: 2 additions & 2 deletions doc/operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
app = App(redis="redis://localhost:6379/0", namespace="staging")
app.include(catalog, config={"dsn": ...})
app.include(browser, enabled=settings.browser_enabled, max_slots=4)
app.start() # blocking; logs the resolved topology first
app.start() # blocking; logs the resolved topology first
```

`App.start()` logs what it resolved before running — services, budgets and any
Expand Down Expand Up @@ -57,7 +57,7 @@ from runtime import switches

await switches.disable(url, "catalog.sync", namespace="staging")
await switches.enable(url, "catalog.sync", namespace="staging")
await switches.status(url, namespace="staging") # only what was explicitly set
await switches.status(url, namespace="staging") # only what was explicitly set

# from inside a handler or producer
await ctx.set_enabled("catalog.sync", False)
Expand Down
Loading