Repository navigation
fix: keep host dialog queue polls and workspace state quiet when a session is not loaded - #3734
Merged
bobleer merged 2 commits intoNov 5, 2026
Conversation
…ssion is not loaded Fixes GCWing#3729. Switching sessions/workspaces (especially local <-> remote) left passive observers polling manage_dialog_queue for a session that was never restored on the execution host, producing an ERROR log roughly every 10s ("Session is not loaded on the execution host"). Three changes: - DialogScheduler::execute_queue_request now lets read-only actions (List, Get) answer from the scheduler-owned receipts when the session is not loaded on this host, instead of failing every poll. Mutations (Submit, Cancel, Promote) still refuse user work for an unloaded session so nothing can silently disappear. - WorkspaceManager.setLoading/setError no longer emit state-quiet events; repeating an unchanged value made listeners observe workspace:loading followed by workspace:error in the same tick, which looked like a load that failed instantly. - The transport adapter classifies a structured host_unavailable answer from get_external_source_* polls as expected (debug-level) instead of logging each poll as ERROR; ApiClient reuses the same classifier. Verification: cargo test -p openbitfun-core (host_queue_ filters, 20 passed incl. new degradation test); web-ui vitest workspaceManager + tauri-adapter + HostPendingQueuePanel (49 passed); web-ui type-check; pnpm run fmt:rs. AI-assisted.
The ApiClient command-level log path now consumes
isExpectedTauriRequestError, but ApiClient.test.ts replaced the
'../adapters' module with a stub that did not export it, so every
rejected invoke in that suite crashed with a TypeError
("preserves structured transport error facts across command wrapping",
"keeps message-only transport errors parseable by domain adapters").
Keep the real classifier via vi.importActual while the transport
adapter itself stays mocked. CI confirmed this was the only real
failure: the macos-15 Rust/CLI jobs were cancelled mid-run (no logs,
BlobNotFound) and the Rust / CLI Validation aggregator only failed
because of that abandonment.
Verification: web-ui vitest ApiClient + tauri-adapter +
workspaceManager suites (63 passed).
AI-assisted.
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.
Fixes #3729.
Problem
When switching sessions/workspaces — especially across a local <-> remote workspace switch — passive host dialog queue observers (
observeHostQueue/useHostQueueTimeline) keep pollingmanage_dialog_queuefor a session that has not been restored on the execution host. The backend (DialogScheduler::execute_queue_request) rejects every read withNotFound: "Session is not loaded on the execution host", and the transport adapter logs each poll as ERROR (~every 10s; the issue trace shows 7 failures in 76 seconds).Two secondary symptoms in the same trace:
workspace:loadingimmediately followed byworkspace:error(with anullerror) in the same tick, so listeners observe an instant-failure pair even for clean switches.get_external_source_*against a host without the external compatibility service log ERROR on every poll even though callers degrade by design.Root cause
execute_queue_requestbails out withPortErrorKind::NotFoundbefore looking at the action wheneversession_manager.get_session(session)isNone. But the scheduler keeps its own queue receipts independent of session restoration, so read-only requests could be answered correctly.WorkspaceManager.setLoading/setErroremit unconditionally;setLoading(true)followed bysetError(null)emitsworkspace:errorwith an unchangednullerror.get_config.Changes
DialogScheduler::execute_queue_request(host_message_queue.rs): read-only actions (List,Get) now answer from the scheduler-owned receipts even when the session is not loaded on this execution host; mutations (Submit,Cancel,Promote) still refuse user work for an unloaded session so nothing can silently disappear.WorkspaceManager.setLoading/setError: state-quiet — skip the update and event when the value did not change.TauriTransportAdapter.isExpectedTauriRequestError: classify a structuredhost_unavailableanswer (ExternalSourceOperationErrorcontract, direct object or serialized insidemessage/error/details) fromget_external_source_*polls as expected (debug-level).ApiClientreuses the same classifier for the command-level log path.Testing
host_queue_reads_degrade_for_a_session_not_loaded_on_the_hostsubmits a message, evicts the loaded session, and assertsList/Getstill return the queued receipt with a stable epoch whileSubmit/Promotefail withNotFound. Fullhost_queue_filter: 20 passed.workspaceManagertests: a cleanscanWorkspaceInfoemitsworkspace:loadingbut noworkspace:error; a real failure still reportsworkspace:error. 35 passed.tauri-adaptertests: structuredhost_unavailableonget_external_source_*is expected; plain prose failures and mutation commands are not. 10 passed.HostPendingQueuePaneltests stay green (4 passed; 49 total across the three files).pnpm run type-check(web-ui) passes;pnpm run fmt:rsapplied.AI-assisted.