livepeer / livepeer/livepeer-python-gateway
Encapsulate live-runner session payments in a stateful session/client object
- Vorherrschende Sprache
- Python
- Sterne
- 1
- Forks
- 7
- PR-Merge-Kennzahlen
- Keine gemergten PRs in 30 T.
Beschreibung
## Problem
Streamed live-runner sessions (trickle / websocket) must keep paying for as long as the session is open, because the orchestrator meters the open session by wall-clock/segments and drops it when the balance runs dry. Today the SDK exposes this as a free function, `run_session_payments(session, interval=...)`, which the caller must drive manually:
```python
payment_task = asyncio.create_task(run_session_payments(session, interval=...))
...
finally:
payment_task.cancel()
await payment_task
```
`reserve_session` already mints and attaches the `payment_session` credential to the returned `LiveRunnerSession`, but `LiveRunnerSession` is a frozen dataclass with no lifecycle, so it cannot own the background task. That pushes task creation and (critically) cancellation onto every consumer. Forget the `finally` and you silently stop paying or leak a task. The echo example (`example-apps/echo/client.py`) shows the boilerplate this requires.
## Prior art (already in our codebase)
Two better-encapsulated patterns already exist and prove the approach:
- `lv2v.py`: `Lv2vJob.start_payment_sender()` runs a per-output-segment payment sender, auto-started by `start_lv2v(start_payments=True)` and cancelled by `job.aclose()`. The consumer cannot forget it.
- daydreamlive/scope `ja/runner` (`server/livepeer_client.py`): `LivepeerClient` starts an interval `_payment_loop` right after connect, gated on `payment_session is not None`, and cancels it on teardown. This is effectively `run_session_payments` hand-rolled inside a client object.
## Proposal
Make `reserve_session` return a stateful session/client that owns the payment lifecycle, so payments are automatic for on-chain sessions:
```python
async with await reserve_session(app=..., signer_url=signer) as session:
# publish/consume trickle; payments start and stop automatically
```
- Auto-start the payment loop when `payment_session is not None` (on-chain only; no-op offchain).
- Auto-cancel on context exit / `aclose()`, alongside `stop_runner_session`.
- Keep `run_session_payments` as the internal primitive.
- This mirrors `start_lv2v(start_payments=True)` + `job.aclose()`.
Payments still need a scope anchor (the session must know when the stream ended); the context manager / `aclose()` provides it. The object cannot infer that media stopped on its own.
## Open questions
1. One unified `LiveRunnerSession` object that subsumes `Lv2vJob`, or keep lv2v separate and only wrap the general live-runner path? The former removes the parallel implementations; the latter is the minimal change.
2. Cadence semantics to standardize on: lv2v pays per output segment (only while media flows); `run_session_payments` pays on a fixed interval (pays even when paused-but-open). These differ in over-payment behavior and should be decided before standardizing the interface.
## Context
Follow-up from the echo example migration and the `run_session_payments` work (branch `rs/live-runner-session-payments`). Related: gateway PR #25 (SSE streaming).
Beitragsleitfaden
Für dieses Repository ist kein Beitragsleitfaden indexiert
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Bewertung
Dieses Issue wurde noch nicht bewertet.