Repository navigation
Add payment session callback for runner calls - #81
Conversation
Support sync and async on_payment_session callbacks in call_runner and expose LivePaymentSession.manifest_id for payment attribution. Invoke the callback for each new session. Validate segCreds when parsing signer responses and remove redundant caller checks. Cover callback ordering, failures, and cancellation.
eliteprox
left a comment
There was a problem hiding this comment.
Still reviewing the error handling and payment status reporting, but here is one nit
eliteprox
left a comment
There was a problem hiding this comment.
Overall changes lgtm and test fine. Added one more suggestion to call_runner.
For context, we're using the on_payment_session callback with manifest_id in builder-core to confirm if payment was sent for the job.
There was a problem hiding this comment.
🟢 Approval recommended
Static review identified no blocking issues in callback handling or signer validation, and the added tests cover the key failure paths; tests were not executed.
No open issues 🎉
What changed in this PR
Adds payment-session notifications to runner calls, allowing callers to attribute payments using the session’s manifest ID.
Changes:
- Supports synchronous and asynchronous callbacks for each new payment session, before dispatching the paid request.
- Exposes
LivePaymentSession.manifest_idand centralizessegCredsvalidation in signer-response parsing. - Adds tests for callback ordering, failures, cancellation, and manifest attribution.
| File | Description |
|---|---|
tests/test_live_runner.py |
Tests callback sequencing, error propagation, and cancellation. |
tests/test_live_payment_session.py |
Verifies the exposed manifest ID. |
src/livepeer_gateway/remote_signer.py |
Adds the manifest property and validates segment credentials centrally. |
src/livepeer_gateway/live_runner.py |
Implements payment-session callbacks and removes redundant validation. |
src/livepeer_gateway/__init__.py |
Exports the callback type. |
CHANGELOG.md |
Documents the new callback and manifest property. |
Review effort: Balanced
| if on_payment_session is not None: | ||
| result = on_payment_session(payment_session) | ||
| if inspect.isawaitable(result): | ||
| await result |
There was a problem hiding this comment.
Once await payment_session.get_payment() returns on line 851, the remote signer has already persisted the ticket and debited the caller's allocation, but call_runner only surfaces that payment_session through on_payment_session. This makes it hard to match job attempts that recorded cost by successfully signing, but failing on job start attempt, leading to regression in billing accuracy.
Would you be open to accumulating each signed payment_session into a list immediately after get_payment() succeeds (before awaiting on_payment_session) and attaching payment_sessions: tuple[LivePaymentSession, ...] = () (or manifest_ids: tuple[str, ...] = ()) to LiveRunnerCallResult, LiveRunnerCallStream, and LivepeerGatewayError? That way consumers recording a job attempt can read every signed manifest_id and whether payment was sent (bool(payment_sessions)) directly from the returned result or caught error, while keeping on_payment_session for callers that want to persist pre-dispatch state (more context in NE-Build-Track/livepeer-builder-core#33 (comment)). This way we're not relying on a callback hook for the manifest_id.
- On
LiveRunnerCallResult(lines 161–173) andLiveRunnerCallStream(lines 176–196),payment_sessionis cleared toNonewhenpayment_type == "fixed"(line 892 and line 939), and when multiple402challenges are signed across retries (as intest_reports_each_successful_session_before_dispatch), only the lastpayment_sessionandsession_idare retained on the return value. - When the paid runner request subsequently raises a non-
402LivepeerHTTPError(line 944), fails JSON decoding (lines 923–930), or exhausts challenge retries (line 951), the raisedLivepeerGatewayErrorcarries none of the sessions signed during the attempt.
There was a problem hiding this comment.
What regression in billing accuracy?
Is there a reason this needs to be built into the API? Can accomplish the same with
payment_sessions = []
await call_runner(
...,
on_payment_session=payment_sessions.append,
)
Support sync and async on_payment_session callbacks in call_runner and expose LivePaymentSession.manifest_id for payment attribution. Invoke the callback for each new session.
Validate segCreds when parsing signer responses and remove redundant caller checks. Cover callback ordering, failures, and cancellation.