Encapsulate live-runner session payments in a stateful session/client object
Assessment
This issue has not been assessed yet.
Description
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:
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 bystart_lv2v(start_payments=True)and cancelled byjob.aclose(). The consumer cannot forget it.- daydreamlive/scope
ja/runner(server/livepeer_client.py):LivepeerClientstarts an interval_payment_loopright after connect, gated onpayment_session is not None, and cancels it on teardown. This is effectivelyrun_session_paymentshand-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:
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(), alongsidestop_runner_session. - Keep
run_session_paymentsas 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
- One unified
LiveRunnerSessionobject that subsumesLv2vJob, or keep lv2v separate and only wrap the general live-runner path? The former removes the parallel implementations; the latter is the minimal change. - Cadence semantics to standardize on: lv2v pays per output segment (only while media flows);
run_session_paymentspays 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).
- Dominant language
- Python
- Stars
- 1
- Forks
- 7
- PR merge metrics
- No merged PRs in 30d
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from livepeer/livepeer-python-gateway
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
livepeer/livepeer-python-gateway#64 · 1 comment ·
-
Improvement
Difficulty 1/5 Under an hour Newbie friendliness 68/100
livepeer/livepeer-python-gateway#27 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 1/5 Under an hour Newbie friendliness 70/100
livepeer/livepeer-python-gateway#12 · 1 comment ·
-
Difficulty 4/5 3-5 days Newbie friendliness 76/100
livepeer/livepeer-python-gateway#62 · 3 comments ·
All issues in livepeer/livepeer-python-gateway
Similar issues
-
documentation help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
simonw/sqlite-utils#872 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100