@impz/testing 6.10.0 → 6.10.1

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.
Files changed (2) hide show
  1. package/dist/index.js +81 -28
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -21994,7 +21994,7 @@ import { join as join48 } from "path";
21994
21994
  // packages/daemon/package.json
21995
21995
  var package_default = {
21996
21996
  name: "@impz/daemon",
21997
- version: "6.10.0",
21997
+ version: "6.10.1",
21998
21998
  private: true,
21999
21999
  description: "impd: the imp host daemon",
22000
22000
  type: "module",
@@ -26293,6 +26293,11 @@ function handleUnknownOp(feature) {
26293
26293
  };
26294
26294
  }
26295
26295
 
26296
+ // packages/daemon/src/vm/agent-client/agent-wait-error.ts
26297
+ class AgentWaitError extends Error {
26298
+ name = "AgentWaitError";
26299
+ }
26300
+
26296
26301
  // packages/daemon/src/vm/agent-client/is-agent-session-state.ts
26297
26302
  function isAgentSessionState(state) {
26298
26303
  return state === "running" || state === "exited";
@@ -26419,7 +26424,7 @@ async function sendThaw(vsockPath) {
26419
26424
  decodeAgentMessage(OKSchema, response);
26420
26425
  }
26421
26426
  function readFrameWithin(connection, wait) {
26422
- return requireWithin(connection.next(), wait.timeoutMs, () => new Error(`agent at ${wait.vsockPath} sent no ${wait.call} within ${String(wait.timeoutMs)} ms`));
26427
+ return requireWithin(connection.next(), wait.timeoutMs, () => new AgentWaitError(`agent at ${wait.vsockPath} sent no ${wait.call} within ${String(wait.timeoutMs)} ms`));
26423
26428
  }
26424
26429
 
26425
26430
  // packages/daemon/src/imps/imps/consistent-disk.ts
@@ -37903,6 +37908,29 @@ function pickSleepVictims(candidates, needMib) {
37903
37908
  return { victims, enough: false };
37904
37909
  }
37905
37910
 
37911
+ // packages/daemon/src/imp-ops/governor/priority-admissions.ts
37912
+ function createPriorityAdmissions(priority) {
37913
+ const admitted = new Set;
37914
+ const isPriority = (name) => priority !== null && name !== null && isImpAllowed(priority.patterns, name);
37915
+ const isPriorityRequest = (request) => isPriority(request.priorityName ?? request.name);
37916
+ return {
37917
+ isPriority,
37918
+ isPriorityRequest,
37919
+ isPriorityImp: (imp) => admitted.has(imp.id) || isPriority(imp.name),
37920
+ isAdmittedPriority: (id) => admitted.has(id),
37921
+ recordAdmission: (request) => {
37922
+ if (isPriorityRequest(request)) {
37923
+ admitted.add(request.id);
37924
+ } else {
37925
+ admitted.delete(request.id);
37926
+ }
37927
+ },
37928
+ release: (id) => {
37929
+ admitted.delete(id);
37930
+ }
37931
+ };
37932
+ }
37933
+
37906
37934
  // packages/daemon/src/imp-ops/governor/ram-governor.ts
37907
37935
  var RESERVATION_TTL_MS = 20000;
37908
37936
  var ENFORCE_INTERVAL_MS = 5000;
@@ -37913,11 +37941,12 @@ function createRamGovernor(deps) {
37913
37941
  const reservations = new Map;
37914
37942
  const now = deps.now ?? Date.now;
37915
37943
  const priority = deps.priority ?? null;
37916
- const isPriority = (name) => priority !== null && name !== null && isImpAllowed(priority.patterns, name);
37944
+ const admittedPriority = createPriorityAdmissions(priority);
37945
+ const isPriority = admittedPriority.isPriority;
37946
+ const isPriorityImp = admittedPriority.isPriorityImp;
37917
37947
  const buildKept = (mib) => priority === null || mib === 0 ? null : { mib, patterns: priority.patterns };
37918
37948
  let stuckOver = false;
37919
37949
  const pendingHugePages = new Map;
37920
- const admittedPriority = new Set;
37921
37950
  const emitDecision = (decision) => {
37922
37951
  deps.events?.publish({
37923
37952
  v: EVENT_VERSION,
@@ -37948,11 +37977,7 @@ function createRamGovernor(deps) {
37948
37977
  if ((request.hugePagesMib ?? 0) > 0) {
37949
37978
  pendingHugePages.set(request.id, request.hugePagesMib ?? 0);
37950
37979
  }
37951
- if (isPriority(request.name)) {
37952
- admittedPriority.add(request.id);
37953
- } else {
37954
- admittedPriority.delete(request.id);
37955
- }
37980
+ admittedPriority.recordAdmission(request);
37956
37981
  emitAdmission(request, "admitted", usedMib);
37957
37982
  };
37958
37983
  const getReservationMib = (id) => {
@@ -37988,14 +38013,14 @@ function createRamGovernor(deps) {
37988
38013
  const live = [...reservations.keys()].filter((id) => id !== excludeId).map((id) => ({
37989
38014
  id,
37990
38015
  mib: getReservationMib(id),
37991
- isPriority: admittedPriority.has(id),
38016
+ isPriority: admittedPriority.isAdmittedPriority(id),
37992
38017
  isOnPool: pendingHugePages.has(id)
37993
38018
  }));
37994
- const pendingPool = [...pendingHugePages].filter(([id]) => id !== excludeId).map(([id, mib]) => ({ id, mib, isPriority: admittedPriority.has(id) }));
38019
+ const pendingPool = [...pendingHugePages].filter(([id]) => id !== excludeId).map(([id, mib]) => ({ id, mib, isPriority: admittedPriority.isAdmittedPriority(id) }));
37995
38020
  const headroom = deps.readHeadroomMib?.(awake.map((imp) => imp.pid)) ?? Promise.resolve(0);
37996
38021
  const headroomMib = await headroom;
37997
38022
  const totals = buildUsageTotals({
37998
- awake: awake.map((imp) => ({ ...imp, isPriority: isPriority(imp.name) })),
38023
+ awake: awake.map((imp) => ({ ...imp, isPriority: isPriorityImp(imp) })),
37999
38024
  readings,
38000
38025
  reservations: live,
38001
38026
  pendingPool,
@@ -38031,7 +38056,7 @@ function createRamGovernor(deps) {
38031
38056
  const shortfall = options.findShortfall(usage);
38032
38057
  const missingMib = shortfall.missingMib;
38033
38058
  const isOrdinary = shortfall.budget === "ordinary";
38034
- const sleepable = usage.awake.filter((imp) => !isOrdinary || imp.hugePagesMib === 0).filter((imp) => !options.sparesPriority || !isPriority(imp.name));
38059
+ const sleepable = usage.awake.filter((imp) => !isOrdinary || imp.hugePagesMib === 0).filter((imp) => !options.sparesPriority || !isPriorityImp(imp));
38035
38060
  if (missingMib <= 0) {
38036
38061
  return {
38037
38062
  fits: true,
@@ -38117,12 +38142,12 @@ function createRamGovernor(deps) {
38117
38142
  });
38118
38143
  }
38119
38144
  const bound = await readEffectiveUsage(request.id, deps.readResidentRam);
38120
- const isPriorityRequest = isPriority(request.name);
38145
+ const isPriorityAdmission = admittedPriority.isPriorityRequest(request);
38121
38146
  if (hugePagesMib > 0) {
38122
- const kept = isPriorityRequest ? null : buildKept(bound.kept.poolMib);
38147
+ const kept = isPriorityAdmission ? null : buildKept(bound.kept.poolMib);
38123
38148
  await checkHugePool(request, hugePagesMib, kept);
38124
38149
  }
38125
- const findReserveShortfall = (usage) => pickEffectiveShortfall(usage, budgets, request.reserveMib, isPriorityRequest);
38150
+ const findReserveShortfall = (usage) => pickEffectiveShortfall(usage, budgets, request.reserveMib, isPriorityAdmission);
38126
38151
  if (findReserveShortfall(bound).missingMib <= 0) {
38127
38152
  recordAdmission(request, bound.effectiveMib);
38128
38153
  return;
@@ -38132,7 +38157,7 @@ function createRamGovernor(deps) {
38132
38157
  reason: `to make room for ${request.name ?? request.id}`,
38133
38158
  whenShort: "giveUp",
38134
38159
  findShortfall: findReserveShortfall,
38135
- sparesPriority: !isPriorityRequest
38160
+ sparesPriority: !isPriorityAdmission
38136
38161
  });
38137
38162
  const diskFull = room.diskFull ? deps.readDiskFullError?.() ?? null : null;
38138
38163
  if (!room.fits && diskFull !== null) {
@@ -38162,7 +38187,7 @@ function createRamGovernor(deps) {
38162
38187
  release: (id) => {
38163
38188
  reservations.delete(id);
38164
38189
  pendingHugePages.delete(id);
38165
- admittedPriority.delete(id);
38190
+ admittedPriority.release(id);
38166
38191
  },
38167
38192
  admitGrow: (request) => admission.run("background", async () => {
38168
38193
  const listed = await deps.listAwake();
@@ -38170,14 +38195,15 @@ function createRamGovernor(deps) {
38170
38195
  return false;
38171
38196
  }
38172
38197
  const budgets = readBudgets();
38173
- const findGrowShortfall = (usage) => pickEffectiveShortfall(usage, budgets, request.mib, isPriority(request.name));
38198
+ const isPriorityGrow = isPriorityImp(request);
38199
+ const findGrowShortfall = (usage) => pickEffectiveShortfall(usage, budgets, request.mib, isPriorityGrow);
38174
38200
  const room = await makeRoom({
38175
38201
  excludeId: null,
38176
38202
  reason: `to grow ${request.name}`,
38177
38203
  whenShort: "giveUp",
38178
38204
  findShortfall: findGrowShortfall,
38179
38205
  protectedId: request.id,
38180
- sparesPriority: !isPriority(request.name)
38206
+ sparesPriority: !isPriorityGrow
38181
38207
  });
38182
38208
  const usage = await readEffectiveUsage(null);
38183
38209
  const shortfall = findGrowShortfall(usage);
@@ -38681,6 +38707,7 @@ function createImpCommands(parts) {
38681
38707
  const checkpoints = await listCheckpoints(context.db, imp.id);
38682
38708
  await removeImpFiles(context, imp.id, checkpoints.map((checkpoint) => checkpoint.id));
38683
38709
  context.admission.release(imp.id);
38710
+ context.priorityNames.delete(imp.id);
38684
38711
  await removeImp(context.db, imp.id);
38685
38712
  };
38686
38713
  return {
@@ -38699,6 +38726,9 @@ function createImpCommands(parts) {
38699
38726
  await context.diskBudget.requireRoom(0);
38700
38727
  return lock.withNewImp(id, writeRecord, async (imp) => {
38701
38728
  const paths = context.findPaths(imp.id);
38729
+ if (input.priorityName !== undefined) {
38730
+ context.priorityNames.set(imp.id, input.priorityName);
38731
+ }
38702
38732
  context.sessionLogs.admitImp(imp.id);
38703
38733
  const started = performance.now();
38704
38734
  const recordMs = Math.round(started - received);
@@ -38771,6 +38801,7 @@ function createImpCommands(parts) {
38771
38801
  } catch (error) {
38772
38802
  await Promise.allSettled([sizing]);
38773
38803
  if (isRamBudgetError(error)) {
38804
+ context.priorityNames.delete(imp.id);
38774
38805
  await removeImpFiles(context, imp.id, []);
38775
38806
  await removeImp(context.db, imp.id);
38776
38807
  }
@@ -41374,8 +41405,15 @@ function createImpContext(deps) {
41374
41405
  growFilesystem: deps.growFilesystem,
41375
41406
  kernelOops: deps.kernelOops
41376
41407
  };
41408
+ const priorityNames = new Map;
41377
41409
  const memory = {
41378
- admission: deps.admission,
41410
+ admission: {
41411
+ ...deps.admission,
41412
+ admit: (request) => deps.admission.admit({
41413
+ ...request,
41414
+ priorityName: request.priorityName ?? priorityNames.get(request.id)
41415
+ })
41416
+ },
41379
41417
  readRamMib: deps.readRamMib,
41380
41418
  readRssMib: deps.readRssMib,
41381
41419
  readSleepRamMib: deps.config.ksm === null ? deps.readRamMib : deps.readUnsharedRamMib,
@@ -41383,6 +41421,7 @@ function createImpContext(deps) {
41383
41421
  probeUffdDevice: deps.probeUffdDevice,
41384
41422
  mergeFlags: createMergeFlags(),
41385
41423
  memoryLimit: deps.memoryLimit ?? NO_MEMORY_LIMIT,
41424
+ priorityNames,
41386
41425
  pluggedSizes: deps.pluggedSizes ?? createPluggedSizes(),
41387
41426
  resources: createResourceSampler({
41388
41427
  now,
@@ -48476,6 +48515,11 @@ async function waitForEngine(exec, signal, clock) {
48476
48515
  const info = await exec(["docker", "info", "--format", "{{.ServerVersion}}"], {
48477
48516
  signal,
48478
48517
  timeoutMs: ENGINE_READY_MS
48518
+ }).catch((error) => {
48519
+ if (!(error instanceof AgentWaitError)) {
48520
+ throw error;
48521
+ }
48522
+ return { exitCode: -1, stdout: "", stderr: error.message };
48479
48523
  });
48480
48524
  if (info.exitCode === 0) {
48481
48525
  return;
@@ -48490,9 +48534,16 @@ async function waitForEngine(exec, signal, clock) {
48490
48534
  var ENGINE_LOG_PATH = "/var/log/imp/docker.log";
48491
48535
  var ENGINE_LOG_LINES = 20;
48492
48536
  async function readEngineLog(exec, signal) {
48493
- const tail = await exec(["tail", "-n", String(ENGINE_LOG_LINES), ENGINE_LOG_PATH], { signal });
48494
- const lines = tail.stdout.trim();
48495
- if (tail.exitCode !== 0 || lines === "") {
48537
+ const tail = await exec(["tail", "-n", String(ENGINE_LOG_LINES), ENGINE_LOG_PATH], {
48538
+ signal
48539
+ }).catch((error) => {
48540
+ if (!(error instanceof AgentWaitError)) {
48541
+ throw error;
48542
+ }
48543
+ return null;
48544
+ });
48545
+ const lines = tail?.stdout.trim() ?? "";
48546
+ if (tail?.exitCode !== 0 || lines === "") {
48496
48547
  return "";
48497
48548
  }
48498
48549
  return `
@@ -48563,7 +48614,8 @@ function createBuilders(deps) {
48563
48614
  }
48564
48615
  };
48565
48616
  return {
48566
- withBuilder: async (signal, run) => {
48617
+ withBuilder: async (builderRequest, run) => {
48618
+ const signal = builderRequest.signal;
48567
48619
  await deps.ensureImage(signal);
48568
48620
  signal.throwIfAborted();
48569
48621
  const id = Bun.randomUUIDv7();
@@ -48577,7 +48629,8 @@ function createBuilders(deps) {
48577
48629
  memoryMib: deps.config.build.memoryMib,
48578
48630
  diskMib: Math.ceil(deps.config.build.diskBytes / 1024 ** 2),
48579
48631
  policy: { mode: "public", allow: [] },
48580
- kind: "builder"
48632
+ kind: "builder",
48633
+ priorityName: builderRequest.imageName
48581
48634
  });
48582
48635
  const exec = createGuestExec((request) => deps.imps.openBuilderExec(name, request));
48583
48636
  await waitForEngine(exec, signal, clock);
@@ -50805,7 +50858,7 @@ function createImageBuilds(deps, writer) {
50805
50858
  if (builders === null) {
50806
50859
  throw new ImpdError("SERVICE_UNAVAILABLE", { message: "impd is starting; try again" });
50807
50860
  }
50808
- return builders.withBuilder(signal, async (exec, builderName) => {
50861
+ return builders.withBuilder({ signal, imageName }, async (exec, builderName) => {
50809
50862
  options.setBuilder?.(builderName);
50810
50863
  const started = deps.clock.now();
50811
50864
  await writePinnedContext(createBuildEngine(toEngineRun(exec)));
@@ -51303,7 +51356,7 @@ function createImageAdds(deps, writer) {
51303
51356
  throw new ImpdError("SERVICE_UNAVAILABLE", { message: "impd is starting; try again" });
51304
51357
  }
51305
51358
  const explicitRef = formatExplicitRef(ref);
51306
- return builders.withBuilder(signal, async (exec) => {
51359
+ return builders.withBuilder({ signal, imageName }, async (exec) => {
51307
51360
  const started = deps.clock.now();
51308
51361
  const platform = await createBuildEngine(toEngineRun(exec)).readPlatform(signal);
51309
51362
  const pulled = await loadGuestImage(exec, { ref: explicitRef, platform, signal });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@impz/testing",
3
- "version": "6.10.0",
3
+ "version": "6.10.1",
4
4
  "description": "A real impd on stand-ins, for Bun tests of code that drives impd through @impz/client",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -29,7 +29,7 @@
29
29
  "@orpc/openapi-client": "^1.16.1",
30
30
  "@orpc/server": "^1.16.1",
31
31
  "@peculiar/x509": "^2.2.0",
32
- "@zgeoff/kysely-bun-sqlite": "^0.3.0",
32
+ "@zgeoff/kysely-bun-sqlite": "^0.3.1",
33
33
  "better-auth": "^1.7.14",
34
34
  "dns-packet": "^5.6.1",
35
35
  "elysia": "^1.4.30",
@@ -43,7 +43,7 @@
43
43
  "ts-pattern": "^5.9.2",
44
44
  "xstate": "^5.33.3",
45
45
  "zod": "^4.6.7",
46
- "@impz/client": "6.10.0"
46
+ "@impz/client": "6.10.1"
47
47
  },
48
48
  "engines": {
49
49
  "bun": ">=1.4.3"