perf: bound Today readiness latency (#441)
All checks were successful
CI / lint (pull_request) Successful in 49s
CI / build-release (pull_request) Successful in 5s
CI / release-candidate (pull_request) Has been skipped

This commit is contained in:
timmy 2026-08-10 01:33:55 +00:00
parent cd9f40a1c4
commit 79c8f1626b
9 changed files with 66 additions and 23 deletions

View File

@ -1,6 +1,6 @@
const BASE = new URL('./', self.location.href).pathname;
importScripts(BASE + 'static/background-issue-sync.js');
const CACHE = 'stackchain-dashboard-shell-v73';
const CACHE = 'stackchain-dashboard-shell-v74';
const OFFLINE_LEASE_URL = new URL(BASE + '__offline-session-lease', self.location.origin).href;
const OUTAGE_STATUSES = new Set([500, 502, 503, 504]);
const NAVIGATION_TIMEOUT_MS = self.__STACKCHAIN_NAVIGATION_TIMEOUT_MS || 4000;

View File

@ -32,15 +32,19 @@
const candidates = preferredIndex >= 0
? ordered.slice(preferredIndex).concat(ordered.slice(0, preferredIndex))
: [preferred].concat(ordered);
const states = [];
for (const item of candidates) states.push({ item, ...(await classify(item)) });
const targetState = { item:preferred, ...(await classify(preferred)) };
if (request !== generation) return 'superseded';
const targetState = states[0];
if (targetState.status === 'ready') {
pending = null;
onOpen(action, preferred);
return 'opened';
}
const fallbackStates = await Promise.all(candidates.slice(1).map(async item => ({
item,
...(await classify(item)),
})));
const states = [targetState, ...fallbackStates];
if (request !== generation) return 'superseded';
const nextReadyState = states.slice(1).find(state => state.status === 'ready');
pending = {
action,

View File

@ -347,5 +347,5 @@ async def test_dashboard_syncs_every_later_change_and_exposes_account_status():
def test_later_sync_ships_atomically_in_the_offline_shell():
source = (Path(__file__).parents[1] / "frontend" / "service-worker.js").read_text()
assert "stackchain-dashboard-shell-v73" in source
assert "stackchain-dashboard-shell-v74" in source
assert "BASE + 'static/later-sync.js'" in source

View File

@ -137,4 +137,4 @@ def test_markdown_work_bodies_are_mobile_safe_block_containers():
assert ".markdown-content { min-width:0; max-width:100%; overflow-wrap:anywhere;" in css
assert ".markdown-content pre { max-width:100%; overflow-x:auto;" in css
assert ".markdown-content a { min-height:44px;" in css
assert "stackchain-dashboard-shell-v73" in worker
assert "stackchain-dashboard-shell-v74" in worker

View File

@ -35,4 +35,4 @@ def test_offline_shell_contains_every_local_dashboard_runtime_asset():
shell_assets = set(re.findall(r"BASE \+ '([^']+)'", worker.split("async function sessionCsrf", 1)[0]))
assert local_assets <= shell_assets, f"Offline shell is missing: {sorted(local_assets - shell_assets)}"
assert "stackchain-dashboard-shell-v73" in worker
assert "stackchain-dashboard-shell-v74" in worker

View File

@ -232,6 +232,6 @@ async def test_plan_today_wires_cancel_back_and_success_through_overlay_history(
def test_plan_today_controller_is_available_in_the_offline_shell():
source = SERVICE_WORKER.read_text()
assert "stackchain-dashboard-shell-v73" in source
assert "stackchain-dashboard-shell-v74" in source
assert "BASE + 'static/plan-today.js'" in source
assert "BASE + 'static/plan-today-preview.js'" in source

View File

@ -122,7 +122,7 @@ async function dispatchNotificationClick(route) {{
def test_resumable_today_session_ships_in_a_new_offline_shell():
source = WORKER.read_text()
assert "stackchain-dashboard-shell-v73" in source
assert "stackchain-dashboard-shell-v74" in source
assert "BASE + 'static/my-work.js'" in source
assert "BASE + 'static/dashboard.js'" in source
assert "BASE + 'static/dashboard.css'" in source
@ -131,7 +131,7 @@ def test_resumable_today_session_ships_in_a_new_offline_shell():
def test_offline_review_next_ships_today_completion_atomically():
source = WORKER.read_text()
assert "stackchain-dashboard-shell-v73" in source
assert "stackchain-dashboard-shell-v74" in source
assert "BASE + 'static/today-completion.js'" in source
assert "BASE + 'static/dashboard.js'" in source
@ -139,7 +139,7 @@ def test_offline_review_next_ships_today_completion_atomically():
def test_duplicate_aware_capture_ships_in_a_new_offline_shell():
source = WORKER.read_text()
assert "stackchain-dashboard-shell-v73" in source
assert "stackchain-dashboard-shell-v74" in source
assert "BASE + 'static/create-issue-sheet.js'" in source
assert "BASE + 'static/dashboard.js'" in source
@ -147,14 +147,14 @@ def test_duplicate_aware_capture_ships_in_a_new_offline_shell():
def test_exact_later_picker_ships_atomically_in_a_new_offline_shell():
source = WORKER.read_text()
assert "stackchain-dashboard-shell-v73" in source
assert "stackchain-dashboard-shell-v74" in source
assert "BASE + 'static/later-picker.js'" in source
def test_navigation_deadline_ships_in_a_new_shell_cache():
source = WORKER.read_text()
assert "stackchain-dashboard-shell-v73" in source
assert "stackchain-dashboard-shell-v74" in source
assert "BASE + 'static/dashboard.css'" in source
assert "BASE + 'static/dashboard.js'" in source
assert "BASE + 'static/install-app.js'" in source
@ -163,21 +163,21 @@ def test_navigation_deadline_ships_in_a_new_shell_cache():
def test_today_convergence_ships_in_a_new_shell_cache():
source = WORKER.read_text()
assert "stackchain-dashboard-shell-v73" in source
assert "stackchain-dashboard-shell-v74" in source
assert "BASE + 'static/today-sync.js'" in source
def test_mobile_search_viewport_ships_in_a_new_offline_shell():
source = WORKER.read_text()
assert "stackchain-dashboard-shell-v73" in source
assert "stackchain-dashboard-shell-v74" in source
assert "BASE + 'static/mobile-search-viewport.js'" in source
def test_update_ownership_flow_ships_atomically_in_a_new_offline_shell():
source = WORKER.read_text()
assert "stackchain-dashboard-shell-v73" in source
assert "stackchain-dashboard-shell-v74" in source
assert "BASE + 'static/update-ownership.js'" in source
@ -358,7 +358,7 @@ def test_one_session_bound_csrf_proof_is_reused_for_a_background_drain():
def test_queue_today_ships_atomically_in_a_new_offline_shell():
source = WORKER.read_text()
assert "stackchain-dashboard-shell-v73" in source
assert "stackchain-dashboard-shell-v74" in source
assert "BASE + 'static/queue-today.js'" in source

View File

@ -18,23 +18,59 @@ def run_node(script):
).stdout
def test_readiness_opens_ready_target_without_showing_a_gate():
def test_readiness_opens_ready_target_without_inspecting_the_rest_of_the_queue():
script = f"""
const createTodayReadiness = require({json.dumps(str(READINESS))});
const calls = [];
const inspections = [];
const item = (number, kind='issue') => ({{kind, repository:'stackchain/dashboard', number, title:'Item ' + number}});
const readiness = createTodayReadiness({{
inspect: async candidate => ({{available:true, dependencies:[]}}),
inspect: async candidate => {{ inspections.push(candidate.number); return {{available:true, dependencies:[]}}; }},
onOpen: (action, candidate) => calls.push(['open', action, candidate.number]),
onGate: state => calls.push(['gate', state.status]),
}});
readiness.run('start', [item(1), item(2)]).then(result =>
process.stdout.write(JSON.stringify({{result, calls}}))
readiness.run('start', [item(1), item(2), item(3)]).then(result =>
process.stdout.write(JSON.stringify({{result, calls, inspections}}))
);
"""
assert json.loads(run_node(script)) == {
"result": "opened",
"calls": [["open", "start", 1]],
"inspections": [1],
}
def test_readiness_checks_fallbacks_concurrently_but_preserves_queue_order():
script = f"""
const createTodayReadiness = require({json.dumps(str(READINESS))});
const items = [1, 2, 3].map(number => ({{kind:'issue', repository:'r', number}}));
const starts = [];
const resolvers = {{}};
const readiness = createTodayReadiness({{
inspect: candidate => {{
starts.push(candidate.number);
if (candidate.number === 1) return Promise.resolve({{available:true, dependencies:[{{state:'open'}}]}});
return new Promise(resolve => {{ resolvers[candidate.number] = resolve; }});
}},
onOpen: () => undefined,
onGate: state => {{ globalThis.gated = state.nextReady.number; }},
}});
(async () => {{
const running = readiness.run('start', items);
await new Promise(resolve => setImmediate(resolve));
const startedTogether = starts.slice();
if (resolvers[3]) resolvers[3]({{available:true, dependencies:[]}});
resolvers[2]({{available:true, dependencies:[]}});
await new Promise(resolve => setImmediate(resolve));
if (!startedTogether.includes(3)) resolvers[3]({{available:true, dependencies:[]}});
const result = await running;
process.stdout.write(JSON.stringify({{result, startedTogether, gated:globalThis.gated}}));
}})();
"""
assert json.loads(run_node(script)) == {
"result": "gated",
"startedTogether": [1, 2, 3],
"gated": 2,
}
@ -135,7 +171,10 @@ async def test_dashboard_exposes_mobile_today_readiness_gate_and_runtime():
def test_readiness_runtime_is_available_in_offline_shell():
assert "BASE + 'static/today-readiness.js'" in SERVICE_WORKER.read_text()
service_worker = SERVICE_WORKER.read_text()
assert "const CACHE = 'stackchain-dashboard-shell-v74';" in service_worker
assert "BASE + 'static/today-readiness.js'" in service_worker
def test_mobile_readiness_gate_has_touch_safe_wrapping_actions():

View File

@ -86,7 +86,7 @@ sync.enqueue('add', 'issue:r:1:');
def test_inflight_today_drain_ships_in_a_new_offline_shell():
source = (Path(__file__).parents[1] / "frontend" / "service-worker.js").read_text()
assert "stackchain-dashboard-shell-v73" in source
assert "stackchain-dashboard-shell-v74" in source
assert "BASE + 'static/today-sync.js'" in source