fix(media): harden the media endpoints shipped in #14#15
Merged
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Fixes everything flagged in the post-merge review of #14 (media endpoints).
Correctness
_media_endpointhelper. Before, only the video route caught it —POST /v1/audio/generationswithlyricsand the defaultinstrumental: truereturned a raw 500 instead of the SDK's clear 400 message.SolanaLLMClient.video/music/speech/sound_effectonly 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 clearAPIError(501)with an upgrade hint instead of anAttributeError500. pyproject documents the version-floor bump owed when that release ships.Capacity / abuse
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.budget_seconds/timeoutare clamped to 900s (previously forwarded verbatim — one request body could pin a worker thread for a day)._run_mediawraps every call inasyncio.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
log_proxy_calland surface the in-body settlementtxHashasx-blockrun-settlement— the priciest per-call traffic was invisible to spend reconciliation.Cleanups
asyncio.get_running_loop()in_run_media;VIDEO_PARAM_KEYSsingle-sourced in the adapter; the three media-client getters collapsed into one cached factory;/v1/responsesadded to the module endpoint catalog;ntype-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) andtests/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.