fix(#5021): keep boot model budget across restore paths
This commit is contained in:
1 parent
a18ddae930
commit
288cbb55bc
4 files changed
+46
-23
No files matched your search
+3
-1
@@ -2278,7 +2278,9 @@ window._applyTitlebarProfileVisibility=_applyTitlebarProfileVisibility;
|
|||||||
let consumed=false;
|
let consumed=false;
|
||||||
const readAttempted=(storage=sessionStorage)=>{
|
const readAttempted=(storage=sessionStorage)=>{
|
||||||
try{
|
try{
|
||||||
return storage&&storage.getItem?storage.getItem(markerKey)==='1':false;
|
const attempted=storage&&storage.getItem?storage.getItem(markerKey)==='1':false;
|
||||||
|
if(attempted) consumed=true;
|
||||||
|
return attempted;
|
||||||
}catch(_){
|
}catch(_){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-7
@@ -1294,14 +1294,18 @@ async function loadSession(sid){
|
|||||||
S._pendingSessionToolsets=null;
|
S._pendingSessionToolsets=null;
|
||||||
if(typeof populateModelDropdown==='function'){
|
if(typeof populateModelDropdown==='function'){
|
||||||
const modelRefreshSid=sid;
|
const modelRefreshSid=sid;
|
||||||
const modelRefreshPromise=Promise.resolve().then(()=>{
|
if(!S._bootReady&&typeof window!=='undefined'&&typeof window._startBootModelDropdown==='function'){
|
||||||
if(_loadingSessionId!==modelRefreshSid) return;
|
Promise.resolve().then(()=>{
|
||||||
if(!S._bootReady&&typeof window!=='undefined'&&typeof window._startBootModelDropdown==='function'){
|
if(_loadingSessionId!==modelRefreshSid) return;
|
||||||
return window._startBootModelDropdown();
|
return window._startBootModelDropdown();
|
||||||
}
|
}).catch(()=>{});
|
||||||
return populateModelDropdown({freshness:'session_visit'});
|
}else{
|
||||||
}).catch(()=>{});
|
const modelRefreshPromise=Promise.resolve().then(()=>{
|
||||||
if(typeof window!=='undefined') window._modelDropdownReady=modelRefreshPromise;
|
if(_loadingSessionId!==modelRefreshSid) return;
|
||||||
|
return populateModelDropdown({freshness:'session_visit'});
|
||||||
|
}).catch(()=>{});
|
||||||
|
if(typeof window!=='undefined') window._modelDropdownReady=modelRefreshPromise;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(typeof _hydrateTodosFromSession==='function') _hydrateTodosFromSession(S.session);
|
if(typeof _hydrateTodosFromSession==='function') _hydrateTodosFromSession(S.session);
|
||||||
S.session._modelResolutionDeferred=true;
|
S.session._modelResolutionDeferred=true;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ ROOT = Path(__file__).resolve().parent.parent
|
|||||||
BOOT_JS = ROOT / "static" / "boot.js"
|
BOOT_JS = ROOT / "static" / "boot.js"
|
||||||
UI_JS = ROOT / "static" / "ui.js"
|
UI_JS = ROOT / "static" / "ui.js"
|
||||||
NODE = shutil.which("node")
|
NODE = shutil.which("node")
|
||||||
|
BOOT_MARKER_KEY = "hermes-webui-active-profile-bootstrap-401"
|
||||||
|
|
||||||
|
|
||||||
pytestmark = pytest.mark.skipif(
|
pytestmark = pytest.mark.skipif(
|
||||||
@@ -436,18 +437,31 @@ def test_boot_model_401_does_not_reopen_redirect_after_active_profile_fallback(d
|
|||||||
|
|
||||||
|
|
||||||
def test_boot_model_401_consumes_budget_when_profile_load_succeeds(driver_path):
|
def test_boot_model_401_consumes_budget_when_profile_load_succeeds(driver_path):
|
||||||
payload = _run(
|
first = _run(
|
||||||
driver_path,
|
driver_path,
|
||||||
{
|
{
|
||||||
"kind": "boot-model-only",
|
"kind": "boot-model-only",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert payload["redirects"] == ["login?next=%2Fsession%2Fabc%3Fworkspace%3Dtest"]
|
second = _run(
|
||||||
assert payload["results"][0]["state"]["status"] == "resolved"
|
driver_path,
|
||||||
assert payload["jsonCalls"] == 0
|
{
|
||||||
assert payload["activeProvider"] is None
|
"kind": "boot-model-only",
|
||||||
assert payload["defaultModel"] is None
|
"initialStorage": first["storage"],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert first["redirects"] == ["login?next=%2Fsession%2Fabc%3Fworkspace%3Dtest"]
|
||||||
|
assert first["results"][0]["state"]["status"] == "resolved"
|
||||||
|
assert first["storage"] == {BOOT_MARKER_KEY: "1"}
|
||||||
|
assert first["jsonCalls"] == 0
|
||||||
|
assert first["activeProvider"] is None
|
||||||
|
assert first["defaultModel"] is None
|
||||||
|
assert second["redirects"] == []
|
||||||
|
assert second["results"][0]["state"]["status"] == "resolved"
|
||||||
|
assert second["storage"] == {}
|
||||||
|
assert second["jsonCalls"] == 0
|
||||||
|
|
||||||
|
|
||||||
def test_boot_model_success_still_stores_active_provider(driver_path):
|
def test_boot_model_success_still_stores_active_provider(driver_path):
|
||||||
|
|||||||
@@ -328,22 +328,25 @@ def test_load_session_schedules_async_session_visit_model_refresh_after_metadata
|
|||||||
body = _extract_function_body(_read_static("sessions.js"), "async function loadSession(")
|
body = _extract_function_body(_read_static("sessions.js"), "async function loadSession(")
|
||||||
|
|
||||||
assign_idx = body.index("S.session=data.session")
|
assign_idx = body.index("S.session=data.session")
|
||||||
promise_idx = body.index("const modelRefreshPromise=Promise.resolve().then(")
|
|
||||||
boot_guard_idx = body.index("if(!S._bootReady&&typeof window!=='undefined'&&typeof window._startBootModelDropdown==='function'){")
|
boot_guard_idx = body.index("if(!S._bootReady&&typeof window!=='undefined'&&typeof window._startBootModelDropdown==='function'){")
|
||||||
|
boot_promise_idx = body.index("Promise.resolve().then(()=>{", boot_guard_idx)
|
||||||
boot_refresh_idx = body.index("return window._startBootModelDropdown();")
|
boot_refresh_idx = body.index("return window._startBootModelDropdown();")
|
||||||
|
else_idx = body.index("}else{", boot_refresh_idx)
|
||||||
|
promise_idx = body.index("const modelRefreshPromise=Promise.resolve().then(", else_idx)
|
||||||
ready_idx = body.index("window._modelDropdownReady=modelRefreshPromise")
|
ready_idx = body.index("window._modelDropdownReady=modelRefreshPromise")
|
||||||
refresh_idx = body.index("populateModelDropdown({freshness:'session_visit'})")
|
refresh_idx = body.index("populateModelDropdown({freshness:'session_visit'})")
|
||||||
stale_guard_idx = body.index("_loadingSessionId!==modelRefreshSid")
|
stale_guard_idx = body.index("_loadingSessionId!==modelRefreshSid")
|
||||||
|
|
||||||
assert assign_idx < promise_idx < boot_guard_idx < boot_refresh_idx < refresh_idx < ready_idx
|
assert assign_idx < boot_guard_idx < boot_promise_idx < boot_refresh_idx < else_idx < promise_idx < refresh_idx < ready_idx
|
||||||
assert promise_idx < stale_guard_idx < boot_guard_idx
|
assert boot_promise_idx < stale_guard_idx < boot_refresh_idx
|
||||||
|
assert promise_idx < body.index("_loadingSessionId!==modelRefreshSid", promise_idx) < refresh_idx
|
||||||
|
|
||||||
|
|
||||||
def test_boot_model_dropdown_reuses_inflight_session_visit_refresh():
|
def test_boot_model_dropdown_clears_cached_ready_on_401():
|
||||||
body = _extract_function_body(_read_static("boot.js"), "const _startBootModelDropdown=()=>")
|
body = _extract_function_body(_read_static("boot.js"), "const _redirectBootModelDropdownIfUnauth=(res)=>")
|
||||||
|
|
||||||
ready_idx = body.index("const ready=window._modelDropdownReady;")
|
status_idx = body.index("if(!res||res.status!==401) return false;")
|
||||||
reuse_idx = body.index("if(ready&&typeof ready.then==='function') return ready;")
|
clear_idx = body.index("window._modelDropdownReady=null;")
|
||||||
hydrate_idx = body.index("const next=_hydrateModelDropdown({redirectIfUnauth:_redirectBootModelDropdownIfUnauth});")
|
consumed_idx = body.index("if(_bootActiveProfileUnauthRedirectBudget.isConsumed()) return true;")
|
||||||
|
|
||||||
assert ready_idx < reuse_idx < hydrate_idx
|
assert status_idx < clear_idx < consumed_idx
|
||||||
Reference in new issue
Block a user