Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 69 additions & 11 deletions packages/host/app/services/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
isLinkableCollectionDocument,
resolveFileDefCodeRef,
X_BOXEL_JOB_PRIORITY_HEADER,
userInitiatedPriority,
Deferred,
delay,
mergeRelationships,
Expand Down Expand Up @@ -125,18 +126,75 @@ const realmEventsLogger = logger('realm:events');
const storeLogger = logger('store');

// Companion to `jobIdHeader()` (re-exported from
// `../lib/prerender-fetch-headers`). The prerender server's
// render-runner injects `__boxelJobPriority` onto the page before
// transitioning into the render route. Outside a prerender tab the
// global is undefined and we send no header — user / API callers
// leave the realm-server's lookup paths to fall back to priority 0
// as today.
// `../lib/prerender-fetch-headers`). Policy is two-state, gated by
// `__boxelDuringPrerender`, not by the presence of
// `__boxelJobPriority`:
//
// 1. Inside a prerender tab: forward the worker job's priority as-is.
// The render-runner injects `__boxelJobPriority` alongside
// `__boxelJobId` on each visit — a priority of 0 is meaningful
// (the originating job is system-initiated background indexing)
// and must be preserved, not upgraded. Sub-`prerenderModule`
// calls fired by `_federated-search` for a `lookupDefinition`
// cache miss inherit this priority so they don't outrun the
// parent. If `__boxelJobPriority` is missing here (older
// render-runner build, test fixture, etc.) treat as 0 — the
// safe default for prerender-context work.
//
// 2. Outside a prerender tab (the host SPA in a real user's browser):
// stamp `userInitiatedPriority` (10). User clicks driving a
// search are by definition user-initiated work and should outrank
// background indexing on the realm-server's PagePool. Without
// this, a user search whose definition lookup misses the modules
// cache would fire its sub-prerender at priority 0 and queue
// behind concurrent indexing fan-out.
//
// External (non-host) HTTP callers — anything that doesn't run in
// the host SPA's JS runtime — bypass this helper entirely and set
// `X-Boxel-Job-Priority` directly on their request if they care.
// This helper covers the host SPA only.
//
// Both globals are checked with `=== true` / strict-number rather
// than truthy coercion: `__boxelDuringPrerender` is typed as a
// boolean and a stray truthy string from a future code path
// shouldn't silently flip the policy from "user-priority" to
// "preserve 0."
// Pure resolver — exported for the unit test in
// `tests/integration/job-priority-header-test.ts`. See the comment
// above for the policy rationale; the function is the literal
// translation of that policy to numbers.
export function resolveOutboundJobPriority({
duringPrerender,
jobPriority,
}: {
duringPrerender: unknown;
jobPriority: unknown;
}): number {
let valid =
typeof jobPriority === 'number' &&
Number.isSafeInteger(jobPriority) &&
jobPriority >= 0
? jobPriority
: undefined;
if (duringPrerender === true) {
return valid ?? 0;
}
return valid ?? userInitiatedPriority;
}

function jobPriorityHeader(): Record<string, string> {
let p = (globalThis as unknown as { __boxelJobPriority?: number })
.__boxelJobPriority;
return typeof p === 'number' && Number.isSafeInteger(p) && p >= 0
? { [X_BOXEL_JOB_PRIORITY_HEADER]: String(p) }
: {};
let g = globalThis as unknown as {
__boxelDuringPrerender?: boolean;
__boxelJobPriority?: number;
};
return {
[X_BOXEL_JOB_PRIORITY_HEADER]: String(
resolveOutboundJobPriority({
duringPrerender: g.__boxelDuringPrerender,
jobPriority: g.__boxelJobPriority,
}),
),
};
}
const queryFieldSeedFromSearchSymbol = Symbol.for(
'cardstack-query-field-seed-from-search',
Expand Down
150 changes: 150 additions & 0 deletions packages/host/tests/unit/job-priority-header-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { module, test } from 'qunit';

import { userInitiatedPriority } from '@cardstack/runtime-common';

import { resolveOutboundJobPriority } from '@cardstack/host/services/store';

// Pure-resolver tests for the policy that decides what
// `X-Boxel-Job-Priority` value the host SPA stamps on outbound
// `_federated-search` calls. The function is module-internal logic
// extracted so its policy can be pinned without acceptance-test
// scaffolding.
//
// Two states gated by `__boxelDuringPrerender`:
// - inside prerender → forward (preserve 0)
// - outside prerender → user-initiated (10) by default
module('Unit | job-priority-header | resolveOutboundJobPriority', function () {
module('outside a prerender tab (user / API caller)', function () {
test('returns userInitiatedPriority when no global is set', function (assert) {
assert.strictEqual(
resolveOutboundJobPriority({
duringPrerender: undefined,
jobPriority: undefined,
}),
userInitiatedPriority,
);
});

test('returns userInitiatedPriority when __boxelDuringPrerender is false', function (assert) {
assert.strictEqual(
resolveOutboundJobPriority({
duringPrerender: false,
jobPriority: undefined,
}),
userInitiatedPriority,
);
});

test('honors an explicit override on __boxelJobPriority', function (assert) {
// Batch / scripting tooling running in the host SPA can set the
// global before issuing a fetch; outside a prerender tab we still
// forward what they set rather than overriding to user priority.
assert.strictEqual(
resolveOutboundJobPriority({
duringPrerender: undefined,
jobPriority: 3,
}),
3,
);
assert.strictEqual(
resolveOutboundJobPriority({
duringPrerender: false,
jobPriority: 0,
}),
0,
'override with 0 is preserved (not coerced to user priority)',
);
});

test('rejects a truthy but non-boolean __boxelDuringPrerender — uses strict === true', function (assert) {
// If `__boxelDuringPrerender` somehow ended up as a stringy
// truthy value (e.g. set by a future code path that didn't
// coerce), the policy must NOT silently flip to "forward 0";
// a real user-facing fetch would then queue behind background
// indexing. The check is `=== true` for exactly this reason.
assert.strictEqual(
resolveOutboundJobPriority({
duringPrerender: 'yes',
jobPriority: undefined,
}),
userInitiatedPriority,
);
assert.strictEqual(
resolveOutboundJobPriority({
duringPrerender: 1,
jobPriority: undefined,
}),
userInitiatedPriority,
);
});
});

module('inside a prerender tab', function () {
test('forwards an explicit __boxelJobPriority of 10', function (assert) {
assert.strictEqual(
resolveOutboundJobPriority({
duringPrerender: true,
jobPriority: 10,
}),
10,
);
});

test('forwards an explicit __boxelJobPriority of 0 — must NOT upgrade', function (assert) {
// System-initiated indexing has priority 0. A
// `_federated-search` fired by the card render must preserve
// that or its sub-prerenders would outrank the parent job.
assert.strictEqual(
resolveOutboundJobPriority({
duringPrerender: true,
jobPriority: 0,
}),
0,
);
});

test('defaults to 0 when __boxelJobPriority is missing (older render-runner / test fixture)', function (assert) {
assert.strictEqual(
resolveOutboundJobPriority({
duringPrerender: true,
jobPriority: undefined,
}),
0,
);
});

test('rejects malformed __boxelJobPriority values', function (assert) {
// Non-number / negative / non-integer values fall through to
// the default for the active branch.
assert.strictEqual(
resolveOutboundJobPriority({
duringPrerender: true,
jobPriority: -1,
}),
0,
);
assert.strictEqual(
resolveOutboundJobPriority({
duringPrerender: true,
jobPriority: 1.5,
}),
0,
);
assert.strictEqual(
resolveOutboundJobPriority({
duringPrerender: true,
jobPriority: '10',
}),
0,
);
assert.strictEqual(
resolveOutboundJobPriority({
duringPrerender: false,
jobPriority: -1,
}),
userInitiatedPriority,
'malformed value outside prerender → user-initiated default',
);
});
});
});
Loading