livepeer / livepeer/livepeer-python-gateway

Make the SDK legible: usage docs, shipped types, and discovery ergonomics

Open
#58 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
1
Forks
7
PR merge metrics
No merged PRs in 30d

Description

Built seven examples against `ja/live-runner` in [runner-app-examples](https://github.com/livepeer/runner-app-examples) and repeatedly had to read go-livepeer's Go structs, or the SDK source, to answer questions the SDK could have answered itself. Collecting the gaps.

## Docs and discoverability

- **`README` has no `.md` extension**, so GitHub renders it as plain text. Its 142 lines are maintainer instructions (protobuf generation, pytest, coverage) — there is **no usage documentation**. Someone landing here learns how to rebuild the protos, not how to reserve a session. Suggest: rename to `README.md`, lead with a quickstart for both shapes (`runner_selector` → `call_runner`, and `reserve_session` → call → `stop_runner_session`), move maintainer material to `CONTRIBUTING.md`.
- **No `py.typed`.** The package is thoroughly annotated, but without the marker every consumer's type checker treats it as untyped. One empty file plus a packaging entry turns all existing annotations into working documentation.
- **Module-level docstrings.** The first question is "which module do I import from" — `selection` vs `live_runner` vs `discovery` is not self-evident, and per-function prose does not answer it.
- **`examples/` mixes two eras.** `write_control.py`, `subscribe_events.py`, `start_job.py`, and `in_out_composite.py` are `lv2v`; `echo/`, `ping-pong/`, and `text/` are live runner. Pattern-matching from that directory can produce `start_lv2v(StartJobRequest(...))` in the belief it is the live-runner API. Worth labelling or separating.
- Linking runner-app-examples from the README would help — it is already the de-facto usage documentation, verified end to end.

## Discovery ergonomics

- **`LiveRunnerInstance` types a minority of what discovery publishes.** `url`, `app`, `mode`, and `price_info` are typed; `gpu`, `metadata`, `version`, `capacity`, `capacity_used`, and `capacity_available` are reachable only through `raw`, despite go-livepeer publishing all of them (`ai/runner/live_runner.go:189-199`). Suggest typing every field the discovery schema defines, keeping `raw` for anything newer than the installed SDK. A `metadata_json()` helper would also stop every caller reimplementing the same parse — but the field should stay `str`, since the protocol guarantees an opaque string.
- **Filtering the candidate list costs you the failover.** `cursor.candidates` is a tuple copy, so narrowing it means abandoning `cursor.next()` and hand-rolling the retry loop, losing `cursor.rejections` with it. Something like `cursor.filter(pred)` / `cursor.order_by(key)` that narrows in place would keep one code path. Discovery filters are exact set membership (`discovery.py:303`), so any selection on capacity, GPU, or metadata is client-side today.
- **Candidates are unordered.** They arrive in discovery order, so `candidates[0]` — which every example uses — is arbitrary rather than cheapest or least loaded. Worth deciding whether a default ordering belongs in the SDK, since it affects how work spreads across orchestrators.

## Runtime state

- **No public setter for `status` or `capacity`, and no way to force an immediate heartbeat.** Both exist privately (`registration._status`, `registration._send_heartbeat()`). They are needed for the one workaround available to an app whose registrations share a GPU (see [go-livepeer#4015](https://github.com/livepeer/go-livepeer/issues/4015)): flip every registration out of `ready` together when the hardware is saturated, and beat immediately rather than waiting out the interval. An example should not have to reach into private attributes to do that.

Happy to take any of these as PRs.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by choosing one scoped gap from the README, packaging and py.typed work, discovery.py, selection, live_runner, or registration. Read the relevant entry point and existing pytest coverage first; done means the selected SDK behavior or documentation is implemented without relying on private attributes, with tests or examples updated to demonstrate it.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, developer-experience, documentation
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.