Skip to content

feat(examples): switch hello-world and tiles to single-shot - #39

Merged
rickstaa merged 6 commits into
mainfrom
rs/single-shot-hello-world-tiles
Jul 29, 2026
Merged

feat(examples): switch hello-world and tiles to single-shot#39
rickstaa merged 6 commits into
mainfrom
rs/single-shot-hello-world-tiles

Conversation

@rickstaa

@rickstaa rickstaa commented Jul 28, 2026

Copy link
Copy Markdown
Member

What

Switches the two request/response examples to their natural mode: hello-world and tiles now register mode="single-shot" with unit="fixed". go-livepeer v0.9.0 (already pinned by the examples) ships fixed pricing (livepeer/go-livepeer#3999) and single-shot payments (livepeer/go-livepeer#4000), so the "stays persistent until single-shot payment lands" stopgap is no longer needed.

Changes

  • Runners: mode="single-shot" plus unit="fixed"; --price is USD per call (hello-world) or per tile (tiles). The orchestrator reserves a session per call and releases it when the response returns.
  • Clients: reserve_session / call_runner / stop_runner_session collapses to runner_selector plus call_runner, which answers the 402 payment challenge inline: one fixed payment, no payment loop, no leaked sessions if a client crashes mid-call.
  • tiles capacity showcase preserved: each in-flight call holds a capacity slot; a full runner replies HTTP 503 and the client retries with the existing jittered backoff (--reserve-timeout renamed to --slot-timeout).
  • Docs: per-example READMEs, .env.examples, compose comments, and the root README (examples table, runner modes, mode-specific calling flows) updated. The price cap note now attributes the ~0.00019 USD ceiling to the signer's 100-tickets-per-payment limit and the demo orchestrator's -ticketEV=1e9. Also fixes stale claims that live runners are not in mainline go-livepeer (they ship in v0.9.0; only the Python SDK still comes from ja/live-runner).

Verification (offchain, livepeer/go-livepeer:v0.9.0)

  • hello-world: discovery advertises "mode": "single-shot" with the proxied /apps/{runner_id}/app URL; the client prints {'message': 'Hello, livepeer!'}.
  • tiles: CAPACITY=1 serializes behind 503 retries (9 tiles in 15.1s); CAPACITY=9 runs them in parallel (4.4s); byte-identical tiles-out.png both ways.
  • Paid path not exercised locally (needs funded wallets); it uses the same reservePaidLiveRunnerSession flow validated for fixed pricing in feat(tiles): showcase fixed pricing on go-livepeer v0.9.0 #36.

Refs #5. vllm intentionally stays persistent: per-token billing belongs to the gateway/signer layer.

go-livepeer v0.9.0 ships single-shot payments (go-livepeer#4000) on top
of fixed pricing (go-livepeer#3999), so the request/response examples no
longer need the persistent-mode stopgap. hello-world and tiles now
register mode="single-shot" with unit="fixed": the orchestrator reserves
a session per call and releases it on return, and the client pays the
402 challenge inline via runner_selector + call_runner — no
reserve/stop, no payment loop. The tiles capacity showcase survives
unchanged: in-flight calls hold capacity slots and a full runner refuses
with 503, which the client waits out with backoff.

Refs #5 (vllm intentionally stays persistent: per-token billing is
brokerage for the gateway/signer layer).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TNptCFhk6SHnioSgpSPVMu
Copilot AI review requested due to automatic review settings July 28, 2026 19:40

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the hello-world and tiles example apps to use Live Runner single-shot mode with fixed pricing, removing the prior persistent-mode stopgap and simplifying client call flows to no longer manage runner sessions.

Changes:

  • Switch both runners to mode="single-shot" and unit="fixed"; update pricing language to “USD per call / per tile”.
  • Update both clients from reserve_session → call_runner → stop_runner_session to runner_selector → call_runner, with capacity/backoff handled at the call level (tiles).
  • Refresh example and root documentation (READMEs, .env.examples, compose comments) to match the single-shot + fixed-pricing behavior.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tiles/runner.py Registers tiles runner as single-shot and updates fixed-price semantics to “per tile”.
tiles/README.md Updates tiles example docs to describe single-shot calling and capacity behavior via 503 retries.
tiles/compose.onchain.yml Updates on-chain compose comments to reflect per-tile single-shot fixed pricing.
tiles/client.py Replaces session lifecycle with runner_selector → call_runner and adds retry behavior around 503 capacity refusals.
tiles/.env.example Updates pricing documentation to “billed once per tile/call” for fixed pricing.
README.md Updates the repo-wide examples table, runner mode explanations, and calling flows for single-shot vs persistent.
hello-world/runner.py Registers hello-world runner as single-shot with fixed pricing billed once per call.
hello-world/README.md Updates hello-world docs to describe the single-shot discovery+call flow and inline payment challenge handling.
hello-world/compose.onchain.yml Adds fixed-pricing guidance comments for on-chain runs.
hello-world/client.py Simplifies the client to runner_selector → call_runner (no reserve/stop session).
hello-world/.env.example Updates on-chain pricing guidance for fixed pricing billed once per call.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

The module docstrings already explain the paid path; keep the grep
marker bare.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TNptCFhk6SHnioSgpSPVMu
Copilot AI review requested due to automatic review settings July 29, 2026 08:09
rickstaa and others added 2 commits July 29, 2026 10:12
Compose files point at .env.example, which now attributes the cap to
its actual sources: the signer's 100-tickets-per-payment limit and the
demo orchestrator's -ticketEV=1e9.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TNptCFhk6SHnioSgpSPVMu
Drop the go-livepeer#4000 reference and the redundant billing-model
prose; say what each knob does in one line.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TNptCFhk6SHnioSgpSPVMu

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

hello-world/client.py:51

  • cursor.candidates[0] can raise IndexError if discovery returns a cursor with no candidates, which would bypass the LivepeerGatewayError handling and produce an unhelpful crash. Guard for the empty-candidates case and raise a user-facing LivepeerGatewayError instead.
        cursor = await runner_selector(  # Livepeer: 1
            discovery_url=args.discovery, app=APP_ID
        )
        runner = cursor.candidates[0]
        log.info("app_url=%s", runner.url)

tiles/client.py:114

  • runner = cursor.candidates[0] can raise IndexError if discovery returns an empty candidate list. Treat this as a retryable "no runner available" condition so tiles don't crash with an uncaught exception.
            cursor = await runner_selector(  # Livepeer: 1
                discovery_url=discovery_url, app=APP_ID
            )
            runner = cursor.candidates[0]
            return await call_runner(  # Livepeer: 2

Copilot AI review requested due to automatic review settings July 29, 2026 08:13
Single-shot session mechanics live in the READMEs; keep only the
price-unit one-liners the code cannot show.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TNptCFhk6SHnioSgpSPVMu

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (3)

tiles/client.py:127

  • This comment says anything but HTTP 503 is a real error, but the code also retries NoRunnerAvailableError/NoOrchestratorAvailableError (which are not 503). Either narrow the retry set or adjust the comment so it matches the actual behavior.
            # Anything but "insufficient capacity" (503) is a real error, not a
            # full runner.

tiles/client.py:135

  • The warning message implies this is always a capacity-slot issue, but this loop also retries on discovery/selection failures. Consider wording that doesn’t mislead when the root cause is e.g. an unreachable discovery URL.
                    "tile (%d,%d) no slot yet, retrying until --slot-timeout: %s",

tiles/client.py:105

  • The retry-loop comment is too narrow: this handler retries not only when the runner is at capacity (503) but also when discovery/selection fails (e.g. no orchestrator/runner available). Updating the comment helps future readers understand why these exceptions are treated as retryable.

This issue also appears in the following locations of the same file:

  • line 126
  • line 135
    # A full runner refuses the call with 503; wait for a slot instead of failing the
    # tile. Re-discover each attempt so a restarted runner is picked up.

Copilot AI review requested due to automatic review settings July 29, 2026 08:16

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

tiles docstring said one session per tile; the root README still claimed
live runners were not on go-livepeer main and drew only the persistent
client flow; run-without-docker sections pointed at the ja/live-runner
branch instead of the v0.9.0 release.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TNptCFhk6SHnioSgpSPVMu
Copilot AI review requested due to automatic review settings July 29, 2026 08:30

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

@rickstaa
rickstaa merged commit f62b781 into main Jul 29, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants