You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Any connection blip (Wi-Fi change, laptop sleep, phone backgrounded) or a backend recycle makes the Geppetto browser reload the page, losing colours, visibility, slice position and layout. Users read this as "VFB is buggy". The socket is also the transport for all bulk data (term info, query results, OBJ/SWC), which is where the size caps and timeouts we keep tuning come from.
Where the reloads come from (geppetto-client VFBv2.3.8.9, geppetto-vfb v2.2.9.8)
Retry budget is seconds, not minutes.MessageSocket.js retries at a fixed 5 s with reconnectionLimit: 10, but each abnormal close spends two attempts (onclose line 217 and reconnect() line 281), so a drop gets ~5 retries over ~25 s and no backoff. A closed lid exhausts it.
VFBMain reloads immediately, so the 10 s dialog from #1728 never shows.components/VFBMain.js:2112–2144 listens for Websocket_disconnected and calls window.location.reload() at line 2133 when attempts >= 2. reconnect() fires that event in the same tick as it opens the auto-dismissing dialog. Net effect of geppetto-vfb #1728: fewer dialogs, same number of reloads. Also an unconditional reload on close code 1002 (MessageSocket.js:211).
Resume only works on the same JVM inside 5 minutes.WebsocketConnection.java:259–270 looks the lost connection id up in ConnectionsManager (5 min / 32-entry retention, from #458). A redeploy, OOM restart or HAProxy redispatch to the other replica returns RECONNECTION_ERROR, which GEPPETTO.GlobalHandler.js:102–113 turns into a reload. The sticky cookie is supposed to route the resume back to the same replica, but containers are recycled often enough (scale: 2, recreateOnQuorum quorum:1, OOM restarts, redeploys) that the JVM holding the session is frequently gone. Resume on the old server can only ever be a fast path; the client must be able to start the session again on whichever server answers.
Nothing is queued during a reconnect.send() silently drops every command while RECONNECTING (MessageSocket.js:307–314); waitForConnection drops when readyState > 1; pending callbacks are never failed. Even a successful resume can leave a term half-loaded with the spinner stopped.
Bulk data over the socket. Term info (fetch_variable), query results (run_query, 66 MB page-0 messages per Geppetto frontend accumulates memory until containers OOM and recycle #458) and OBJ/SWC bodies (resolve_import_value, parsed from the model JSON at ThreeDEngine.js:1038) all travel over the socket. Hence MAX_OBJ_BYTES 150 MB + skeleton fallback, VFB_WS_SEND_TIMEOUT_MS 300 s and per-message gzip from #455 / geppetto-vfb #1714, and the decimation work in #456. Only the stack-viewer tiles, Solr, the pdb graph/circuit browsers and the ROI tree (already fetch to v3-cached) bypass it.
Reload recovers only the URL.id, i and q are restored (VFBMain.js:1816–1870); colours, visibility and layout are not.
A. Silent reconnect in v2. Backoff + long budget + retry on online/visibilitychange; queue and replay commands; treat a new server as the normal case: try reconnect once, and on RECONNECTION_ERROR rebuild the session in place on the new server (reload the project, re-request the ids the Redux store already holds, re-apply colour/visibility, replay the queue) with a non-blocking toast; reload only if the in-place rebuild fails. The store and URL already hold everything needed, so no server-side state has to survive. Days of work; caps remain, but which JVM serves the session stops mattering.
B. Bypass the socket for data in v2. Meshes/SWC by URL from the get_term_info image records, paged run_query over HTTP from v3-cached, term info rendered from VFBquery JSON in JS (port of the subset of VFBProcessTermInfoVFBqueryJson the panel uses). After that the socket carries nothing and can go. Weeks; it is a rewrite of v2's data layer in a codebase we intend to replace. Only the mesh half is cheap.
C. Single-page term view on the v3 data layer.virtual-fly-brain already has no socket: plain fetch for term info and queries, meshes by URL, ?id=/?i= state. Its layout is a v2 clone that users want replaced anyway (Codex-style scrolling term page, 3D as an optional widget — grant Figure 3). Keep its data layer, Redux slices, URL middleware and stack viewer; drop the flexlayout shell, the Flask wrapper (talk to v3-cached directly) and the MUI v4 code. Months, and a design pass first.
D. Deploy what is built and stop. v2.2.9.1 and v2.2.9.0 are released, not deployed. Removes the blocking dialog and the memory ratchet; does not reduce reloads (point 2).
Proposed way forward
Phase 0 (now): deploy geppetto-vfb v2.2.9.1 to production; pull a baseline of the existing GA websocket-disconnect events (disconnected, reconnect-attempt:N, reconnect-failed-reloading) for the preceding weeks so Phase 1 can be measured against it.
Phase 1 (1–2 weeks, geppetto-client VFBv2.3.8.10 + geppetto-vfb): option A. Acceptance: restart the backend under a loaded scene, and separately force the resume onto the other replica (drop the sticky cookie); in both cases the page recovers with ids, colours and visibility intact, no reload; reconnect-failed-reloading near zero against the baseline over a week of production traffic.
Phase 3 (design now, build after the grant decision): the single-page term view on the v3 data layer. Start with a design review of Figure 3 + Codex with Kit/Philipp/David, then a thin prototype rendering get_term_info for one class and one individual as a scrolling page with a lazy 3D widget. Decide then whether virtual-fly-brain is evolved in place or a new app imports its data layer.
Open decisions: whether Phase 2 happens at all; evolve vs restart for Phase 3; Neuroglancer vs the Geppetto canvas as the 3D widget; who owns the design pass.
The problem
Any connection blip (Wi-Fi change, laptop sleep, phone backgrounded) or a backend recycle makes the Geppetto browser reload the page, losing colours, visibility, slice position and layout. Users read this as "VFB is buggy". The socket is also the transport for all bulk data (term info, query results, OBJ/SWC), which is where the size caps and timeouts we keep tuning come from.
Where the reloads come from (geppetto-client
VFBv2.3.8.9, geppetto-vfb v2.2.9.8)MessageSocket.jsretries at a fixed 5 s withreconnectionLimit: 10, but each abnormal close spends two attempts (oncloseline 217 andreconnect()line 281), so a drop gets ~5 retries over ~25 s and no backoff. A closed lid exhausts it.components/VFBMain.js:2112–2144listens forWebsocket_disconnectedand callswindow.location.reload()at line 2133 whenattempts >= 2.reconnect()fires that event in the same tick as it opens the auto-dismissing dialog. Net effect of geppetto-vfb #1728: fewer dialogs, same number of reloads. Also an unconditional reload on close code 1002 (MessageSocket.js:211).WebsocketConnection.java:259–270looks the lost connection id up inConnectionsManager(5 min / 32-entry retention, from #458). A redeploy, OOM restart or HAProxy redispatch to the other replica returnsRECONNECTION_ERROR, whichGEPPETTO.GlobalHandler.js:102–113turns into a reload. Thestickycookie is supposed to route the resume back to the same replica, but containers are recycled often enough (scale: 2,recreateOnQuorum quorum:1, OOM restarts, redeploys) that the JVM holding the session is frequently gone. Resume on the old server can only ever be a fast path; the client must be able to start the session again on whichever server answers.send()silently drops every command whileRECONNECTING(MessageSocket.js:307–314);waitForConnectiondrops whenreadyState > 1; pending callbacks are never failed. Even a successful resume can leave a term half-loaded with the spinner stopped.fetch_variable), query results (run_query, 66 MB page-0 messages per Geppetto frontend accumulates memory until containers OOM and recycle #458) and OBJ/SWC bodies (resolve_import_value, parsed from the model JSON atThreeDEngine.js:1038) all travel over the socket. HenceMAX_OBJ_BYTES150 MB + skeleton fallback,VFB_WS_SEND_TIMEOUT_MS300 s and per-message gzip from #455 / geppetto-vfb #1714, and the decimation work in #456. Only the stack-viewer tiles, Solr, the pdb graph/circuit browsers and the ROI tree (alreadyfetchtov3-cached) bypass it.id,iandqare restored (VFBMain.js:1816–1870); colours, visibility and layout are not.Related: #328 (new TermInfo design), #403 (query caching), virtual-fly-brain #7 (v3 testing epic).
Options considered
online/visibilitychange; queue and replay commands; treat a new server as the normal case: tryreconnectonce, and onRECONNECTION_ERRORrebuild the session in place on the new server (reload the project, re-request the ids the Redux store already holds, re-apply colour/visibility, replay the queue) with a non-blocking toast; reload only if the in-place rebuild fails. The store and URL already hold everything needed, so no server-side state has to survive. Days of work; caps remain, but which JVM serves the session stops mattering.get_term_infoimage records, pagedrun_queryover HTTP fromv3-cached, term info rendered from VFBquery JSON in JS (port of the subset ofVFBProcessTermInfoVFBqueryJsonthe panel uses). After that the socket carries nothing and can go. Weeks; it is a rewrite of v2's data layer in a codebase we intend to replace. Only the mesh half is cheap.virtual-fly-brainalready has no socket: plainfetchfor term info and queries, meshes by URL,?id=/?i=state. Its layout is a v2 clone that users want replaced anyway (Codex-style scrolling term page, 3D as an optional widget — grant Figure 3). Keep its data layer, Redux slices, URL middleware and stack viewer; drop the flexlayout shell, the Flask wrapper (talk tov3-cacheddirectly) and the MUI v4 code. Months, and a design pass first.Proposed way forward
websocket-disconnectevents (disconnected,reconnect-attempt:N,reconnect-failed-reloading) for the preceding weeks so Phase 1 can be measured against it.VFBv2.3.8.10+ geppetto-vfb): option A. Acceptance: restart the backend under a loaded scene, and separately force the resume onto the other replica (drop the sticky cookie); in both cases the page recovers with ids, colours and visibility intact, no reload;reconnect-failed-reloadingnear zero against the baseline over a week of production traffic.get_term_infofor one class and one individual as a scrolling page with a lazy 3D widget. Decide then whethervirtual-fly-brainis evolved in place or a new app imports its data layer.Open decisions: whether Phase 2 happens at all; evolve vs restart for Phase 3; Neuroglancer vs the Geppetto canvas as the 3D widget; who owns the design pass.