@indigoai-us/hq-cloud 6.18.43-alpha.2 → 6.18.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bandwidth.d.ts +2 -3
- package/dist/bandwidth.d.ts.map +1 -1
- package/dist/bandwidth.js +16 -21
- package/dist/bandwidth.js.map +1 -1
- package/dist/bandwidth.test.js +0 -23
- package/dist/bandwidth.test.js.map +1 -1
- package/dist/bin/sync-runner-heap-telemetry.d.ts +0 -3
- package/dist/bin/sync-runner-heap-telemetry.d.ts.map +1 -1
- package/dist/bin/sync-runner-heap-telemetry.js +0 -3
- package/dist/bin/sync-runner-heap-telemetry.js.map +1 -1
- package/dist/bin/sync-runner-watch-loop.d.ts +2 -25
- package/dist/bin/sync-runner-watch-loop.d.ts.map +1 -1
- package/dist/bin/sync-runner-watch-loop.js +8 -82
- package/dist/bin/sync-runner-watch-loop.js.map +1 -1
- package/dist/bin/sync-runner-watch-routes.d.ts +1 -3
- package/dist/bin/sync-runner-watch-routes.d.ts.map +1 -1
- package/dist/bin/sync-runner-watch-routes.js +0 -13
- package/dist/bin/sync-runner-watch-routes.js.map +1 -1
- package/dist/bin/sync-runner.d.ts +1 -2
- package/dist/bin/sync-runner.d.ts.map +1 -1
- package/dist/bin/sync-runner.js.map +1 -1
- package/dist/bin/sync-runner.test.js +4 -297
- package/dist/bin/sync-runner.test.js.map +1 -1
- package/dist/cli/index.d.ts +3 -7
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +1 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/journal-snapshot-rows.d.ts +0 -2
- package/dist/journal-snapshot-rows.d.ts.map +1 -1
- package/dist/journal-snapshot-rows.js +0 -4
- package/dist/journal-snapshot-rows.js.map +1 -1
- package/dist/sync/parallel-sync-coordinator.d.ts +0 -7
- package/dist/sync/parallel-sync-coordinator.d.ts.map +1 -1
- package/dist/sync/parallel-sync-coordinator.js +0 -22
- package/dist/sync/parallel-sync-coordinator.js.map +1 -1
- package/dist/sync/parallel-sync-coordinator.test.js +0 -31
- package/dist/sync/parallel-sync-coordinator.test.js.map +1 -1
- package/dist/sync/realtime-telemetry.d.ts +2 -24
- package/dist/sync/realtime-telemetry.d.ts.map +1 -1
- package/dist/sync/realtime-telemetry.js +3 -47
- package/dist/sync/realtime-telemetry.js.map +1 -1
- package/dist/sync/realtime-telemetry.test.js +8 -47
- package/dist/sync/realtime-telemetry.test.js.map +1 -1
- package/package.json +1 -1
- package/dist/daemon.d.ts +0 -12
- package/dist/daemon.d.ts.map +0 -1
- package/dist/daemon.js +0 -90
- package/dist/daemon.js.map +0 -1
|
@@ -21,7 +21,7 @@ import { PresignObjectIO, S3SdkObjectIO } from "../object-io.js";
|
|
|
21
21
|
import { BandwidthGovernor, setBandwidthGovernorForTesting, } from "../bandwidth.js";
|
|
22
22
|
import { POST_SYNC_FLAG_KEYS, } from "./sync-runner-post-sync-flags.js";
|
|
23
23
|
import { FakeClock, TreeWatcher, createWatchPathFilter, } from "../watcher.js";
|
|
24
|
-
import { adaptivePollMs, advanceMonotonicDeadline, DEFAULT_EVENT_BATCH_LIMIT, DEFAULT_FAST_LANE_MAX_BYTES, DEFAULT_FAST_LANE_MAX_FILE_BYTES, DEFAULT_FAST_LANE_MAX_FILES, DEFAULT_FULL_RECONCILE_MS, EVENT_BATCH_LIMIT_ENV, FAST_LANE_MAX_BYTES_ENV, FAST_LANE_MAX_FILES_ENV, FULL_RECONCILE_MS_ENV, isFastLocalBatch, isLargeLocalUpload, localUploadSizeClass, isChoreLocalPush, isSessionLogsPushOnlyPath, isFastReceiverBatch, partitionLocalBatch, journalEntriesForWatcherDelete, resolveEventBatchLimit, resolveFullReconcileMs, resolveWatchPollMs, CHORE_STARVATION_CAP_MS, CooperativePassScheduler,
|
|
24
|
+
import { adaptivePollMs, advanceMonotonicDeadline, DEFAULT_EVENT_BATCH_LIMIT, DEFAULT_FAST_LANE_MAX_BYTES, DEFAULT_FAST_LANE_MAX_FILE_BYTES, DEFAULT_FAST_LANE_MAX_FILES, DEFAULT_FULL_RECONCILE_MS, EVENT_BATCH_LIMIT_ENV, FAST_LANE_MAX_BYTES_ENV, FAST_LANE_MAX_FILES_ENV, FULL_RECONCILE_MS_ENV, isFastLocalBatch, isLargeLocalUpload, localUploadSizeClass, isChoreLocalPush, isSessionLogsPushOnlyPath, isFastReceiverBatch, partitionLocalBatch, journalEntriesForWatcherDelete, resolveEventBatchLimit, resolveFullReconcileMs, resolveWatchPollMs, CHORE_STARVATION_CAP_MS, CooperativePassScheduler, allowConcurrentHandoffForGuardedWork, REALTIME_ADMISSION_DEADLINE_MS, REALTIME_DRAIN_BURST_MS, REALTIME_WORKER_OCCUPANCY_CAP, REALTIME_LARGE_UPLOAD_THRESHOLD_BYTES, RealtimeAdmissionTimeoutError, setRealtimeAdmissionDeadlineMsForTesting, setRealtimeDrainBurstMsForTesting, normalizeCoordinatorPaths, shouldQuarantineWatcherDeleteIntents, shouldUseAreaStorage, WATCHER_REDISCOVERY_RETRY_MS, WATCHER_REDISCOVERY_RETRY_MAX_MS, EVENT_SYNC_STARTUP_SHUTDOWN_WAIT_MS, } from "./sync-runner-watch-loop.js";
|
|
25
25
|
import { FullPassCapController, resetFullPassCapLogForTest, } from "../sync/full-pass-caps.js";
|
|
26
26
|
import { AreaLedgerMigration, JournalStore, getJournalPath, openJournalStateStoreForMigration, PERSONAL_VAULT_JOURNAL_SLUG, readJournal, readJournalForPass, readJournalScoped, readJournalScopedAsync, writeJournal, } from "../journal.js";
|
|
27
27
|
import { AreaLedger } from "../sync/area-ledger.js";
|
|
@@ -1755,7 +1755,7 @@ describe("automatic journal maintenance", () => {
|
|
|
1755
1755
|
const diagnostic = deps.stderr
|
|
1756
1756
|
.events()
|
|
1757
1757
|
.filter((event) => event.type === "bandwidth-policy")
|
|
1758
|
-
.find((event) => "
|
|
1758
|
+
.find((event) => "governorWaitMs" in event && (event.governorWaitMs ?? 0) > 0);
|
|
1759
1759
|
expect(diagnostic).toMatchObject({
|
|
1760
1760
|
type: "bandwidth-policy",
|
|
1761
1761
|
message: "bandwidth governor: 1 B/s cap",
|
|
@@ -1763,7 +1763,7 @@ describe("automatic journal maintenance", () => {
|
|
|
1763
1763
|
activeChoreTransfers: 1,
|
|
1764
1764
|
});
|
|
1765
1765
|
expect(diagnostic
|
|
1766
|
-
.
|
|
1766
|
+
.governorWaitMs).toBeGreaterThan(0);
|
|
1767
1767
|
}
|
|
1768
1768
|
finally {
|
|
1769
1769
|
releaseBody();
|
|
@@ -7201,7 +7201,7 @@ describe("runRunnerWithLoop — event-push wiring", () => {
|
|
|
7201
7201
|
});
|
|
7202
7202
|
await expect(superseded).resolves.toBeUndefined();
|
|
7203
7203
|
expect(runPass.mock.calls.filter(([argv]) => argv.includes("superseded.md"))).toHaveLength(0);
|
|
7204
|
-
expect(stderr.mock.calls.map(([chunk]) => String(chunk)).join("")).toContain('"event":"sync.realtime.timing","schemaVersion":
|
|
7204
|
+
expect(stderr.mock.calls.map(([chunk]) => String(chunk)).join("")).toContain('"event":"sync.realtime.timing","schemaVersion":5,"source":"receiver","direction":"pull","sizeClass":"unknown","outcome":"refused"');
|
|
7205
7205
|
releaseHeld();
|
|
7206
7206
|
await heldReceiverWork;
|
|
7207
7207
|
await replacement;
|
|
@@ -10283,184 +10283,6 @@ describe("runRunnerWithLoop — U58 realtime scheduler guard", () => {
|
|
|
10283
10283
|
process.env.HQ_SYNC_PARALLEL_COORDINATOR = previousCoordinator;
|
|
10284
10284
|
}
|
|
10285
10285
|
});
|
|
10286
|
-
it("REGRESSION: realtime held behind a running chore names that chore; an unblocked op names nothing", async () => {
|
|
10287
|
-
const previousCoordinator = process.env.HQ_SYNC_PARALLEL_COORDINATOR;
|
|
10288
|
-
process.env.HQ_SYNC_PARALLEL_COORDINATOR = "1";
|
|
10289
|
-
const watcher = makeWatcherStub();
|
|
10290
|
-
let triggerShutdown = () => { };
|
|
10291
|
-
let releaseCheckpoint = () => { };
|
|
10292
|
-
const checkpointGate = new Promise((resolve) => { releaseCheckpoint = resolve; });
|
|
10293
|
-
let markChoreHeld = () => { };
|
|
10294
|
-
const choreHeld = new Promise((resolve) => { markChoreHeld = resolve; });
|
|
10295
|
-
let receiverSync;
|
|
10296
|
-
let passes = 0;
|
|
10297
|
-
const timings = [];
|
|
10298
|
-
const stderr = vi.spyOn(process.stderr, "write").mockImplementation((chunk) => {
|
|
10299
|
-
if (typeof chunk === "string" && chunk.startsWith("{")) {
|
|
10300
|
-
try {
|
|
10301
|
-
const record = JSON.parse(chunk);
|
|
10302
|
-
if (record.event === "sync.realtime.timing")
|
|
10303
|
-
timings.push(record);
|
|
10304
|
-
}
|
|
10305
|
-
catch {
|
|
10306
|
-
// Non-telemetry diagnostics are outside this assertion.
|
|
10307
|
-
}
|
|
10308
|
-
}
|
|
10309
|
-
return true;
|
|
10310
|
-
});
|
|
10311
|
-
const receiverEvent = (relativePath) => ({
|
|
10312
|
-
kind: "upsert",
|
|
10313
|
-
relativePath,
|
|
10314
|
-
contentHash: "sha256:remote",
|
|
10315
|
-
mtime: "2026-10-03T13:00:00.000Z",
|
|
10316
|
-
originDeviceId: "peer-device",
|
|
10317
|
-
originTenantId: "tenant-indigo",
|
|
10318
|
-
sequenceNumber: 1,
|
|
10319
|
-
eventTimestamp: "2026-10-03T13:00:00.000Z",
|
|
10320
|
-
});
|
|
10321
|
-
const loop = runRunnerWithLoop(["--companies", "--watch", "--event-push", "--hq-root", "/tmp/hq"], {
|
|
10322
|
-
runPass: vi.fn().mockImplementation(async (argv, checkpoint) => {
|
|
10323
|
-
if (argv.some((argument) => argument.endsWith(".md")))
|
|
10324
|
-
return completedPassOutcome();
|
|
10325
|
-
passes += 1;
|
|
10326
|
-
if (passes === 2) {
|
|
10327
|
-
markChoreHeld();
|
|
10328
|
-
await checkpointGate;
|
|
10329
|
-
await checkpoint?.();
|
|
10330
|
-
}
|
|
10331
|
-
return completedPassOutcome();
|
|
10332
|
-
}),
|
|
10333
|
-
runPassSupportsCooperativeCheckpoint: true,
|
|
10334
|
-
clock: new FakeClock(),
|
|
10335
|
-
createWatcher: () => watcher,
|
|
10336
|
-
createReceiver: ({ syncBatchFn }) => {
|
|
10337
|
-
receiverSync = syncBatchFn;
|
|
10338
|
-
return { connected: true, start: async () => { }, dispose: async () => { } };
|
|
10339
|
-
},
|
|
10340
|
-
sleep: makeSteppableSleep().sleep,
|
|
10341
|
-
onShutdownSignal: (handler) => {
|
|
10342
|
-
triggerShutdown = handler;
|
|
10343
|
-
return () => { };
|
|
10344
|
-
},
|
|
10345
|
-
});
|
|
10346
|
-
try {
|
|
10347
|
-
await flushLoopMicrotasks(30);
|
|
10348
|
-
watcher.emit();
|
|
10349
|
-
await choreHeld;
|
|
10350
|
-
await flushLoopMicrotasks(10);
|
|
10351
|
-
const held = receiverSync({
|
|
10352
|
-
events: [receiverEvent("companies/indigo/held-by-chore.md")],
|
|
10353
|
-
signal: new AbortController().signal,
|
|
10354
|
-
});
|
|
10355
|
-
await flushLoopMicrotasks(20);
|
|
10356
|
-
releaseCheckpoint();
|
|
10357
|
-
await held;
|
|
10358
|
-
await flushLoopMicrotasks(20);
|
|
10359
|
-
await receiverSync({
|
|
10360
|
-
events: [receiverEvent("companies/indigo/unblocked.md")],
|
|
10361
|
-
signal: new AbortController().signal,
|
|
10362
|
-
});
|
|
10363
|
-
await flushLoopMicrotasks(10);
|
|
10364
|
-
const receiverTimings = timings.filter((record) => record.source === "receiver");
|
|
10365
|
-
expect(receiverTimings).toHaveLength(2);
|
|
10366
|
-
expect(receiverTimings[0]).toMatchObject({
|
|
10367
|
-
schemaVersion: 6,
|
|
10368
|
-
operationGateBlockedBy: "chore:full-reconcile",
|
|
10369
|
-
});
|
|
10370
|
-
expect(receiverTimings[1]).not.toHaveProperty("operationGateBlockedBy");
|
|
10371
|
-
expect(receiverTimings[1]).not.toHaveProperty("admissionBlockedBy");
|
|
10372
|
-
}
|
|
10373
|
-
finally {
|
|
10374
|
-
releaseCheckpoint();
|
|
10375
|
-
triggerShutdown();
|
|
10376
|
-
await loop;
|
|
10377
|
-
stderr.mockRestore();
|
|
10378
|
-
if (previousCoordinator === undefined)
|
|
10379
|
-
delete process.env.HQ_SYNC_PARALLEL_COORDINATOR;
|
|
10380
|
-
else
|
|
10381
|
-
process.env.HQ_SYNC_PARALLEL_COORDINATOR = previousCoordinator;
|
|
10382
|
-
}
|
|
10383
|
-
});
|
|
10384
|
-
it("REGRESSION: a wake drain held behind a running chore names that chore", async () => {
|
|
10385
|
-
const previousCoordinator = process.env.HQ_SYNC_PARALLEL_COORDINATOR;
|
|
10386
|
-
process.env.HQ_SYNC_PARALLEL_COORDINATOR = "1";
|
|
10387
|
-
const watcher = makeWatcherStub();
|
|
10388
|
-
let triggerShutdown = () => { };
|
|
10389
|
-
let releaseCheckpoint = () => { };
|
|
10390
|
-
const checkpointGate = new Promise((resolve) => { releaseCheckpoint = resolve; });
|
|
10391
|
-
let markChoreHeld = () => { };
|
|
10392
|
-
const choreHeld = new Promise((resolve) => { markChoreHeld = resolve; });
|
|
10393
|
-
let passes = 0;
|
|
10394
|
-
let runRealtime = null;
|
|
10395
|
-
const timings = [];
|
|
10396
|
-
const stderr = vi.spyOn(process.stderr, "write").mockImplementation((chunk) => {
|
|
10397
|
-
if (typeof chunk === "string" && chunk.startsWith("{")) {
|
|
10398
|
-
try {
|
|
10399
|
-
const record = JSON.parse(chunk);
|
|
10400
|
-
if (record.event === "sync.realtime.timing")
|
|
10401
|
-
timings.push(record);
|
|
10402
|
-
}
|
|
10403
|
-
catch {
|
|
10404
|
-
// Non-telemetry diagnostics are outside this assertion.
|
|
10405
|
-
}
|
|
10406
|
-
}
|
|
10407
|
-
return true;
|
|
10408
|
-
});
|
|
10409
|
-
const loop = runRunnerWithLoop(["--companies", "--watch", "--event-push", "--hq-root", "/tmp/hq"], {
|
|
10410
|
-
runPass: vi.fn().mockImplementation(async (_argv, checkpoint) => {
|
|
10411
|
-
passes += 1;
|
|
10412
|
-
if (passes === 2) {
|
|
10413
|
-
markChoreHeld();
|
|
10414
|
-
await checkpointGate;
|
|
10415
|
-
await checkpoint?.();
|
|
10416
|
-
}
|
|
10417
|
-
return completedPassOutcome();
|
|
10418
|
-
}),
|
|
10419
|
-
runPassSupportsCooperativeCheckpoint: true,
|
|
10420
|
-
clock: new FakeClock(),
|
|
10421
|
-
createWatcher: () => watcher,
|
|
10422
|
-
sleep: makeSteppableSleep().sleep,
|
|
10423
|
-
onShutdownSignal: (handler) => {
|
|
10424
|
-
triggerShutdown = handler;
|
|
10425
|
-
return () => { };
|
|
10426
|
-
},
|
|
10427
|
-
startRealtimeScheduler: async (opts) => {
|
|
10428
|
-
runRealtime = () => opts.runGuarded(async () => undefined);
|
|
10429
|
-
return {
|
|
10430
|
-
signal: () => undefined,
|
|
10431
|
-
checkHighWater: async () => undefined,
|
|
10432
|
-
dispose: async () => undefined,
|
|
10433
|
-
};
|
|
10434
|
-
},
|
|
10435
|
-
});
|
|
10436
|
-
try {
|
|
10437
|
-
await flushLoopMicrotasks(30);
|
|
10438
|
-
watcher.emit();
|
|
10439
|
-
await choreHeld;
|
|
10440
|
-
await flushLoopMicrotasks(10);
|
|
10441
|
-
const wake = runRealtime();
|
|
10442
|
-
await flushLoopMicrotasks(20);
|
|
10443
|
-
releaseCheckpoint();
|
|
10444
|
-
await wake;
|
|
10445
|
-
await flushLoopMicrotasks(20);
|
|
10446
|
-
const wakeTimings = timings.filter((record) => record.source === "wake");
|
|
10447
|
-
expect(wakeTimings).toHaveLength(1);
|
|
10448
|
-
expect(wakeTimings[0]).toMatchObject({
|
|
10449
|
-
schemaVersion: 6,
|
|
10450
|
-
operationGateBlockedBy: "chore:full-reconcile",
|
|
10451
|
-
});
|
|
10452
|
-
}
|
|
10453
|
-
finally {
|
|
10454
|
-
releaseCheckpoint();
|
|
10455
|
-
triggerShutdown();
|
|
10456
|
-
await loop;
|
|
10457
|
-
stderr.mockRestore();
|
|
10458
|
-
if (previousCoordinator === undefined)
|
|
10459
|
-
delete process.env.HQ_SYNC_PARALLEL_COORDINATOR;
|
|
10460
|
-
else
|
|
10461
|
-
process.env.HQ_SYNC_PARALLEL_COORDINATOR = previousCoordinator;
|
|
10462
|
-
}
|
|
10463
|
-
});
|
|
10464
10286
|
it("feeds a watcher-originated V2 drain through the same single-flight guard as the poll", async () => {
|
|
10465
10287
|
const watcher = makeWatcherStub();
|
|
10466
10288
|
let triggerShutdown = () => { };
|
|
@@ -11393,121 +11215,6 @@ describe("CooperativePassScheduler", () => {
|
|
|
11393
11215
|
await Promise.all([chore, realtime]);
|
|
11394
11216
|
expect(order).toEqual(["chore-start", "realtime", "chore-end"]);
|
|
11395
11217
|
});
|
|
11396
|
-
it("tells a queued realtime submission what holds the scheduler, and stays silent when it starts at once", async () => {
|
|
11397
|
-
const scheduler = new CooperativePassScheduler(() => 0);
|
|
11398
|
-
const heldBy = [];
|
|
11399
|
-
let releaseCheckpoint = () => { };
|
|
11400
|
-
const checkpointReady = new Promise((resolve) => {
|
|
11401
|
-
releaseCheckpoint = resolve;
|
|
11402
|
-
});
|
|
11403
|
-
const chore = scheduler.submit(async ({ checkpoint }) => {
|
|
11404
|
-
await checkpointReady;
|
|
11405
|
-
await checkpoint();
|
|
11406
|
-
return 0;
|
|
11407
|
-
}, "chore");
|
|
11408
|
-
await Promise.resolve();
|
|
11409
|
-
const realtime = scheduler.submit(async () => 0, "realtime", "slow", false, undefined, false, false, undefined, "unknown", (blocker) => heldBy.push(`${blocker.workClass}:${blocker.lane}`));
|
|
11410
|
-
expect(heldBy).toEqual(["chore:slow"]);
|
|
11411
|
-
releaseCheckpoint();
|
|
11412
|
-
await Promise.all([chore, realtime]);
|
|
11413
|
-
await scheduler.submit(async () => 0, "realtime", "slow", false, undefined, false, false, undefined, "unknown", (blocker) => heldBy.push(`${blocker.workClass}:${blocker.lane}`));
|
|
11414
|
-
expect(heldBy).toEqual(["chore:slow"]);
|
|
11415
|
-
});
|
|
11416
|
-
it("names the fast-lane occupant, not the slow pass, when a fast task queues behind it", async () => {
|
|
11417
|
-
const scheduler = new CooperativePassScheduler(() => 0);
|
|
11418
|
-
const heldBy = [];
|
|
11419
|
-
let releaseSlow = () => { };
|
|
11420
|
-
let releaseFast = () => { };
|
|
11421
|
-
const slowGate = new Promise((resolve) => { releaseSlow = resolve; });
|
|
11422
|
-
const fastGate = new Promise((resolve) => { releaseFast = resolve; });
|
|
11423
|
-
const slow = scheduler.submit(async () => { await slowGate; return 0; }, "realtime", "slow");
|
|
11424
|
-
await Promise.resolve();
|
|
11425
|
-
const fast = scheduler.submit(async () => { await fastGate; return 0; }, "realtime", "fast", true);
|
|
11426
|
-
await Promise.resolve();
|
|
11427
|
-
const queued = scheduler.submit(async () => 0, "realtime", "fast", true, undefined, false, false, undefined, "unknown", (blocker) => heldBy.push(blocker));
|
|
11428
|
-
expect(heldBy).toEqual([{ workClass: "realtime", lane: "fast" }]);
|
|
11429
|
-
releaseFast();
|
|
11430
|
-
releaseSlow();
|
|
11431
|
-
await Promise.all([slow, fast, queued]);
|
|
11432
|
-
});
|
|
11433
|
-
it("names the chore that holds the scheduler, not a later chore still waiting behind it", async () => {
|
|
11434
|
-
const scheduler = new CooperativePassScheduler(() => 0);
|
|
11435
|
-
const heldBy = [];
|
|
11436
|
-
let releaseFirst = () => { };
|
|
11437
|
-
const firstGate = new Promise((resolve) => { releaseFirst = resolve; });
|
|
11438
|
-
// A chore outside the coordinator owns the scheduler (no kind) ...
|
|
11439
|
-
const first = scheduler.submit(async ({ checkpoint }) => {
|
|
11440
|
-
await firstGate;
|
|
11441
|
-
await checkpoint();
|
|
11442
|
-
return 0;
|
|
11443
|
-
}, "chore");
|
|
11444
|
-
await Promise.resolve();
|
|
11445
|
-
// ... while a coordinator chore with a kind waits behind it.
|
|
11446
|
-
let releaseSecond = () => { };
|
|
11447
|
-
const secondGate = new Promise((resolve) => { releaseSecond = resolve; });
|
|
11448
|
-
let markSecondStarted = () => { };
|
|
11449
|
-
const secondStarted = new Promise((resolve) => { markSecondStarted = resolve; });
|
|
11450
|
-
const second = scheduler.submit(async ({ checkpoint }) => {
|
|
11451
|
-
markSecondStarted();
|
|
11452
|
-
await secondGate;
|
|
11453
|
-
await checkpoint();
|
|
11454
|
-
return 0;
|
|
11455
|
-
}, "chore", "slow", false, undefined, false, false, undefined, "unknown", undefined, "cadence");
|
|
11456
|
-
const realtime = scheduler.submit(async () => 0, "realtime", "slow", false, undefined, false, false, undefined, "unknown", (blocker) => heldBy.push(blocker));
|
|
11457
|
-
expect(heldBy).toEqual([{ workClass: "chore", lane: "slow" }]);
|
|
11458
|
-
releaseFirst();
|
|
11459
|
-
await first;
|
|
11460
|
-
await realtime;
|
|
11461
|
-
await secondStarted;
|
|
11462
|
-
// Now the kinded chore owns the scheduler; a new op is told its kind.
|
|
11463
|
-
const later = scheduler.submit(async () => 0, "realtime", "slow", false, undefined, false, false, undefined, "unknown", (blocker) => heldBy.push(blocker));
|
|
11464
|
-
expect(heldBy[1]).toEqual({ workClass: "chore", lane: "slow", choreKind: "cadence" });
|
|
11465
|
-
releaseSecond();
|
|
11466
|
-
await Promise.all([second, later]);
|
|
11467
|
-
});
|
|
11468
|
-
it("names the hand-off occupant that refuses admission, then the chore lending the slot", async () => {
|
|
11469
|
-
const scheduler = new CooperativePassScheduler(() => 0);
|
|
11470
|
-
const heldBy = [];
|
|
11471
|
-
let releaseCheckpoint = () => { };
|
|
11472
|
-
const checkpointGate = new Promise((resolve) => { releaseCheckpoint = resolve; });
|
|
11473
|
-
let releaseOccupant = () => { };
|
|
11474
|
-
const occupantGate = new Promise((resolve) => { releaseOccupant = resolve; });
|
|
11475
|
-
let markOccupantStarted = () => { };
|
|
11476
|
-
const occupantStarted = new Promise((resolve) => { markOccupantStarted = resolve; });
|
|
11477
|
-
const chore = scheduler.submit(async ({ checkpoint }) => {
|
|
11478
|
-
await checkpointGate;
|
|
11479
|
-
await checkpoint();
|
|
11480
|
-
return 0;
|
|
11481
|
-
}, "chore", "slow", false, undefined, true, false, undefined, "unknown", undefined, "full-reconcile");
|
|
11482
|
-
await Promise.resolve();
|
|
11483
|
-
// A coordinator-fenced push waits for the chore, then runs as a hand-off occupant.
|
|
11484
|
-
const occupant = scheduler.submit(async () => {
|
|
11485
|
-
markOccupantStarted();
|
|
11486
|
-
await occupantGate;
|
|
11487
|
-
return 0;
|
|
11488
|
-
}, "realtime", "slow", false, undefined, false, true, "push", "small");
|
|
11489
|
-
releaseCheckpoint();
|
|
11490
|
-
await occupantStarted;
|
|
11491
|
-
expect(scheduler.handoffActive).toBe(true);
|
|
11492
|
-
// A second push cannot share the occupant's direction, so the occupant holds it.
|
|
11493
|
-
const samePush = scheduler.submit(async () => 0, "realtime", "slow", false, undefined, false, true, "push", "small", (blocker) => heldBy.push(blocker));
|
|
11494
|
-
// A legacy (unfenced) op cannot join the hand-off at all; the lending chore holds it.
|
|
11495
|
-
const legacy = scheduler.submit(async () => 0, "realtime", "slow", false, undefined, false, false, undefined, "unknown", (blocker) => heldBy.push(blocker));
|
|
11496
|
-
expect(heldBy).toEqual([
|
|
11497
|
-
{ workClass: "realtime", lane: "slow" },
|
|
11498
|
-
{ workClass: "chore", lane: "slow", choreKind: "full-reconcile" },
|
|
11499
|
-
]);
|
|
11500
|
-
releaseOccupant();
|
|
11501
|
-
await Promise.all([chore, occupant, samePush, legacy]);
|
|
11502
|
-
});
|
|
11503
|
-
it("labels an unknown chore kind as chore:unscoped instead of failing the timing record", () => {
|
|
11504
|
-
expect(realtimeBlockerLabel({ workClass: "chore", lane: "slow", choreKind: "full-reconcile" }))
|
|
11505
|
-
.toBe("chore:full-reconcile");
|
|
11506
|
-
expect(realtimeBlockerLabel({ workClass: "chore", lane: "slow", choreKind: "future-kind" }))
|
|
11507
|
-
.toBe("chore:unscoped");
|
|
11508
|
-
expect(realtimeBlockerLabel({ workClass: "chore", lane: "slow" })).toBe("chore:unscoped");
|
|
11509
|
-
expect(realtimeBlockerLabel({ workClass: "realtime", lane: "fast" })).toBe("realtime:fast");
|
|
11510
|
-
});
|
|
11511
11218
|
it("refuses to wait past 2x the authorization timeout when the chore never yields", async () => {
|
|
11512
11219
|
setRealtimeAdmissionDeadlineMsForTesting(40);
|
|
11513
11220
|
const scheduler = new CooperativePassScheduler(() => 0);
|