Repository navigation
Request batches and obs-batch - #9
Conversation
The client's sendBatch sends several requests in one RequestBatch message and returns each request's result; a failed request no longer fails its neighbours. obs-batch exposes it with the three OBS execution types, so a serial-frame batch can change two sources on the same frame and pause with Sleep. With OBS_MCP_CONFIRM_LIVE, obs-batch and obs-call-request now ask before sending a request that stops or toggles a stream or recording. obs-preflight reads every input's mute state and tracks in one batch, and obs-capture-window silences a capture in one. The fake OBS answers batches from the same scripts and responders, and records each batched request. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vjn8uBEa4mJshaQU3pFuqX
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 39b73313ec
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
|
|
||
| try { | ||
| const batch = await client.sendBatch(requests, { executionType: EXECUTION_TYPES[executionType], haltOnFailure }); |
There was a problem hiding this comment.
Disallow halt-on-failure in parallel mode
When executionType is parallel and haltOnFailure is true, forwarding both options cannot provide the promised “skip remaining requests” behavior: OBS starts the requests concurrently, so a later mutation may already execute before an earlier failure is observed. This is especially dangerous when callers treat the reported skipped count as proof that those mutations did not run; reject this combination or avoid claiming that omitted parallel results were skipped.
Useful? React with 👍 / 👎.
| /** Wall-clock time a batch spends in Sleep requests, assuming 30 fps for frames. */ | ||
| function batchSleepMillis(requests: readonly BatchRequest[]): number { | ||
| let total = 0; | ||
| for (const { requestType, requestData } of requests) { | ||
| if (requestType !== "Sleep" || !isObject(requestData)) continue; | ||
| if (typeof requestData.sleepMillis === "number") total += requestData.sleepMillis; | ||
| if (typeof requestData.sleepFrames === "number") total += (requestData.sleepFrames / 30) * 1000; |
There was a problem hiding this comment.
Base frame-sleep timeouts on OBS's actual frame rate
For a serial-frame batch, sleepFrames is measured at OBS's configured frame rate, but this timeout extension hard-codes 30 fps. At 24 fps, for example, a valid 10,000-frame sleep takes about 417 seconds while the client times out after about 343 seconds; OBS is not cancelled by that local timeout and can subsequently execute the remaining requests after the tool has reported failure. Derive the duration from OBS's video settings or otherwise use a conservative timeout for frame sleeps.
Useful? React with 👍 / 👎.
In obs-websocket 5.7, a parallel batch holds a thread-pool thread while it waits for its requests on the same pool (RequestBatchHandler.cpp), so a few concurrent parallel batches deadlock the WebSocket server until OBS restarts. Its results are also collected in completion order, so they came back matched to the wrong requests: live, GetInputSettings for a color source was reported as failing with "does not support audio". Every internal batch now runs serial-realtime, still one round trip. obs-batch no longer offers parallel. Each batched request carries its index as its ID and results are matched by ID. The live test now checks each result's position. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vjn8uBEa4mJshaQU3pFuqX
|
Update: parallel batches are removed. obs-websocket 5.7 returns parallel results in completion order (mismatched to their requests) and deadlocks its WebSocket server under concurrent parallel batches. See commit "Stop using parallel request batches". Every internal batch is now serial, and |
Stacked on #8.
What
client.sendBatch(requests, {executionType, haltOnFailure})sends oneRequestBatch(op 8) and returns a result per request. One failed request doesn't fail the rest. The timeout grows by the batch's ownSleeptime.obs-batchtool:serial-realtime,serial-frame(one request per rendered frame, so changes to two sources land on the same frame) orparallel, withSleepbetween requests.Sleepin parallel batches.OBS_MCP_CONFIRM_LIVE,obs-batchandobs-call-requestnow ask before sendingStopStream,ToggleStream,StopRecordorToggleRecord. Before this,obs-call-requestcould stop a stream without asking.obs-preflightreads every input's audio state in one batch (2×N requests became 1 message).obs-capture-windowsilences the capture in one batch.history().obs-batchhas nooutputSchema: a cancelled confirmation returns{message}, which would fail it. It still returnsstructuredContent, likeobs-call-request.Tests
npm run checkpasses: 125 unit, 11 e2e. Tool count is now 159; the contract snapshot is updated.Sleep6 frames). It ran withOBS_MCP_READ_OBS_CONFIG=1from Opt-in: use the WebSocket password OBS saved #8, so no password was exported.🤖 Generated with Claude Code
https://claude.ai/code/session_01Vjn8uBEa4mJshaQU3pFuqX