Skip to content

obs-websocket: Keep Parallel batch results in request order - #1074

Merged
zackees merged 2 commits into
obs-rust:masterfrom
rdoupe:fix/813-ws-batch-order-2
Oct 16, 2026
Merged

zackees merged 2 commits into
obs-rust:masterfrom
rdoupe:fix/813-ws-batch-order-2

Conversation

@rdoupe

@rdoupe rdoupe commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

Fixes #813

What and why

obs-websocket now returns a Parallel request batch's results in request order, so each result carries its own request's requestType and requestId. Clients that match results by requestId, as the protocol documents, get the right data again.

  • A RequestBatch with executionType: 2 (Parallel) runs each request as its own thread-pool task. In plugins/obs-websocket/src/requesthandler/RequestBatchHandler.cpp each task did results.push_back(requestResult) (line 217) when it finished, so the vector came back in completion order. WebSocketServer_Protocol.cpp (lines 336-339) then labels results[i] with requests[i]'s requestType and requestId. With a slow request first (a full-size GetSourceScreenshot) and quick ones after it, every result went out under another request's label.
  • The fork fix, requesthandler: Keep Parallel batch results in request order obs-websocket#13 (requesthandler: Keep Parallel batch results in request order), gives the results vector one slot per request, has each task write its result at its request's index, and waits for a finished count instead of the vector's size. This PR moves the submodule to it.
  • Nothing that works today changes: Parallel batches were only right when the requests happened to finish in order, and the serial modes (SerialRealtime, SerialFrame) are untouched.
  • Reported upstream by wesbos in Bug: Parallel Batch Requests do not return correct order or requestId obsproject/obs-websocket#1317 (September 2025, open, no reply), with GetSourceScreenshot and GetSourceFilterList.

Reproduced in release v0.1.0-beta.20261014 (AppImage, headless: private Xvfb, private HOME, dbus-run-session, --multi), 1920x1080 canvas with one colour source, sending a batch of a full-size PNG GetSourceScreenshot, GetVersion, GetSceneList, GetStats and GetInputList 20 times per mode:

Build SerialRealtime (0) Parallel (2)
v0.1.0-beta.20261014 0 of 20 mislabelled 20 of 20 mislabelled (every entry)
Stock OBS 32.2.2 10 of 10 mislabelled
This branch, C libobs lane 0 of 20 0 of 20
This branch, Rust libobs lane 0 of 20 0 of 20

RED → GREEN

  • RED commit: 4e2eb8b test/cmocka: Add failing test for Parallel request batch result order, with the submodule at master's pin f9e2a95 (the fork before the fix). test_ws_batch_order builds the plugin's RequestBatchHandler.cpp (plus its Request, RequestBatchRequest, RequestResult and Compat sources) with RequestHandler stubbed: each request sleeps for a given delay and answers with its own requestType and a tag. Batches run on a real QThreadPool. 3 of 5 fail in both lanes: test_parallel_slow_first (the upstream batch shape: the screenshot's slot holds a quick request's result, e.g. "GetStats" != "GetSourceScreenshot"), test_parallel_reverse_finish (eight requests finishing in reverse order) and test_parallel_failure_keeps_slot (a failed request in the middle keeps its slot). test_parallel_empty and the control test_serial_realtime_order pass. Qt Core and nlohmann_json only, no libobs startup, no display; built where both are found, not on Windows (like the other test_ws_* tests).
  • GREEN: f031337 moves plugins/obs-websocket from f9e2a95 to 2542c6a9f (the merge of requesthandler: Keep Parallel batch results in request order obs-websocket#13; forward only). 5 of 5 with ENABLE_RUST_LIBOBS OFF and ON, also with DISPLAY unset; with the fix the result order no longer depends on timing. Full OBS build (frontend + obs-websocket) in both lanes. Full ctest -j8 (private Xvfb, system libobs-opengl masked, TMPDIR unset), rebased on master 673f76f: 261/262 in each lane. The one failure in both lanes is test_text_freetype2_bundled_font (from text-freetype2: Default to the bundled JetBrainsMono Nerd Font #1016, not touched here): on a machine with JetBrainsMono Nerd Font installed, fontconfig picks the system copy over the bundled file. clang-format, gersemi and ci/test_registration.py clean.

Checklist

  • Base is master
  • I claimed the issue, or no one else has an open PR for it
  • Characterization test (if the unit had none), then RED, then GREEN commits
  • (Optional) Local gate passed and the pushed head is stamped; otherwise PR CI runs the full suite
  • Warning or flag changes (-W..., ratchets): none
  • Intentional differences from C listed in the parity test header and rust/README.md (ports): not a port

AI note: Claude Code (Claude Opus 5.5) wrote the code, the test, the commit messages and this text under the submitter's direction, and ran the tests above on the submitter's machines.

🤖 Generated with Claude Code

rdoupe and others added 2 commits October 16, 2026 06:22
obs-websocket answers a RequestBatch with one result per request, and
the protocol layer labels results[i] with the requestType and requestId
of requests[i]. With executionType Parallel, each request runs as its
own thread-pool task and RequestBatchHandler appends its result when it
finishes, so the results come back in completion order. A batch with a
slow request first (a full-size GetSourceScreenshot) and fast ones after
it returns every result under another request's requestType and
requestId: the screenshot is labelled GetInputList, and so on (upstream
obsproject/obs-websocket#1317). Clients that match results by requestId,
as the protocol documents, get the wrong data. Serial batches are in
request order.

test_ws_batch_order builds the plugin's RequestBatchHandler.cpp with
RequestHandler stubbed: each request sleeps for its delay and answers
with its own requestType and tag. Three Parallel cases fail (a slow
request first, eight requests finishing in reverse order, a failed
request in the middle); an empty Parallel batch and a SerialRealtime
batch pass. Qt Core and nlohmann_json only, no libobs startup, no
display.

Refs obs-rust#813.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Moves the submodule to the fork fix "requesthandler: Keep Parallel
batch results in request order". RequestBatchHandler appended each
Parallel request's result when its thread-pool task finished, so the
protocol layer, which labels results[i] with requests[i]'s requestType
and requestId, attached most results to the wrong request (upstream
obsproject/obs-websocket#1317). Each task now writes its result at its
request's index, so Parallel results come back in request order, as
serial batches already do.

test_ws_batch_order passes 5 of 5.

Fixes obs-rust#813.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rdoupe
rdoupe requested a review from zackees as a code owner October 16, 2026 10:37
@zackees zackees added the ci-full Run every CI job on this PR, including the release-gating OBS app builds and Flatpak label Oct 16, 2026
@zackees
zackees enabled auto-merge October 16, 2026 10:39
@zackees
zackees added this pull request to the merge queue Oct 16, 2026
Merged via the queue into obs-rust:master with commit e863e0b Oct 16, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-full Run every CI job on this PR, including the release-gating OBS app builds and Flatpak

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: obs-websocket: a Parallel request batch returns each result under another request's requestType and requestId (upstream obs-websocket#1317)

2 participants