Skip to content

fix(media): harden the media endpoints shipped in #14#15

Merged
VickyXAI merged 1 commit into
mainfrom
fix/media-endpoints-hardening
Jul 4, 2026
Merged

fix(media): harden the media endpoints shipped in #14#15
VickyXAI merged 1 commit into
mainfrom
fix/media-endpoints-hardening

Conversation

@VickyXAI

@VickyXAI VickyXAI commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

What

Fixes everything flagged in the post-merge review of #14 (media endpoints).

Correctness

  • ValueError → 400 on every media route via a shared _media_endpoint helper. Before, only the video route caught it — POST /v1/audio/generations with lyrics and the default instrumental: true returned a raw 500 instead of the SDK's clear 400 message.
  • Graceful 501 on old Solana SDKs: SolanaLLMClient.video/music/speech/sound_effect only exist in the blockrun-llm release carrying feat(solana): add video/music/speech/portrait/realface/price/rpc media support blockrun-llm#16. On older SDKs the adapter now raises a clear APIError(501) with an upgrade hint instead of an AttributeError 500. pyproject documents the version-floor bump owed when that release ships.

Capacity / abuse

  • Dedicated long-media pool: video (60–900s) and music (60–210s) run on their own 8-thread executor (BLOCKRUN_LONG_MEDIA_THREADS), and all media routes admit through their own semaphore (BLOCKRUN_MEDIA_MAX_CONCURRENT, default 20) instead of the global one — a burst of video jobs can no longer starve image/speech traffic or exhaust the global semaphore and brick /v1/chat/completions.
  • Server-side clamps: client-supplied budget_seconds/timeout are clamped to 900s (previously forwarded verbatim — one request body could pin a worker thread for a day). _run_media wraps every call in asyncio.wait_for, so the coroutine and its permit always release even if the SDK thread wedges (mapped to 504 with an honest note that the background job may still settle).

Observability

  • Media calls (including the pre-existing image route) now audit-log via log_proxy_call and surface the in-body settlement txHash as x-blockrun-settlement — the priciest per-call traffic was invisible to spend reconciliation.

Cleanups

  • asyncio.get_running_loop() in _run_media; VIDEO_PARAM_KEYS single-sourced in the adapter; the three media-client getters collapsed into one cached factory; /v1/responses added to the module endpoint catalog; n type-checked on the image route.

Tests

tests/test_proxy_media.py (parametrized negative-path suite across all 5 media routes: invalid JSON, missing field, 402 with gateway details, APIError clamping, ValueError→400, alias precedence, param filtering, settlement header) and tests/test_adapter_media.py (Base/Solana dispatch, timeout stripping, budget clamping, 501 guard, cache routing, 504 ceiling).

169 passed, 1 skipped (pre-existing skip); ruff clean on touched files.

Review follow-up fixing everything flagged on the media-endpoints PR:

- ValueError -> 400 on ALL media routes via a shared _media_endpoint
  helper (was video-only; music with lyrics + default instrumental=True
  500'd instead of returning the SDK's clear message)
- Solana media on a pre-#16 blockrun-llm now degrades to a clear 501
  (upgrade hint) instead of an AttributeError 500; pyproject notes the
  floor bump owed when the SDK release ships
- Long media (video 60-900s, music 60-210s) moved to a dedicated
  8-thread pool (BLOCKRUN_LONG_MEDIA_THREADS) and all media routes to
  their own semaphore (BLOCKRUN_MEDIA_MAX_CONCURRENT, default 20) so a
  video burst can no longer starve images or brick chat/messages
- Client-supplied budget_seconds/timeout clamped to the 900s server cap
  (was forwarded verbatim: one request body could pin a worker thread
  for a day); _run_media wraps every call in asyncio.wait_for so the
  coroutine + permit always release even if the SDK thread wedges (504)
- Media calls now audit-log via log_proxy_call and surface the in-body
  settlement txHash as x-blockrun-settlement (paid media traffic was
  invisible to spend reconciliation)
- asyncio.get_running_loop() in _run_media; VIDEO_PARAM_KEYS single-
  sourced in the adapter; media client getters collapsed to one cached
  factory; /v1/responses added to the module endpoint catalog
- tests: full negative-path suite for all 5 media routes (incl. the
  pre-existing image route) + adapter dispatch/clamp/guard/ceiling tests
@VickyXAI VickyXAI merged commit a27e1eb into main Jul 4, 2026
@VickyXAI VickyXAI deleted the fix/media-endpoints-hardening branch July 4, 2026 05:58
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.

1 participant