@shipfox/api-runners 12.1.0 → 12.3.0
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/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +35 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +24 -2
- package/dist/config.js.map +1 -1
- package/dist/core/errors.d.ts +4 -0
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +6 -0
- package/dist/core/errors.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/rate-limit.d.ts.map +1 -1
- package/dist/core/runner-control-sessions.d.ts.map +1 -1
- package/dist/core/runner-control-sessions.js +37 -11
- package/dist/core/runner-control-sessions.js.map +1 -1
- package/dist/core/runner-instances.d.ts +1 -0
- package/dist/core/runner-instances.d.ts.map +1 -1
- package/dist/core/runner-instances.js.map +1 -1
- package/dist/core/runner-labels.d.ts +11 -0
- package/dist/core/runner-labels.d.ts.map +1 -0
- package/dist/core/runner-labels.js +41 -0
- package/dist/core/runner-labels.js.map +1 -0
- package/dist/core/runner-sessions.d.ts.map +1 -1
- package/dist/core/runner-sessions.js +5 -1
- package/dist/core/runner-sessions.js.map +1 -1
- package/dist/db/db.d.ts +64 -64
- package/dist/db/ephemeral-registration-tokens.d.ts.map +1 -1
- package/dist/db/ephemeral-registration-tokens.js +12 -2
- package/dist/db/ephemeral-registration-tokens.js.map +1 -1
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +1 -1
- package/dist/db/index.js.map +1 -1
- package/dist/db/reservations.d.ts.map +1 -1
- package/dist/db/reservations.js +36 -10
- package/dist/db/reservations.js.map +1 -1
- package/dist/db/runner-instances.d.ts +4 -0
- package/dist/db/runner-instances.d.ts.map +1 -1
- package/dist/db/runner-instances.js +16 -5
- package/dist/db/runner-instances.js.map +1 -1
- package/dist/db/runner-sessions.d.ts.map +1 -1
- package/dist/db/runner-sessions.js +33 -15
- package/dist/db/runner-sessions.js.map +1 -1
- package/dist/db/schema/admin-command-results.d.ts +1 -1
- package/dist/db/schema/ephemeral-registration-tokens.d.ts +1 -1
- package/dist/db/schema/manual-registration-tokens.d.ts +1 -1
- package/dist/db/schema/outbox.d.ts +1 -1
- package/dist/db/schema/pending-job-executions.d.ts +3 -3
- package/dist/db/schema/provisioner-capability-snapshots.d.ts +3 -3
- package/dist/db/schema/provisioner-tokens.d.ts +2 -2
- package/dist/db/schema/rate-limits.d.ts +1 -1
- package/dist/db/schema/reservations.d.ts +3 -3
- package/dist/db/schema/runner-activation-tokens.d.ts +1 -1
- package/dist/db/schema/runner-control-sessions.d.ts +2 -2
- package/dist/db/schema/runner-instances.d.ts +4 -4
- package/dist/db/schema/runner-instances.d.ts.map +1 -1
- package/dist/db/schema/runner-instances.js +1 -0
- package/dist/db/schema/runner-instances.js.map +1 -1
- package/dist/db/schema/runner-sessions.d.ts +4 -4
- package/dist/db/schema/running-job-executions.d.ts +5 -5
- package/dist/metrics/index.d.ts +2 -1
- package/dist/metrics/index.d.ts.map +1 -1
- package/dist/metrics/index.js +1 -1
- package/dist/metrics/index.js.map +1 -1
- package/dist/metrics/instance.d.ts +13 -8
- package/dist/metrics/instance.d.ts.map +1 -1
- package/dist/metrics/instance.js +8 -0
- package/dist/metrics/instance.js.map +1 -1
- package/dist/metrics/service.d.ts.map +1 -1
- package/dist/metrics/service.js +20 -4
- package/dist/metrics/service.js.map +1 -1
- package/dist/presentation/dto/admin-provisioner-token.d.ts +1 -1
- package/dist/presentation/dto/admin-provisioner-token.d.ts.map +1 -1
- package/dist/presentation/dto/admin-runner-instances.d.ts +2 -2
- package/dist/presentation/dto/admin-runner-instances.d.ts.map +1 -1
- package/dist/presentation/routes/poll-demand.d.ts.map +1 -1
- package/dist/presentation/routes/poll-demand.js +12 -6
- package/dist/presentation/routes/poll-demand.js.map +1 -1
- package/dist/presentation/routes/rate-limit.d.ts.map +1 -1
- package/dist/presentation/routes/register.d.ts.map +1 -1
- package/dist/presentation/routes/register.js +9 -1
- package/dist/presentation/routes/register.js.map +1 -1
- package/dist/presentation/routes/report-runner-instances.d.ts.map +1 -1
- package/dist/presentation/routes/report-runner-instances.js +1 -0
- package/dist/presentation/routes/report-runner-instances.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/drizzle/0004_huge_skreet.sql +1 -0
- package/drizzle/meta/0004_snapshot.json +2194 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +9 -9
- package/src/config.test.ts +81 -0
- package/src/config.ts +39 -2
- package/src/core/errors.ts +9 -0
- package/src/core/index.ts +1 -0
- package/src/core/runner-control-sessions.test.ts +404 -0
- package/src/core/runner-control-sessions.ts +51 -11
- package/src/core/runner-instances.ts +1 -0
- package/src/core/runner-labels.test.ts +53 -0
- package/src/core/runner-labels.ts +51 -0
- package/src/core/runner-sessions.test.ts +34 -1
- package/src/core/runner-sessions.ts +8 -1
- package/src/db/ephemeral-registration-tokens.ts +15 -1
- package/src/db/index.ts +1 -0
- package/src/db/reservations.test.ts +537 -0
- package/src/db/reservations.ts +116 -17
- package/src/db/runner-instances.test.ts +276 -1
- package/src/db/runner-instances.ts +39 -3
- package/src/db/runner-sessions.ts +39 -15
- package/src/db/schema/runner-instances.ts +3 -0
- package/src/metrics/index.ts +2 -0
- package/src/metrics/instance.ts +18 -0
- package/src/metrics/service.test.ts +99 -0
- package/src/metrics/service.ts +24 -4
- package/src/presentation/routes/late-runner-enrollment.test.ts +230 -0
- package/src/presentation/routes/poll-demand.test.ts +116 -3
- package/src/presentation/routes/poll-demand.ts +18 -6
- package/src/presentation/routes/register.test.ts +116 -2
- package/src/presentation/routes/register.ts +7 -0
- package/src/presentation/routes/report-runner-instances.test.ts +33 -0
- package/src/presentation/routes/report-runner-instances.ts +1 -0
- package/src/presentation/routes/runner-enrollment.test.ts +65 -5
- package/src/temporal/activities/maintenance-activities.test.ts +24 -31
- package/test/env.ts +1 -0
- package/test/fixtures/late-runner-enrollment.ts +103 -0
- package/test/index.ts +5 -0
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -175,8 +175,8 @@ export declare const providerRunners: import("drizzle-orm/pg-core").PgTableWithC
|
|
|
175
175
|
}, {}, {
|
|
176
176
|
baseBuilder: import("drizzle-orm/pg-core").PgColumnBuilder<{
|
|
177
177
|
name: "labels";
|
|
178
|
-
dataType:
|
|
179
|
-
columnType:
|
|
178
|
+
dataType: 'string';
|
|
179
|
+
columnType: 'PgText';
|
|
180
180
|
data: string;
|
|
181
181
|
enumValues: [string, ...string[]];
|
|
182
182
|
driverParam: string;
|
|
@@ -188,7 +188,7 @@ export declare const providerRunners: import("drizzle-orm/pg-core").PgTableWithC
|
|
|
188
188
|
tableName: "runner_instances";
|
|
189
189
|
dataType: "string";
|
|
190
190
|
columnType: "PgEnumColumn";
|
|
191
|
-
data: "
|
|
191
|
+
data: "failed" | "running" | "starting" | "stopped" | "stopping" | "terminated";
|
|
192
192
|
driverParam: string;
|
|
193
193
|
notNull: true;
|
|
194
194
|
hasDefault: false;
|
|
@@ -476,7 +476,7 @@ export declare const providerRunners: import("drizzle-orm/pg-core").PgTableWithC
|
|
|
476
476
|
generated: undefined;
|
|
477
477
|
}, {}, {}>;
|
|
478
478
|
};
|
|
479
|
-
dialect:
|
|
479
|
+
dialect: 'pg';
|
|
480
480
|
}>;
|
|
481
481
|
export type RunnerInstanceDb = typeof providerRunners.$inferSelect;
|
|
482
482
|
export type RunnerInstanceInsertDb = typeof providerRunners.$inferInsert;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner-instances.d.ts","sourceRoot":"","sources":["../../../src/db/schema/runner-instances.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,mCAAmC,CAAC;AAGtE,eAAO,MAAM,uBAAuB,8GAOlC,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"runner-instances.d.ts","sourceRoot":"","sources":["../../../src/db/schema/runner-instances.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,mCAAmC,CAAC;AAGtE,eAAO,MAAM,uBAAuB,8GAOlC,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwD3B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,OAAO,eAAe,CAAC,YAAY,CAAC;AACnE,MAAM,MAAM,sBAAsB,GAAG,OAAO,eAAe,CAAC,YAAY,CAAC;AAEzE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,GAAG,cAAc,CAyBtE"}
|
|
@@ -65,6 +65,7 @@ export const providerRunners = pgTable('runner_instances', {
|
|
|
65
65
|
index('runners_runner_instances_workspace_state_updated_idx').on(table.state, table.updatedAt),
|
|
66
66
|
index('runners_runner_instances_stale_reaper_idx').on(table.state, table.updatedAt, table.reportedAt),
|
|
67
67
|
index('runners_runner_instances_provisioner_intended_reservation_idx').on(table.provisionerId, table.intendedReservationId).where(sql`${table.intendedReservationId} is not null and ${table.reservationReleasedAt} is null`),
|
|
68
|
+
index('runners_runner_instances_intended_reservation_idx').on(table.intendedReservationId).where(sql`${table.intendedReservationId} is not null`),
|
|
68
69
|
index('runners_runner_instances_provisioner_reservation_idx').on(table.provisionerId, table.reservationId).where(sql`${table.reservationId} is not null`),
|
|
69
70
|
index('runners_runner_instances_active_template_counts_idx').on(table.provisionerId, table.state, table.templateKey).where(sql`"state" in ('starting', 'running') and "template_key" is not null`)
|
|
70
71
|
]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/db/schema/runner-instances.ts"],"sourcesContent":["import type {RunnerToolCapabilitiesDto} from '@shipfox/api-runners-dto';\nimport {uuidv7PrimaryKey} from '@shipfox/node-drizzle';\nimport {sql} from 'drizzle-orm';\nimport {index, jsonb, pgEnum, text, timestamp, uniqueIndex, uuid} from 'drizzle-orm/pg-core';\nimport type {RunnerInstance} from '#core/entities/runner-instance.js';\nimport {pgTable} from './common.js';\n\nexport const providerRunnerStateEnum = pgEnum('runners_provider_runner_state', [\n 'starting',\n 'running',\n 'stopping',\n 'stopped',\n 'failed',\n 'terminated',\n]);\n\nexport const providerRunners = pgTable(\n 'runner_instances',\n {\n id: uuidv7PrimaryKey(),\n // Kept during the protocol migration for legacy workspace capacity. New capacity is owned\n // only by its provisioner and has no workspace assignment.\n workspaceId: uuid('workspace_id'),\n provisionerId: uuid('provisioner_id').notNull(),\n providerRunnerId: text('provider_runner_id'),\n intendedReservationId: uuid('intended_reservation_id'),\n reservationId: uuid('reservation_id'),\n assignedAt: timestamp('assigned_at', {withTimezone: true}),\n templateKey: text('template_key'),\n labels: text('labels').array().notNull().default([]),\n state: providerRunnerStateEnum('state').notNull(),\n reason: text('reason'),\n runnerSessionId: uuid('runner_session_id'),\n firstClaimedAt: timestamp('first_claimed_at', {withTimezone: true}),\n providerKind: text('provider_kind'),\n protocolVersion: text('protocol_version'),\n capabilities: jsonb('capabilities').$type<RunnerToolCapabilitiesDto | null>(),\n reportedAt: timestamp('reported_at', {withTimezone: true}).notNull(),\n startedAt: timestamp('started_at', {withTimezone: true}),\n stoppingAt: timestamp('stopping_at', {withTimezone: true}),\n stoppedAt: timestamp('stopped_at', {withTimezone: true}),\n failedAt: timestamp('failed_at', {withTimezone: true}),\n terminatedAt: timestamp('terminated_at', {withTimezone: true}),\n reservationReleasedAt: timestamp('reservation_released_at', {withTimezone: true}),\n createdAt: timestamp('created_at', {withTimezone: true}).notNull().defaultNow(),\n updatedAt: timestamp('updated_at', {withTimezone: true}).notNull().defaultNow(),\n },\n (table) => [\n uniqueIndex('runners_runner_instances_provisioner_runner_unique')\n .on(table.provisionerId, table.providerRunnerId)\n .where(sql`${table.providerRunnerId} is not null`),\n index('runners_runner_instances_workspace_state_updated_idx').on(table.state, table.updatedAt),\n index('runners_runner_instances_stale_reaper_idx').on(\n table.state,\n table.updatedAt,\n table.reportedAt,\n ),\n index('runners_runner_instances_provisioner_intended_reservation_idx')\n .on(table.provisionerId, table.intendedReservationId)\n .where(\n sql`${table.intendedReservationId} is not null and ${table.reservationReleasedAt} is null`,\n ),\n index('runners_runner_instances_provisioner_reservation_idx')\n .on(table.provisionerId, table.reservationId)\n .where(sql`${table.reservationId} is not null`),\n index('runners_runner_instances_active_template_counts_idx')\n .on(table.provisionerId, table.state, table.templateKey)\n .where(sql`\"state\" in ('starting', 'running') and \"template_key\" is not null`),\n ],\n);\n\nexport type RunnerInstanceDb = typeof providerRunners.$inferSelect;\nexport type RunnerInstanceInsertDb = typeof providerRunners.$inferInsert;\n\nexport function toRunnerInstance(row: RunnerInstanceDb): RunnerInstance {\n if (!row.providerRunnerId) throw new Error('Runner instance has no provider runner identity');\n return {\n id: row.id,\n workspaceId: row.workspaceId,\n provisionerId: row.provisionerId,\n providerRunnerId: row.providerRunnerId,\n reservationId: row.reservationId,\n assignedAt: row.assignedAt,\n templateKey: row.templateKey,\n labels: row.labels,\n state: row.state,\n reason: row.reason,\n runnerSessionId: row.runnerSessionId,\n providerKind: row.providerKind,\n reportedAt: row.reportedAt,\n startedAt: row.startedAt,\n stoppingAt: row.stoppingAt,\n stoppedAt: row.stoppedAt,\n failedAt: row.failedAt,\n terminatedAt: row.terminatedAt,\n reservationReleasedAt: row.reservationReleasedAt,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n}\n"],"names":["uuidv7PrimaryKey","sql","index","jsonb","pgEnum","text","timestamp","uniqueIndex","uuid","pgTable","providerRunnerStateEnum","providerRunners","id","workspaceId","provisionerId","notNull","providerRunnerId","intendedReservationId","reservationId","assignedAt","withTimezone","templateKey","labels","array","default","state","reason","runnerSessionId","firstClaimedAt","providerKind","protocolVersion","capabilities","$type","reportedAt","startedAt","stoppingAt","stoppedAt","failedAt","terminatedAt","reservationReleasedAt","createdAt","defaultNow","updatedAt","table","on","where","toRunnerInstance","row","Error"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/db/schema/runner-instances.ts"],"sourcesContent":["import type {RunnerToolCapabilitiesDto} from '@shipfox/api-runners-dto';\nimport {uuidv7PrimaryKey} from '@shipfox/node-drizzle';\nimport {sql} from 'drizzle-orm';\nimport {index, jsonb, pgEnum, text, timestamp, uniqueIndex, uuid} from 'drizzle-orm/pg-core';\nimport type {RunnerInstance} from '#core/entities/runner-instance.js';\nimport {pgTable} from './common.js';\n\nexport const providerRunnerStateEnum = pgEnum('runners_provider_runner_state', [\n 'starting',\n 'running',\n 'stopping',\n 'stopped',\n 'failed',\n 'terminated',\n]);\n\nexport const providerRunners = pgTable(\n 'runner_instances',\n {\n id: uuidv7PrimaryKey(),\n // Kept during the protocol migration for legacy workspace capacity. New capacity is owned\n // only by its provisioner and has no workspace assignment.\n workspaceId: uuid('workspace_id'),\n provisionerId: uuid('provisioner_id').notNull(),\n providerRunnerId: text('provider_runner_id'),\n intendedReservationId: uuid('intended_reservation_id'),\n reservationId: uuid('reservation_id'),\n assignedAt: timestamp('assigned_at', {withTimezone: true}),\n templateKey: text('template_key'),\n labels: text('labels').array().notNull().default([]),\n state: providerRunnerStateEnum('state').notNull(),\n reason: text('reason'),\n runnerSessionId: uuid('runner_session_id'),\n firstClaimedAt: timestamp('first_claimed_at', {withTimezone: true}),\n providerKind: text('provider_kind'),\n protocolVersion: text('protocol_version'),\n capabilities: jsonb('capabilities').$type<RunnerToolCapabilitiesDto | null>(),\n reportedAt: timestamp('reported_at', {withTimezone: true}).notNull(),\n startedAt: timestamp('started_at', {withTimezone: true}),\n stoppingAt: timestamp('stopping_at', {withTimezone: true}),\n stoppedAt: timestamp('stopped_at', {withTimezone: true}),\n failedAt: timestamp('failed_at', {withTimezone: true}),\n terminatedAt: timestamp('terminated_at', {withTimezone: true}),\n reservationReleasedAt: timestamp('reservation_released_at', {withTimezone: true}),\n createdAt: timestamp('created_at', {withTimezone: true}).notNull().defaultNow(),\n updatedAt: timestamp('updated_at', {withTimezone: true}).notNull().defaultNow(),\n },\n (table) => [\n uniqueIndex('runners_runner_instances_provisioner_runner_unique')\n .on(table.provisionerId, table.providerRunnerId)\n .where(sql`${table.providerRunnerId} is not null`),\n index('runners_runner_instances_workspace_state_updated_idx').on(table.state, table.updatedAt),\n index('runners_runner_instances_stale_reaper_idx').on(\n table.state,\n table.updatedAt,\n table.reportedAt,\n ),\n index('runners_runner_instances_provisioner_intended_reservation_idx')\n .on(table.provisionerId, table.intendedReservationId)\n .where(\n sql`${table.intendedReservationId} is not null and ${table.reservationReleasedAt} is null`,\n ),\n index('runners_runner_instances_intended_reservation_idx')\n .on(table.intendedReservationId)\n .where(sql`${table.intendedReservationId} is not null`),\n index('runners_runner_instances_provisioner_reservation_idx')\n .on(table.provisionerId, table.reservationId)\n .where(sql`${table.reservationId} is not null`),\n index('runners_runner_instances_active_template_counts_idx')\n .on(table.provisionerId, table.state, table.templateKey)\n .where(sql`\"state\" in ('starting', 'running') and \"template_key\" is not null`),\n ],\n);\n\nexport type RunnerInstanceDb = typeof providerRunners.$inferSelect;\nexport type RunnerInstanceInsertDb = typeof providerRunners.$inferInsert;\n\nexport function toRunnerInstance(row: RunnerInstanceDb): RunnerInstance {\n if (!row.providerRunnerId) throw new Error('Runner instance has no provider runner identity');\n return {\n id: row.id,\n workspaceId: row.workspaceId,\n provisionerId: row.provisionerId,\n providerRunnerId: row.providerRunnerId,\n reservationId: row.reservationId,\n assignedAt: row.assignedAt,\n templateKey: row.templateKey,\n labels: row.labels,\n state: row.state,\n reason: row.reason,\n runnerSessionId: row.runnerSessionId,\n providerKind: row.providerKind,\n reportedAt: row.reportedAt,\n startedAt: row.startedAt,\n stoppingAt: row.stoppingAt,\n stoppedAt: row.stoppedAt,\n failedAt: row.failedAt,\n terminatedAt: row.terminatedAt,\n reservationReleasedAt: row.reservationReleasedAt,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n}\n"],"names":["uuidv7PrimaryKey","sql","index","jsonb","pgEnum","text","timestamp","uniqueIndex","uuid","pgTable","providerRunnerStateEnum","providerRunners","id","workspaceId","provisionerId","notNull","providerRunnerId","intendedReservationId","reservationId","assignedAt","withTimezone","templateKey","labels","array","default","state","reason","runnerSessionId","firstClaimedAt","providerKind","protocolVersion","capabilities","$type","reportedAt","startedAt","stoppingAt","stoppedAt","failedAt","terminatedAt","reservationReleasedAt","createdAt","defaultNow","updatedAt","table","on","where","toRunnerInstance","row","Error"],"mappings":"AACA,SAAQA,gBAAgB,QAAO,wBAAwB;AACvD,SAAQC,GAAG,QAAO,cAAc;AAChC,SAAQC,KAAK,EAAEC,KAAK,EAAEC,MAAM,EAAEC,IAAI,EAAEC,SAAS,EAAEC,WAAW,EAAEC,IAAI,QAAO,sBAAsB;AAE7F,SAAQC,OAAO,QAAO,cAAc;AAEpC,OAAO,MAAMC,0BAA0BN,OAAO,iCAAiC;IAC7E;IACA;IACA;IACA;IACA;IACA;CACD,EAAE;AAEH,OAAO,MAAMO,kBAAkBF,QAC7B,oBACA;IACEG,IAAIZ;IACJ,0FAA0F;IAC1F,2DAA2D;IAC3Da,aAAaL,KAAK;IAClBM,eAAeN,KAAK,kBAAkBO,OAAO;IAC7CC,kBAAkBX,KAAK;IACvBY,uBAAuBT,KAAK;IAC5BU,eAAeV,KAAK;IACpBW,YAAYb,UAAU,eAAe;QAACc,cAAc;IAAI;IACxDC,aAAahB,KAAK;IAClBiB,QAAQjB,KAAK,UAAUkB,KAAK,GAAGR,OAAO,GAAGS,OAAO,CAAC,EAAE;IACnDC,OAAOf,wBAAwB,SAASK,OAAO;IAC/CW,QAAQrB,KAAK;IACbsB,iBAAiBnB,KAAK;IACtBoB,gBAAgBtB,UAAU,oBAAoB;QAACc,cAAc;IAAI;IACjES,cAAcxB,KAAK;IACnByB,iBAAiBzB,KAAK;IACtB0B,cAAc5B,MAAM,gBAAgB6B,KAAK;IACzCC,YAAY3B,UAAU,eAAe;QAACc,cAAc;IAAI,GAAGL,OAAO;IAClEmB,WAAW5B,UAAU,cAAc;QAACc,cAAc;IAAI;IACtDe,YAAY7B,UAAU,eAAe;QAACc,cAAc;IAAI;IACxDgB,WAAW9B,UAAU,cAAc;QAACc,cAAc;IAAI;IACtDiB,UAAU/B,UAAU,aAAa;QAACc,cAAc;IAAI;IACpDkB,cAAchC,UAAU,iBAAiB;QAACc,cAAc;IAAI;IAC5DmB,uBAAuBjC,UAAU,2BAA2B;QAACc,cAAc;IAAI;IAC/EoB,WAAWlC,UAAU,cAAc;QAACc,cAAc;IAAI,GAAGL,OAAO,GAAG0B,UAAU;IAC7EC,WAAWpC,UAAU,cAAc;QAACc,cAAc;IAAI,GAAGL,OAAO,GAAG0B,UAAU;AAC/E,GACA,CAACE,QAAU;QACTpC,YAAY,sDACTqC,EAAE,CAACD,MAAM7B,aAAa,EAAE6B,MAAM3B,gBAAgB,EAC9C6B,KAAK,CAAC5C,GAAG,CAAC,EAAE0C,MAAM3B,gBAAgB,CAAC,YAAY,CAAC;QACnDd,MAAM,wDAAwD0C,EAAE,CAACD,MAAMlB,KAAK,EAAEkB,MAAMD,SAAS;QAC7FxC,MAAM,6CAA6C0C,EAAE,CACnDD,MAAMlB,KAAK,EACXkB,MAAMD,SAAS,EACfC,MAAMV,UAAU;QAElB/B,MAAM,iEACH0C,EAAE,CAACD,MAAM7B,aAAa,EAAE6B,MAAM1B,qBAAqB,EACnD4B,KAAK,CACJ5C,GAAG,CAAC,EAAE0C,MAAM1B,qBAAqB,CAAC,iBAAiB,EAAE0B,MAAMJ,qBAAqB,CAAC,QAAQ,CAAC;QAE9FrC,MAAM,qDACH0C,EAAE,CAACD,MAAM1B,qBAAqB,EAC9B4B,KAAK,CAAC5C,GAAG,CAAC,EAAE0C,MAAM1B,qBAAqB,CAAC,YAAY,CAAC;QACxDf,MAAM,wDACH0C,EAAE,CAACD,MAAM7B,aAAa,EAAE6B,MAAMzB,aAAa,EAC3C2B,KAAK,CAAC5C,GAAG,CAAC,EAAE0C,MAAMzB,aAAa,CAAC,YAAY,CAAC;QAChDhB,MAAM,uDACH0C,EAAE,CAACD,MAAM7B,aAAa,EAAE6B,MAAMlB,KAAK,EAAEkB,MAAMtB,WAAW,EACtDwB,KAAK,CAAC5C,GAAG,CAAC,iEAAiE,CAAC;KAChF,EACD;AAKF,OAAO,SAAS6C,iBAAiBC,GAAqB;IACpD,IAAI,CAACA,IAAI/B,gBAAgB,EAAE,MAAM,IAAIgC,MAAM;IAC3C,OAAO;QACLpC,IAAImC,IAAInC,EAAE;QACVC,aAAakC,IAAIlC,WAAW;QAC5BC,eAAeiC,IAAIjC,aAAa;QAChCE,kBAAkB+B,IAAI/B,gBAAgB;QACtCE,eAAe6B,IAAI7B,aAAa;QAChCC,YAAY4B,IAAI5B,UAAU;QAC1BE,aAAa0B,IAAI1B,WAAW;QAC5BC,QAAQyB,IAAIzB,MAAM;QAClBG,OAAOsB,IAAItB,KAAK;QAChBC,QAAQqB,IAAIrB,MAAM;QAClBC,iBAAiBoB,IAAIpB,eAAe;QACpCE,cAAckB,IAAIlB,YAAY;QAC9BI,YAAYc,IAAId,UAAU;QAC1BC,WAAWa,IAAIb,SAAS;QACxBC,YAAYY,IAAIZ,UAAU;QAC1BC,WAAWW,IAAIX,SAAS;QACxBC,UAAUU,IAAIV,QAAQ;QACtBC,cAAcS,IAAIT,YAAY;QAC9BC,uBAAuBQ,IAAIR,qBAAqB;QAChDC,WAAWO,IAAIP,SAAS;QACxBE,WAAWK,IAAIL,SAAS;IAC1B;AACF"}
|
|
@@ -78,7 +78,7 @@ export declare const runnerSessions: import("drizzle-orm/pg-core").PgTableWithCo
|
|
|
78
78
|
tableName: "runner_sessions";
|
|
79
79
|
dataType: "string";
|
|
80
80
|
columnType: "PgEnumColumn";
|
|
81
|
-
data: "
|
|
81
|
+
data: "activation" | "ephemeral" | "manual";
|
|
82
82
|
driverParam: string;
|
|
83
83
|
notNull: true;
|
|
84
84
|
hasDefault: false;
|
|
@@ -176,8 +176,8 @@ export declare const runnerSessions: import("drizzle-orm/pg-core").PgTableWithCo
|
|
|
176
176
|
}, {}, {
|
|
177
177
|
baseBuilder: import("drizzle-orm/pg-core").PgColumnBuilder<{
|
|
178
178
|
name: "labels";
|
|
179
|
-
dataType:
|
|
180
|
-
columnType:
|
|
179
|
+
dataType: 'string';
|
|
180
|
+
columnType: 'PgText';
|
|
181
181
|
data: string;
|
|
182
182
|
enumValues: [string, ...string[]];
|
|
183
183
|
driverParam: string;
|
|
@@ -324,7 +324,7 @@ export declare const runnerSessions: import("drizzle-orm/pg-core").PgTableWithCo
|
|
|
324
324
|
generated: undefined;
|
|
325
325
|
}, {}, {}>;
|
|
326
326
|
};
|
|
327
|
-
dialect:
|
|
327
|
+
dialect: 'pg';
|
|
328
328
|
}>;
|
|
329
329
|
export type RunnerSessionDb = typeof runnerSessions.$inferSelect;
|
|
330
330
|
export type RunnerSessionInsertDb = typeof runnerSessions.$inferInsert;
|
|
@@ -207,8 +207,8 @@ export declare const runningJobExecutions: import("drizzle-orm/pg-core").PgTable
|
|
|
207
207
|
}, {}, {
|
|
208
208
|
baseBuilder: import("drizzle-orm/pg-core").PgColumnBuilder<{
|
|
209
209
|
name: "required_labels";
|
|
210
|
-
dataType:
|
|
211
|
-
columnType:
|
|
210
|
+
dataType: 'string';
|
|
211
|
+
columnType: 'PgText';
|
|
212
212
|
data: string;
|
|
213
213
|
enumValues: [string, ...string[]];
|
|
214
214
|
driverParam: string;
|
|
@@ -250,8 +250,8 @@ export declare const runningJobExecutions: import("drizzle-orm/pg-core").PgTable
|
|
|
250
250
|
}, {}, {
|
|
251
251
|
baseBuilder: import("drizzle-orm/pg-core").PgColumnBuilder<{
|
|
252
252
|
name: "runner_labels";
|
|
253
|
-
dataType:
|
|
254
|
-
columnType:
|
|
253
|
+
dataType: 'string';
|
|
254
|
+
columnType: 'PgText';
|
|
255
255
|
data: string;
|
|
256
256
|
enumValues: [string, ...string[]];
|
|
257
257
|
driverParam: string;
|
|
@@ -327,7 +327,7 @@ export declare const runningJobExecutions: import("drizzle-orm/pg-core").PgTable
|
|
|
327
327
|
generated: undefined;
|
|
328
328
|
}, {}, {}>;
|
|
329
329
|
};
|
|
330
|
-
dialect:
|
|
330
|
+
dialect: 'pg';
|
|
331
331
|
}>;
|
|
332
332
|
export type RunningJobExecutionDb = typeof runningJobExecutions.$inferSelect;
|
|
333
333
|
export type RunningJobExecutionInsertDb = typeof runningJobExecutions.$inferInsert;
|
package/dist/metrics/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export type { RunnerReservationPromotionFailureReason } from './instance.js';
|
|
2
|
+
export { jobExecutionClaimedCount, jobExecutionEnqueuedCount, jobExecutionLeaseExpiredCount, providerRunnerAbsentTerminatedCount, providerRunnerCountDivergenceCount, providerRunnerReconcileCallCount, providerRunnerTerminateIntentHonoredCount, providerRunnerTerminateIntentIssuedCount, recordRunnerReservationPromotionFailure, recordRunnersRateLimitCheck, recordRunnersRateLimitPruneFailure, } from './instance.js';
|
|
2
3
|
export { registerRunnersServiceMetrics } from './service.js';
|
|
3
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,6BAA6B,EAC7B,mCAAmC,EACnC,kCAAkC,EAClC,gCAAgC,EAChC,yCAAyC,EACzC,wCAAwC,EACxC,2BAA2B,EAC3B,kCAAkC,GACnC,MAAM,eAAe,CAAC;AACvB,OAAO,EAAC,6BAA6B,EAAC,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAC,uCAAuC,EAAC,MAAM,eAAe,CAAC;AAC3E,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,6BAA6B,EAC7B,mCAAmC,EACnC,kCAAkC,EAClC,gCAAgC,EAChC,yCAAyC,EACzC,wCAAwC,EACxC,uCAAuC,EACvC,2BAA2B,EAC3B,kCAAkC,GACnC,MAAM,eAAe,CAAC;AACvB,OAAO,EAAC,6BAA6B,EAAC,MAAM,cAAc,CAAC"}
|
package/dist/metrics/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { jobExecutionClaimedCount, jobExecutionEnqueuedCount, jobExecutionLeaseExpiredCount, providerRunnerAbsentTerminatedCount, providerRunnerCountDivergenceCount, providerRunnerReconcileCallCount, providerRunnerTerminateIntentHonoredCount, providerRunnerTerminateIntentIssuedCount, recordRunnersRateLimitCheck, recordRunnersRateLimitPruneFailure } from './instance.js';
|
|
1
|
+
export { jobExecutionClaimedCount, jobExecutionEnqueuedCount, jobExecutionLeaseExpiredCount, providerRunnerAbsentTerminatedCount, providerRunnerCountDivergenceCount, providerRunnerReconcileCallCount, providerRunnerTerminateIntentHonoredCount, providerRunnerTerminateIntentIssuedCount, recordRunnerReservationPromotionFailure, recordRunnersRateLimitCheck, recordRunnersRateLimitPruneFailure } from './instance.js';
|
|
2
2
|
export { registerRunnersServiceMetrics } from './service.js';
|
|
3
3
|
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/metrics/index.ts"],"sourcesContent":["export {\n jobExecutionClaimedCount,\n jobExecutionEnqueuedCount,\n jobExecutionLeaseExpiredCount,\n providerRunnerAbsentTerminatedCount,\n providerRunnerCountDivergenceCount,\n providerRunnerReconcileCallCount,\n providerRunnerTerminateIntentHonoredCount,\n providerRunnerTerminateIntentIssuedCount,\n recordRunnersRateLimitCheck,\n recordRunnersRateLimitPruneFailure,\n} from './instance.js';\nexport {registerRunnersServiceMetrics} from './service.js';\n"],"names":["jobExecutionClaimedCount","jobExecutionEnqueuedCount","jobExecutionLeaseExpiredCount","providerRunnerAbsentTerminatedCount","providerRunnerCountDivergenceCount","providerRunnerReconcileCallCount","providerRunnerTerminateIntentHonoredCount","providerRunnerTerminateIntentIssuedCount","recordRunnersRateLimitCheck","recordRunnersRateLimitPruneFailure","registerRunnersServiceMetrics"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/metrics/index.ts"],"sourcesContent":["export type {RunnerReservationPromotionFailureReason} from './instance.js';\nexport {\n jobExecutionClaimedCount,\n jobExecutionEnqueuedCount,\n jobExecutionLeaseExpiredCount,\n providerRunnerAbsentTerminatedCount,\n providerRunnerCountDivergenceCount,\n providerRunnerReconcileCallCount,\n providerRunnerTerminateIntentHonoredCount,\n providerRunnerTerminateIntentIssuedCount,\n recordRunnerReservationPromotionFailure,\n recordRunnersRateLimitCheck,\n recordRunnersRateLimitPruneFailure,\n} from './instance.js';\nexport {registerRunnersServiceMetrics} from './service.js';\n"],"names":["jobExecutionClaimedCount","jobExecutionEnqueuedCount","jobExecutionLeaseExpiredCount","providerRunnerAbsentTerminatedCount","providerRunnerCountDivergenceCount","providerRunnerReconcileCallCount","providerRunnerTerminateIntentHonoredCount","providerRunnerTerminateIntentIssuedCount","recordRunnerReservationPromotionFailure","recordRunnersRateLimitCheck","recordRunnersRateLimitPruneFailure","registerRunnersServiceMetrics"],"mappings":"AACA,SACEA,wBAAwB,EACxBC,yBAAyB,EACzBC,6BAA6B,EAC7BC,mCAAmC,EACnCC,kCAAkC,EAClCC,gCAAgC,EAChCC,yCAAyC,EACzCC,wCAAwC,EACxCC,uCAAuC,EACvCC,2BAA2B,EAC3BC,kCAAkC,QAC7B,gBAAgB;AACvB,SAAQC,6BAA6B,QAAO,eAAe"}
|
|
@@ -1,34 +1,39 @@
|
|
|
1
1
|
export declare const jobExecutionEnqueuedCount: import("@shipfox/node-opentelemetry").Counter<Record<string, never>>;
|
|
2
2
|
export declare const jobExecutionClaimedCount: import("@shipfox/node-opentelemetry").Counter<{
|
|
3
|
-
outcome:
|
|
3
|
+
outcome: 'claimed' | 'empty';
|
|
4
4
|
}>;
|
|
5
5
|
export declare const jobExecutionLeaseExpiredCount: import("@shipfox/node-opentelemetry").Counter<Record<string, never>>;
|
|
6
6
|
export declare const providerRunnerReportCount: import("@shipfox/node-opentelemetry").Counter<{
|
|
7
|
-
state:
|
|
7
|
+
state: 'starting' | 'running' | 'stopping' | 'stopped' | 'failed' | 'terminated';
|
|
8
8
|
}>;
|
|
9
9
|
export declare const runnerBootstrapExchangeCount: import("@shipfox/node-opentelemetry").Counter<{
|
|
10
|
-
outcome:
|
|
10
|
+
outcome: 'accepted' | 'rejected';
|
|
11
11
|
}>;
|
|
12
12
|
export declare const runnerControlHeartbeatCount: import("@shipfox/node-opentelemetry").Counter<Record<string, never>>;
|
|
13
13
|
export declare const providerRunnerReapedCount: import("@shipfox/node-opentelemetry").Counter<Record<string, never>>;
|
|
14
14
|
export declare const providerRunnerCountDivergenceCount: import("@shipfox/node-opentelemetry").Counter<{
|
|
15
15
|
template_key?: string;
|
|
16
|
-
state:
|
|
17
|
-
direction:
|
|
16
|
+
state: 'starting' | 'running';
|
|
17
|
+
direction: 'backend-higher' | 'advertised-higher';
|
|
18
18
|
}>;
|
|
19
19
|
export declare const providerRunnerReconcileCallCount: import("@shipfox/node-opentelemetry").Counter<Record<string, never>>;
|
|
20
20
|
export declare const providerRunnerAbsentTerminatedCount: import("@shipfox/node-opentelemetry").Counter<Record<string, never>>;
|
|
21
21
|
export declare const providerRunnerTerminateIntentIssuedCount: import("@shipfox/node-opentelemetry").Counter<{
|
|
22
|
-
surface:
|
|
23
|
-
reason:
|
|
22
|
+
surface: 'poll-demand' | 'reconcile';
|
|
23
|
+
reason: 'job-cancelled' | 'terminal-state';
|
|
24
24
|
}>;
|
|
25
25
|
export declare const providerRunnerTerminateIntentHonoredCount: import("@shipfox/node-opentelemetry").Counter<{
|
|
26
|
-
reason:
|
|
26
|
+
reason: 'job-cancelled';
|
|
27
27
|
}>;
|
|
28
28
|
export declare const reservationReleasedCount: import("@shipfox/node-opentelemetry").Counter<Record<string, never>>;
|
|
29
|
+
export type RunnerReservationPromotionFailureReason = 'reservation-expired' | 'reservation-not-found' | 'already-assigned' | 'not-assignable';
|
|
30
|
+
export declare const runnerReservationPromotionFailureCount: import("@shipfox/node-opentelemetry").Counter<{
|
|
31
|
+
reason: RunnerReservationPromotionFailureReason;
|
|
32
|
+
}>;
|
|
29
33
|
export type RunnersRateLimitAction = 'provisioner-mint' | 'ephemeral-register';
|
|
30
34
|
export type RunnersRateLimitScope = 'provisioner' | 'ephemeral-token';
|
|
31
35
|
export type RunnersRateLimitOutcome = 'allowed' | 'blocked' | 'unavailable';
|
|
36
|
+
export declare function recordRunnerReservationPromotionFailure(reason: RunnerReservationPromotionFailureReason): void;
|
|
32
37
|
export declare function recordRunnersRateLimitCheck(params: {
|
|
33
38
|
action: RunnersRateLimitAction;
|
|
34
39
|
scope: RunnersRateLimitScope;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../../src/metrics/instance.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,yBAAyB,sEAKrC,CAAC;AAEF,eAAO,MAAM,wBAAwB;aAAiC,SAAS,GAAG,OAAO;EAGxF,CAAC;AAEF,eAAO,MAAM,6BAA6B,sEAGzC,CAAC;AAEF,eAAO,MAAM,yBAAyB;WAC7B,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,YAAY;EAGhF,CAAC;AAEH,eAAO,MAAM,4BAA4B;aAC9B,UAAU,GAAG,UAAU;EAGhC,CAAC;AAEH,eAAO,MAAM,2BAA2B,sEAGvC,CAAC;AAEF,eAAO,MAAM,yBAAyB,sEAKrC,CAAC;AAEF,eAAO,MAAM,kCAAkC;mBAC9B,MAAM;WACd,UAAU,GAAG,SAAS;eAClB,gBAAgB,GAAG,mBAAmB;EAIjD,CAAC;AAEH,eAAO,MAAM,gCAAgC,sEAG5C,CAAC;AAEF,eAAO,MAAM,mCAAmC,sEAM/C,CAAC;AAEF,eAAO,MAAM,wCAAwC;aAC1C,aAAa,GAAG,WAAW;YAC5B,eAAe,GAAG,gBAAgB;EAG1C,CAAC;AAEH,eAAO,MAAM,yCAAyC;YAC5C,eAAe;EAGvB,CAAC;AAEH,eAAO,MAAM,wBAAwB,sEAGpC,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,kBAAkB,GAAG,oBAAoB,CAAC;AAC/E,MAAM,MAAM,qBAAqB,GAAG,aAAa,GAAG,iBAAiB,CAAC;AACtE,MAAM,MAAM,uBAAuB,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAC;AAsB5E,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,MAAM,EAAE,sBAAsB,CAAC;IAC/B,KAAK,EAAE,qBAAqB,CAAC;IAC7B,OAAO,EAAE,uBAAuB,CAAC;CAClC,GAAG,IAAI,CAQP;AAED,wBAAgB,kCAAkC,IAAI,IAAI,CAEzD"}
|
|
1
|
+
{"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../../src/metrics/instance.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,yBAAyB,sEAKrC,CAAC;AAEF,eAAO,MAAM,wBAAwB;aAAiC,SAAS,GAAG,OAAO;EAGxF,CAAC;AAEF,eAAO,MAAM,6BAA6B,sEAGzC,CAAC;AAEF,eAAO,MAAM,yBAAyB;WAC7B,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,YAAY;EAGhF,CAAC;AAEH,eAAO,MAAM,4BAA4B;aAC9B,UAAU,GAAG,UAAU;EAGhC,CAAC;AAEH,eAAO,MAAM,2BAA2B,sEAGvC,CAAC;AAEF,eAAO,MAAM,yBAAyB,sEAKrC,CAAC;AAEF,eAAO,MAAM,kCAAkC;mBAC9B,MAAM;WACd,UAAU,GAAG,SAAS;eAClB,gBAAgB,GAAG,mBAAmB;EAIjD,CAAC;AAEH,eAAO,MAAM,gCAAgC,sEAG5C,CAAC;AAEF,eAAO,MAAM,mCAAmC,sEAM/C,CAAC;AAEF,eAAO,MAAM,wCAAwC;aAC1C,aAAa,GAAG,WAAW;YAC5B,eAAe,GAAG,gBAAgB;EAG1C,CAAC;AAEH,eAAO,MAAM,yCAAyC;YAC5C,eAAe;EAGvB,CAAC;AAEH,eAAO,MAAM,wBAAwB,sEAGpC,CAAC;AAEF,MAAM,MAAM,uCAAuC,GAC/C,qBAAqB,GACrB,uBAAuB,GACvB,kBAAkB,GAClB,gBAAgB,CAAC;AAErB,eAAO,MAAM,sCAAsC;YACzC,uCAAuC;EAG/C,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,kBAAkB,GAAG,oBAAoB,CAAC;AAC/E,MAAM,MAAM,qBAAqB,GAAG,aAAa,GAAG,iBAAiB,CAAC;AACtE,MAAM,MAAM,uBAAuB,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAC;AAsB5E,wBAAgB,uCAAuC,CACrD,MAAM,EAAE,uCAAuC,GAC9C,IAAI,CAEN;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,MAAM,EAAE,sBAAsB,CAAC;IAC/B,KAAK,EAAE,qBAAqB,CAAC;IAC7B,OAAO,EAAE,uBAAuB,CAAC;CAClC,GAAG,IAAI,CAQP;AAED,wBAAgB,kCAAkC,IAAI,IAAI,CAEzD"}
|
package/dist/metrics/instance.js
CHANGED
|
@@ -39,6 +39,9 @@ export const providerRunnerTerminateIntentHonoredCount = meter.createCounter('ru
|
|
|
39
39
|
export const reservationReleasedCount = meter.createCounter('runners_reservation_released', {
|
|
40
40
|
description: 'Reservation units released from terminal provisioned runner reports'
|
|
41
41
|
});
|
|
42
|
+
export const runnerReservationPromotionFailureCount = meter.createCounter('runners_reservation_promotion_failures', {
|
|
43
|
+
description: 'Runner reservation promotion failures during enrollment by reason'
|
|
44
|
+
});
|
|
42
45
|
const rateLimitCheckCount = meter.createCounter('runners_rate_limit_checks', {
|
|
43
46
|
description: 'Runners rate limit checks by action, scope, and outcome'
|
|
44
47
|
});
|
|
@@ -52,6 +55,11 @@ function recordMetric(record) {
|
|
|
52
55
|
// Metrics must not affect runner or provisioner request outcomes.
|
|
53
56
|
}
|
|
54
57
|
}
|
|
58
|
+
export function recordRunnerReservationPromotionFailure(reason) {
|
|
59
|
+
recordMetric(()=>runnerReservationPromotionFailureCount.add(1, {
|
|
60
|
+
reason
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
55
63
|
export function recordRunnersRateLimitCheck(params) {
|
|
56
64
|
recordMetric(()=>rateLimitCheckCount.add(1, {
|
|
57
65
|
action: params.action,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/metrics/instance.ts"],"sourcesContent":["import {instanceMetrics} from '@shipfox/node-opentelemetry';\n\nconst meter = instanceMetrics.getMeter('runners');\n\nexport const jobExecutionEnqueuedCount = meter.createCounter<Record<string, never>>(\n 'runners_job_execution_enqueued',\n {\n description: 'Job executions added to the pending queue',\n },\n);\n\nexport const jobExecutionClaimedCount = meter.createCounter<{outcome: 'claimed' | 'empty'}>(\n 'runners_job_execution_claimed',\n {description: 'Job execution claim attempts by outcome'},\n);\n\nexport const jobExecutionLeaseExpiredCount = meter.createCounter<Record<string, never>>(\n 'runners_job_execution_lease_expired',\n {description: 'Job execution leases reaped after passing the heartbeat threshold'},\n);\n\nexport const providerRunnerReportCount = meter.createCounter<{\n state: 'starting' | 'running' | 'stopping' | 'stopped' | 'failed' | 'terminated';\n}>('runners_provider_runner_reported', {\n description: 'Provisioned runner lifecycle reports accepted by state',\n});\n\nexport const runnerBootstrapExchangeCount = meter.createCounter<{\n outcome: 'accepted' | 'rejected';\n}>('runners_runner_bootstrap_exchange', {\n description: 'Runner bootstrap-token exchanges by outcome',\n});\n\nexport const runnerControlHeartbeatCount = meter.createCounter<Record<string, never>>(\n 'runners_runner_control_heartbeat',\n {description: 'Pre-workspace runner-control heartbeats accepted'},\n);\n\nexport const providerRunnerReapedCount = meter.createCounter<Record<string, never>>(\n 'runners_provider_runner_reaped',\n {\n description: 'Stale provisioned runners marked failed by backend maintenance',\n },\n);\n\nexport const providerRunnerCountDivergenceCount = meter.createCounter<{\n template_key?: string;\n state: 'starting' | 'running';\n direction: 'backend-higher' | 'advertised-higher';\n}>('runners_provider_runner_count_divergence', {\n description:\n 'Absolute difference between provisioner-advertised and backend-observed provisioned runner counts',\n});\n\nexport const providerRunnerReconcileCallCount = meter.createCounter<Record<string, never>>(\n 'runners_provider_runner_reconcile_called',\n {description: 'Provisioned runner reconcile calls completed successfully'},\n);\n\nexport const providerRunnerAbsentTerminatedCount = meter.createCounter<Record<string, never>>(\n 'runners_provider_runner_absent_terminated',\n {\n description:\n 'Owned provisioned runners marked terminated because they were absent from reconcile',\n },\n);\n\nexport const providerRunnerTerminateIntentIssuedCount = meter.createCounter<{\n surface: 'poll-demand' | 'reconcile';\n reason: 'job-cancelled' | 'terminal-state';\n}>('runners_provider_runner_terminate_intent_issued', {\n description: 'Provisioned runner terminate intents returned to provisioners',\n});\n\nexport const providerRunnerTerminateIntentHonoredCount = meter.createCounter<{\n reason: 'job-cancelled';\n}>('runners_provider_runner_terminate_intent_honored', {\n description: 'Provisioned runner terminate intents honored by first transition to terminated',\n});\n\nexport const reservationReleasedCount = meter.createCounter<Record<string, never>>(\n 'runners_reservation_released',\n {description: 'Reservation units released from terminal provisioned runner reports'},\n);\n\nexport type RunnersRateLimitAction = 'provisioner-mint' | 'ephemeral-register';\nexport type RunnersRateLimitScope = 'provisioner' | 'ephemeral-token';\nexport type RunnersRateLimitOutcome = 'allowed' | 'blocked' | 'unavailable';\n\nconst rateLimitCheckCount = meter.createCounter<{\n action: RunnersRateLimitAction;\n scope: RunnersRateLimitScope;\n outcome: RunnersRateLimitOutcome;\n}>('runners_rate_limit_checks', {\n description: 'Runners rate limit checks by action, scope, and outcome',\n});\n\nconst rateLimitPruneFailureCount = meter.createCounter('runners_rate_limit_prune_failures', {\n description: 'Runners rate limit prune failures',\n});\n\nfunction recordMetric(record: () => void): void {\n try {\n record();\n } catch {\n // Metrics must not affect runner or provisioner request outcomes.\n }\n}\n\nexport function recordRunnersRateLimitCheck(params: {\n action: RunnersRateLimitAction;\n scope: RunnersRateLimitScope;\n outcome: RunnersRateLimitOutcome;\n}): void {\n recordMetric(() =>\n rateLimitCheckCount.add(1, {\n action: params.action,\n scope: params.scope,\n outcome: params.outcome,\n }),\n );\n}\n\nexport function recordRunnersRateLimitPruneFailure(): void {\n recordMetric(() => rateLimitPruneFailureCount.add(1));\n}\n"],"names":["instanceMetrics","meter","getMeter","jobExecutionEnqueuedCount","createCounter","description","jobExecutionClaimedCount","jobExecutionLeaseExpiredCount","providerRunnerReportCount","runnerBootstrapExchangeCount","runnerControlHeartbeatCount","providerRunnerReapedCount","providerRunnerCountDivergenceCount","providerRunnerReconcileCallCount","providerRunnerAbsentTerminatedCount","providerRunnerTerminateIntentIssuedCount","providerRunnerTerminateIntentHonoredCount","reservationReleasedCount","rateLimitCheckCount","rateLimitPruneFailureCount","recordMetric","record","
|
|
1
|
+
{"version":3,"sources":["../../src/metrics/instance.ts"],"sourcesContent":["import {instanceMetrics} from '@shipfox/node-opentelemetry';\n\nconst meter = instanceMetrics.getMeter('runners');\n\nexport const jobExecutionEnqueuedCount = meter.createCounter<Record<string, never>>(\n 'runners_job_execution_enqueued',\n {\n description: 'Job executions added to the pending queue',\n },\n);\n\nexport const jobExecutionClaimedCount = meter.createCounter<{outcome: 'claimed' | 'empty'}>(\n 'runners_job_execution_claimed',\n {description: 'Job execution claim attempts by outcome'},\n);\n\nexport const jobExecutionLeaseExpiredCount = meter.createCounter<Record<string, never>>(\n 'runners_job_execution_lease_expired',\n {description: 'Job execution leases reaped after passing the heartbeat threshold'},\n);\n\nexport const providerRunnerReportCount = meter.createCounter<{\n state: 'starting' | 'running' | 'stopping' | 'stopped' | 'failed' | 'terminated';\n}>('runners_provider_runner_reported', {\n description: 'Provisioned runner lifecycle reports accepted by state',\n});\n\nexport const runnerBootstrapExchangeCount = meter.createCounter<{\n outcome: 'accepted' | 'rejected';\n}>('runners_runner_bootstrap_exchange', {\n description: 'Runner bootstrap-token exchanges by outcome',\n});\n\nexport const runnerControlHeartbeatCount = meter.createCounter<Record<string, never>>(\n 'runners_runner_control_heartbeat',\n {description: 'Pre-workspace runner-control heartbeats accepted'},\n);\n\nexport const providerRunnerReapedCount = meter.createCounter<Record<string, never>>(\n 'runners_provider_runner_reaped',\n {\n description: 'Stale provisioned runners marked failed by backend maintenance',\n },\n);\n\nexport const providerRunnerCountDivergenceCount = meter.createCounter<{\n template_key?: string;\n state: 'starting' | 'running';\n direction: 'backend-higher' | 'advertised-higher';\n}>('runners_provider_runner_count_divergence', {\n description:\n 'Absolute difference between provisioner-advertised and backend-observed provisioned runner counts',\n});\n\nexport const providerRunnerReconcileCallCount = meter.createCounter<Record<string, never>>(\n 'runners_provider_runner_reconcile_called',\n {description: 'Provisioned runner reconcile calls completed successfully'},\n);\n\nexport const providerRunnerAbsentTerminatedCount = meter.createCounter<Record<string, never>>(\n 'runners_provider_runner_absent_terminated',\n {\n description:\n 'Owned provisioned runners marked terminated because they were absent from reconcile',\n },\n);\n\nexport const providerRunnerTerminateIntentIssuedCount = meter.createCounter<{\n surface: 'poll-demand' | 'reconcile';\n reason: 'job-cancelled' | 'terminal-state';\n}>('runners_provider_runner_terminate_intent_issued', {\n description: 'Provisioned runner terminate intents returned to provisioners',\n});\n\nexport const providerRunnerTerminateIntentHonoredCount = meter.createCounter<{\n reason: 'job-cancelled';\n}>('runners_provider_runner_terminate_intent_honored', {\n description: 'Provisioned runner terminate intents honored by first transition to terminated',\n});\n\nexport const reservationReleasedCount = meter.createCounter<Record<string, never>>(\n 'runners_reservation_released',\n {description: 'Reservation units released from terminal provisioned runner reports'},\n);\n\nexport type RunnerReservationPromotionFailureReason =\n | 'reservation-expired'\n | 'reservation-not-found'\n | 'already-assigned'\n | 'not-assignable';\n\nexport const runnerReservationPromotionFailureCount = meter.createCounter<{\n reason: RunnerReservationPromotionFailureReason;\n}>('runners_reservation_promotion_failures', {\n description: 'Runner reservation promotion failures during enrollment by reason',\n});\n\nexport type RunnersRateLimitAction = 'provisioner-mint' | 'ephemeral-register';\nexport type RunnersRateLimitScope = 'provisioner' | 'ephemeral-token';\nexport type RunnersRateLimitOutcome = 'allowed' | 'blocked' | 'unavailable';\n\nconst rateLimitCheckCount = meter.createCounter<{\n action: RunnersRateLimitAction;\n scope: RunnersRateLimitScope;\n outcome: RunnersRateLimitOutcome;\n}>('runners_rate_limit_checks', {\n description: 'Runners rate limit checks by action, scope, and outcome',\n});\n\nconst rateLimitPruneFailureCount = meter.createCounter('runners_rate_limit_prune_failures', {\n description: 'Runners rate limit prune failures',\n});\n\nfunction recordMetric(record: () => void): void {\n try {\n record();\n } catch {\n // Metrics must not affect runner or provisioner request outcomes.\n }\n}\n\nexport function recordRunnerReservationPromotionFailure(\n reason: RunnerReservationPromotionFailureReason,\n): void {\n recordMetric(() => runnerReservationPromotionFailureCount.add(1, {reason}));\n}\n\nexport function recordRunnersRateLimitCheck(params: {\n action: RunnersRateLimitAction;\n scope: RunnersRateLimitScope;\n outcome: RunnersRateLimitOutcome;\n}): void {\n recordMetric(() =>\n rateLimitCheckCount.add(1, {\n action: params.action,\n scope: params.scope,\n outcome: params.outcome,\n }),\n );\n}\n\nexport function recordRunnersRateLimitPruneFailure(): void {\n recordMetric(() => rateLimitPruneFailureCount.add(1));\n}\n"],"names":["instanceMetrics","meter","getMeter","jobExecutionEnqueuedCount","createCounter","description","jobExecutionClaimedCount","jobExecutionLeaseExpiredCount","providerRunnerReportCount","runnerBootstrapExchangeCount","runnerControlHeartbeatCount","providerRunnerReapedCount","providerRunnerCountDivergenceCount","providerRunnerReconcileCallCount","providerRunnerAbsentTerminatedCount","providerRunnerTerminateIntentIssuedCount","providerRunnerTerminateIntentHonoredCount","reservationReleasedCount","runnerReservationPromotionFailureCount","rateLimitCheckCount","rateLimitPruneFailureCount","recordMetric","record","recordRunnerReservationPromotionFailure","reason","add","recordRunnersRateLimitCheck","params","action","scope","outcome","recordRunnersRateLimitPruneFailure"],"mappings":"AAAA,SAAQA,eAAe,QAAO,8BAA8B;AAE5D,MAAMC,QAAQD,gBAAgBE,QAAQ,CAAC;AAEvC,OAAO,MAAMC,4BAA4BF,MAAMG,aAAa,CAC1D,kCACA;IACEC,aAAa;AACf,GACA;AAEF,OAAO,MAAMC,2BAA2BL,MAAMG,aAAa,CACzD,iCACA;IAACC,aAAa;AAAyC,GACvD;AAEF,OAAO,MAAME,gCAAgCN,MAAMG,aAAa,CAC9D,uCACA;IAACC,aAAa;AAAmE,GACjF;AAEF,OAAO,MAAMG,4BAA4BP,MAAMG,aAAa,CAEzD,oCAAoC;IACrCC,aAAa;AACf,GAAG;AAEH,OAAO,MAAMI,+BAA+BR,MAAMG,aAAa,CAE5D,qCAAqC;IACtCC,aAAa;AACf,GAAG;AAEH,OAAO,MAAMK,8BAA8BT,MAAMG,aAAa,CAC5D,oCACA;IAACC,aAAa;AAAkD,GAChE;AAEF,OAAO,MAAMM,4BAA4BV,MAAMG,aAAa,CAC1D,kCACA;IACEC,aAAa;AACf,GACA;AAEF,OAAO,MAAMO,qCAAqCX,MAAMG,aAAa,CAIlE,4CAA4C;IAC7CC,aACE;AACJ,GAAG;AAEH,OAAO,MAAMQ,mCAAmCZ,MAAMG,aAAa,CACjE,4CACA;IAACC,aAAa;AAA2D,GACzE;AAEF,OAAO,MAAMS,sCAAsCb,MAAMG,aAAa,CACpE,6CACA;IACEC,aACE;AACJ,GACA;AAEF,OAAO,MAAMU,2CAA2Cd,MAAMG,aAAa,CAGxE,mDAAmD;IACpDC,aAAa;AACf,GAAG;AAEH,OAAO,MAAMW,4CAA4Cf,MAAMG,aAAa,CAEzE,oDAAoD;IACrDC,aAAa;AACf,GAAG;AAEH,OAAO,MAAMY,2BAA2BhB,MAAMG,aAAa,CACzD,gCACA;IAACC,aAAa;AAAqE,GACnF;AAQF,OAAO,MAAMa,yCAAyCjB,MAAMG,aAAa,CAEtE,0CAA0C;IAC3CC,aAAa;AACf,GAAG;AAMH,MAAMc,sBAAsBlB,MAAMG,aAAa,CAI5C,6BAA6B;IAC9BC,aAAa;AACf;AAEA,MAAMe,6BAA6BnB,MAAMG,aAAa,CAAC,qCAAqC;IAC1FC,aAAa;AACf;AAEA,SAASgB,aAAaC,MAAkB;IACtC,IAAI;QACFA;IACF,EAAE,OAAM;IACN,kEAAkE;IACpE;AACF;AAEA,OAAO,SAASC,wCACdC,MAA+C;IAE/CH,aAAa,IAAMH,uCAAuCO,GAAG,CAAC,GAAG;YAACD;QAAM;AAC1E;AAEA,OAAO,SAASE,4BAA4BC,MAI3C;IACCN,aAAa,IACXF,oBAAoBM,GAAG,CAAC,GAAG;YACzBG,QAAQD,OAAOC,MAAM;YACrBC,OAAOF,OAAOE,KAAK;YACnBC,SAASH,OAAOG,OAAO;QACzB;AAEJ;AAEA,OAAO,SAASC;IACdV,aAAa,IAAMD,2BAA2BK,GAAG,CAAC;AACpD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/metrics/service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/metrics/service.ts"],"names":[],"mappings":"AAKA,wBAAgB,6BAA6B,IAAI,IAAI,CAoCpD"}
|
package/dist/metrics/service.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { getServiceMetricsProvider } from '@shipfox/node-opentelemetry';
|
|
2
|
+
import { config } from '#config.js';
|
|
2
3
|
import { getJobExecutionQueueDepth } from '#db/job-executions.js';
|
|
4
|
+
import { countStaleEnrolledRunnerInstances } from '#db/runner-instances.js';
|
|
3
5
|
export function registerRunnersServiceMetrics() {
|
|
4
6
|
const meter = getServiceMetricsProvider().getMeter('runners');
|
|
5
7
|
const pendingJobExecutions = meter.createObservableGauge('runners_pending_job_executions', {
|
|
@@ -8,13 +10,27 @@ export function registerRunnersServiceMetrics() {
|
|
|
8
10
|
const runningJobExecutions = meter.createObservableGauge('runners_running_job_executions', {
|
|
9
11
|
description: 'Job executions currently claimed by a runner and in progress'
|
|
10
12
|
});
|
|
13
|
+
const enrolledRunnersWithoutRecentReport = meter.createObservableGauge('runners_enrolled_without_recent_report', {
|
|
14
|
+
description: 'Running enrolled runners with a live control session, no workspace or runner session, and no recent provisioner report after the stale-runner grace window'
|
|
15
|
+
});
|
|
11
16
|
meter.addBatchObservableCallback(async (observer)=>{
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
const [depthResult, staleEnrolledRunnerCountResult] = await Promise.allSettled([
|
|
18
|
+
getJobExecutionQueueDepth(),
|
|
19
|
+
countStaleEnrolledRunnerInstances({
|
|
20
|
+
graceSeconds: config.RUNNER_STALE_PROVISIONED_RUNNER_THRESHOLD_SECONDS
|
|
21
|
+
})
|
|
22
|
+
]);
|
|
23
|
+
if (depthResult.status === 'fulfilled') {
|
|
24
|
+
observer.observe(pendingJobExecutions, depthResult.value.pendingJobExecutions);
|
|
25
|
+
observer.observe(runningJobExecutions, depthResult.value.runningJobExecutions);
|
|
26
|
+
}
|
|
27
|
+
if (staleEnrolledRunnerCountResult.status === 'fulfilled') {
|
|
28
|
+
observer.observe(enrolledRunnersWithoutRecentReport, staleEnrolledRunnerCountResult.value);
|
|
29
|
+
}
|
|
15
30
|
}, [
|
|
16
31
|
pendingJobExecutions,
|
|
17
|
-
runningJobExecutions
|
|
32
|
+
runningJobExecutions,
|
|
33
|
+
enrolledRunnersWithoutRecentReport
|
|
18
34
|
]);
|
|
19
35
|
}
|
|
20
36
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/metrics/service.ts"],"sourcesContent":["import {getServiceMetricsProvider} from '@shipfox/node-opentelemetry';\nimport {getJobExecutionQueueDepth} from '#db/job-executions.js';\n\nexport function registerRunnersServiceMetrics(): void {\n const meter = getServiceMetricsProvider().getMeter('runners');\n\n const pendingJobExecutions = meter.createObservableGauge('runners_pending_job_executions', {\n description: 'Job executions currently waiting in the queue to be claimed',\n });\n const runningJobExecutions = meter.createObservableGauge('runners_running_job_executions', {\n description: 'Job executions currently claimed by a runner and in progress',\n });\n\n meter.addBatchObservableCallback(\n async (observer) => {\n const
|
|
1
|
+
{"version":3,"sources":["../../src/metrics/service.ts"],"sourcesContent":["import {getServiceMetricsProvider} from '@shipfox/node-opentelemetry';\nimport {config} from '#config.js';\nimport {getJobExecutionQueueDepth} from '#db/job-executions.js';\nimport {countStaleEnrolledRunnerInstances} from '#db/runner-instances.js';\n\nexport function registerRunnersServiceMetrics(): void {\n const meter = getServiceMetricsProvider().getMeter('runners');\n\n const pendingJobExecutions = meter.createObservableGauge('runners_pending_job_executions', {\n description: 'Job executions currently waiting in the queue to be claimed',\n });\n const runningJobExecutions = meter.createObservableGauge('runners_running_job_executions', {\n description: 'Job executions currently claimed by a runner and in progress',\n });\n const enrolledRunnersWithoutRecentReport = meter.createObservableGauge(\n 'runners_enrolled_without_recent_report',\n {\n description:\n 'Running enrolled runners with a live control session, no workspace or runner session, and no recent provisioner report after the stale-runner grace window',\n },\n );\n\n meter.addBatchObservableCallback(\n async (observer) => {\n const [depthResult, staleEnrolledRunnerCountResult] = await Promise.allSettled([\n getJobExecutionQueueDepth(),\n countStaleEnrolledRunnerInstances({\n graceSeconds: config.RUNNER_STALE_PROVISIONED_RUNNER_THRESHOLD_SECONDS,\n }),\n ]);\n\n if (depthResult.status === 'fulfilled') {\n observer.observe(pendingJobExecutions, depthResult.value.pendingJobExecutions);\n observer.observe(runningJobExecutions, depthResult.value.runningJobExecutions);\n }\n if (staleEnrolledRunnerCountResult.status === 'fulfilled') {\n observer.observe(enrolledRunnersWithoutRecentReport, staleEnrolledRunnerCountResult.value);\n }\n },\n [pendingJobExecutions, runningJobExecutions, enrolledRunnersWithoutRecentReport],\n );\n}\n"],"names":["getServiceMetricsProvider","config","getJobExecutionQueueDepth","countStaleEnrolledRunnerInstances","registerRunnersServiceMetrics","meter","getMeter","pendingJobExecutions","createObservableGauge","description","runningJobExecutions","enrolledRunnersWithoutRecentReport","addBatchObservableCallback","observer","depthResult","staleEnrolledRunnerCountResult","Promise","allSettled","graceSeconds","RUNNER_STALE_PROVISIONED_RUNNER_THRESHOLD_SECONDS","status","observe","value"],"mappings":"AAAA,SAAQA,yBAAyB,QAAO,8BAA8B;AACtE,SAAQC,MAAM,QAAO,aAAa;AAClC,SAAQC,yBAAyB,QAAO,wBAAwB;AAChE,SAAQC,iCAAiC,QAAO,0BAA0B;AAE1E,OAAO,SAASC;IACd,MAAMC,QAAQL,4BAA4BM,QAAQ,CAAC;IAEnD,MAAMC,uBAAuBF,MAAMG,qBAAqB,CAAC,kCAAkC;QACzFC,aAAa;IACf;IACA,MAAMC,uBAAuBL,MAAMG,qBAAqB,CAAC,kCAAkC;QACzFC,aAAa;IACf;IACA,MAAME,qCAAqCN,MAAMG,qBAAqB,CACpE,0CACA;QACEC,aACE;IACJ;IAGFJ,MAAMO,0BAA0B,CAC9B,OAAOC;QACL,MAAM,CAACC,aAAaC,+BAA+B,GAAG,MAAMC,QAAQC,UAAU,CAAC;YAC7Ef;YACAC,kCAAkC;gBAChCe,cAAcjB,OAAOkB,iDAAiD;YACxE;SACD;QAED,IAAIL,YAAYM,MAAM,KAAK,aAAa;YACtCP,SAASQ,OAAO,CAACd,sBAAsBO,YAAYQ,KAAK,CAACf,oBAAoB;YAC7EM,SAASQ,OAAO,CAACX,sBAAsBI,YAAYQ,KAAK,CAACZ,oBAAoB;QAC/E;QACA,IAAIK,+BAA+BK,MAAM,KAAK,aAAa;YACzDP,SAASQ,OAAO,CAACV,oCAAoCI,+BAA+BO,KAAK;QAC3F;IACF,GACA;QAACf;QAAsBG;QAAsBC;KAAmC;AAEpF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ProvisionerToken } from '#core/entities/provisioner-token.js';
|
|
2
2
|
export declare function toAdministratorProvisionerTokenDto(token: ProvisionerToken): {
|
|
3
3
|
id: string;
|
|
4
|
-
scope:
|
|
4
|
+
scope: 'installation';
|
|
5
5
|
prefix: string;
|
|
6
6
|
name: string | null;
|
|
7
7
|
status: import("#core/provisioner-tokens.js").InstallationProvisionerTokenStatus;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin-provisioner-token.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/admin-provisioner-token.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,qCAAqC,CAAC;AAG1E,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,gBAAgB
|
|
1
|
+
{"version":3,"file":"admin-provisioner-token.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/admin-provisioner-token.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,qCAAqC,CAAC;AAG1E,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,gBAAgB;IAMtE,EAAE;IACF,KAAK,EAAE,cAAc;IACrB,MAAM;IACN,IAAI;IACJ,MAAM;IACN,kBAAkB;IAClB,kBAAkB;IAClB,UAAU;IACV,UAAU;IACV,YAAY;IACZ,UAAU;IACV,UAAU;EAEb"}
|
|
@@ -4,7 +4,7 @@ export declare function toRunnerAdministratorInstanceDto(runner: RunnerAdministr
|
|
|
4
4
|
lifecycle_state: import("#core/admin-runner-instances.js").RunnerAdministratorLifecycleState;
|
|
5
5
|
compute_state: import("../../core/index.js").RunnerInstanceState;
|
|
6
6
|
enrollment_state: import("#core/admin-runner-instances.js").RunnerAdministratorEnrollmentState;
|
|
7
|
-
assignment_presence: "
|
|
7
|
+
assignment_presence: "assigned" | "unassigned";
|
|
8
8
|
assigned_workspace: {
|
|
9
9
|
id: string;
|
|
10
10
|
} | null;
|
|
@@ -15,7 +15,7 @@ export declare function toRunnerAdministratorInstanceDto(runner: RunnerAdministr
|
|
|
15
15
|
closed_at: string | null;
|
|
16
16
|
provisioner: {
|
|
17
17
|
id: string;
|
|
18
|
-
scope:
|
|
18
|
+
scope: 'installation';
|
|
19
19
|
name: string | null;
|
|
20
20
|
};
|
|
21
21
|
reconciliation_status: import("#core/admin-runner-instances.js").RunnerAdministratorReconciliationStatus;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin-runner-instances.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/admin-runner-instances.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,iCAAiC,CAAC;AAEjF,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,2BAA2B
|
|
1
|
+
{"version":3,"file":"admin-runner-instances.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/admin-runner-instances.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,iCAAiC,CAAC;AAEjF,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,2BAA2B;IAEhF,EAAE;IACF,eAAe;IACf,aAAa;IACb,gBAAgB;IAChB,mBAAmB;IACnB,kBAAkB;;;IAClB,MAAM;IACN,UAAU;IACV,iBAAiB;IACjB,cAAc;IACd,SAAS;IACT,WAAW;;;;;IACX,qBAAqB;EAExB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poll-demand.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/poll-demand.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"poll-demand.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/poll-demand.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAC,0BAA0B,EAAC,MAAM,+BAA+B,CAAC;AAsB9E,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,0BAA+B,mDAgG7E;AAED,eAAO,MAAM,eAAe,iDAA0B,CAAC"}
|
|
@@ -5,14 +5,19 @@ import { ClientError, defineRoute } from '@shipfox/node-fastify';
|
|
|
5
5
|
import { logger } from '@shipfox/node-opentelemetry';
|
|
6
6
|
import { config } from '#config.js';
|
|
7
7
|
import { pollDemand, releaseReservationGrants } from '#core/demand.js';
|
|
8
|
+
import { sanitizeRunnerLabels } from '#core/runner-labels.js';
|
|
8
9
|
import { publishWorkspaceProvisionerCapabilitySnapshot } from '#db/provisioner-capability-snapshots.js';
|
|
9
10
|
import { listQueuedDemandWorkspaceIds, pollInstallationDemandAndReserve } from '#db/reservations.js';
|
|
10
11
|
import { toPollDemandResponseDto } from '#presentation/dto/index.js';
|
|
11
12
|
const TERMINATE_INTENT_LIMIT = 1000;
|
|
12
|
-
function toReservationTemplates(templates) {
|
|
13
|
+
function toReservationTemplates(templates, scope) {
|
|
13
14
|
return templates.map((template)=>({
|
|
14
15
|
templateKey: template.template_key,
|
|
15
|
-
labels: template.labels,
|
|
16
|
+
labels: sanitizeRunnerLabels(template.labels, {
|
|
17
|
+
scope,
|
|
18
|
+
logLevel: 'debug',
|
|
19
|
+
source: 'provisioner template advertisement'
|
|
20
|
+
}),
|
|
16
21
|
availableSlots: template.available_slots,
|
|
17
22
|
starting: template.starting,
|
|
18
23
|
running: template.running
|
|
@@ -55,6 +60,7 @@ export function createPollDemandRoute(options = {}) {
|
|
|
55
60
|
}
|
|
56
61
|
});
|
|
57
62
|
const provisionerContext = requireProvisionerContext(request);
|
|
63
|
+
const ttlSeconds = Math.min(request.body.reservation_ttl_seconds ?? config.RESERVATION_TTL_SECONDS, config.RESERVATION_TTL_MAX_SECONDS);
|
|
58
64
|
if (provisionerContext.scope === 'installation') {
|
|
59
65
|
if (!options.installationProvisioning) {
|
|
60
66
|
throw new ClientError('Installation provisioner credentials are not accepted on this host', 'forbidden', {
|
|
@@ -63,11 +69,11 @@ export function createPollDemandRoute(options = {}) {
|
|
|
63
69
|
}
|
|
64
70
|
const candidateWorkspaceIds = await listQueuedDemandWorkspaceIds();
|
|
65
71
|
const eligibleWorkspaceIds = await options.installationProvisioning.policy.filterEligibleWorkspaceIds(candidateWorkspaceIds);
|
|
66
|
-
const templates = toReservationTemplates(request.body.templates);
|
|
72
|
+
const templates = toReservationTemplates(request.body.templates, 'installation');
|
|
67
73
|
const result = await pollInstallationDemandAndReserve({
|
|
68
74
|
provisionerId: provisionerContext.provisionerTokenId,
|
|
69
75
|
maxReservations: request.body.max_reservations,
|
|
70
|
-
ttlSeconds
|
|
76
|
+
ttlSeconds,
|
|
71
77
|
templates,
|
|
72
78
|
capabilityWindowSeconds: config.PROVISIONER_ACTIVE_WINDOW_SECONDS,
|
|
73
79
|
eligibleWorkspaceIds,
|
|
@@ -82,7 +88,7 @@ export function createPollDemandRoute(options = {}) {
|
|
|
82
88
|
});
|
|
83
89
|
}
|
|
84
90
|
const { provisionerTokenId, workspaceId } = requireWorkspaceProvisionerContext(request);
|
|
85
|
-
const templates = toReservationTemplates(request.body.templates);
|
|
91
|
+
const templates = toReservationTemplates(request.body.templates, 'workspace');
|
|
86
92
|
await publishWorkspaceProvisionerCapabilitySnapshot({
|
|
87
93
|
workspaceId,
|
|
88
94
|
provisionerId: provisionerTokenId,
|
|
@@ -93,7 +99,7 @@ export function createPollDemandRoute(options = {}) {
|
|
|
93
99
|
provisionerId: provisionerTokenId,
|
|
94
100
|
maxReservations: request.body.max_reservations,
|
|
95
101
|
waitSeconds: request.body.wait_seconds,
|
|
96
|
-
ttlSeconds
|
|
102
|
+
ttlSeconds,
|
|
97
103
|
terminateIntentLimit: TERMINATE_INTENT_LIMIT,
|
|
98
104
|
templates,
|
|
99
105
|
signal: abortController.signal
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/presentation/routes/poll-demand.ts"],"sourcesContent":["import {\n requireProvisionerContext,\n requireWorkspaceProvisionerContext,\n} from '@shipfox/api-auth-context';\nimport type {PollDemandTemplateDto} from '@shipfox/api-runners-dto';\nimport {pollDemandBodySchema, pollDemandResponseSchema} from '@shipfox/api-runners-dto';\nimport {reportError} from '@shipfox/node-error-monitoring';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport {config} from '#config.js';\nimport {pollDemand, releaseReservationGrants} from '#core/demand.js';\nimport {publishWorkspaceProvisionerCapabilitySnapshot} from '#db/provisioner-capability-snapshots.js';\nimport {\n listQueuedDemandWorkspaceIds,\n pollInstallationDemandAndReserve,\n type ReservationGrant,\n type ReservationTemplate,\n} from '#db/reservations.js';\nimport type {CreateRunnersModuleOptions} from '#installation-provisioning.js';\nimport {toPollDemandResponseDto} from '#presentation/dto/index.js';\n\nconst TERMINATE_INTENT_LIMIT = 1000;\n\nfunction toReservationTemplates(templates: PollDemandTemplateDto[]): ReservationTemplate[] {\n return templates.map((template) => ({\n templateKey: template.template_key,\n labels: template.labels,\n availableSlots: template.available_slots,\n starting: template.starting,\n running: template.running,\n }));\n}\n\nexport function createPollDemandRoute(options: CreateRunnersModuleOptions = {}) {\n return defineRoute({\n method: 'POST',\n path: '/demand/poll',\n description: 'Poll aggregate runner demand and reserve capacity for a provisioner',\n schema: {\n body: pollDemandBodySchema,\n response: {\n 200: pollDemandResponseSchema,\n },\n },\n handler: async (request, reply) => {\n const abortController = new AbortController();\n let responseFinished = false;\n let responseReservations: ReservationGrant[] = [];\n reply.raw.on('finish', () => {\n responseFinished = true;\n });\n reply.raw.on('close', () => {\n if (!responseFinished) {\n abortController.abort();\n void releaseReservationGrants(responseReservations).catch((error) => {\n logger().error(\n {err: error, reservationCount: responseReservations.length},\n 'Failed to release reservations after provisioner disconnect',\n );\n reportError(error, {\n boundary: 'runners.cleanup',\n operation: 'release-disconnected-reservations',\n extra: {reservationCount: responseReservations.length},\n });\n });\n }\n });\n const provisionerContext = requireProvisionerContext(request);\n if (provisionerContext.scope === 'installation') {\n if (!options.installationProvisioning) {\n throw new ClientError(\n 'Installation provisioner credentials are not accepted on this host',\n 'forbidden',\n {\n status: 403,\n },\n );\n }\n const candidateWorkspaceIds = await listQueuedDemandWorkspaceIds();\n const eligibleWorkspaceIds =\n await options.installationProvisioning.policy.filterEligibleWorkspaceIds(\n candidateWorkspaceIds,\n );\n const templates = toReservationTemplates(request.body.templates);\n const result = await pollInstallationDemandAndReserve({\n provisionerId: provisionerContext.provisionerTokenId,\n maxReservations: request.body.max_reservations,\n ttlSeconds
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/routes/poll-demand.ts"],"sourcesContent":["import {\n requireProvisionerContext,\n requireWorkspaceProvisionerContext,\n} from '@shipfox/api-auth-context';\nimport type {PollDemandTemplateDto} from '@shipfox/api-runners-dto';\nimport {pollDemandBodySchema, pollDemandResponseSchema} from '@shipfox/api-runners-dto';\nimport {reportError} from '@shipfox/node-error-monitoring';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport {config} from '#config.js';\nimport {pollDemand, releaseReservationGrants} from '#core/demand.js';\nimport {sanitizeRunnerLabels} from '#core/runner-labels.js';\nimport {publishWorkspaceProvisionerCapabilitySnapshot} from '#db/provisioner-capability-snapshots.js';\nimport {\n listQueuedDemandWorkspaceIds,\n pollInstallationDemandAndReserve,\n type ReservationGrant,\n type ReservationTemplate,\n} from '#db/reservations.js';\nimport type {CreateRunnersModuleOptions} from '#installation-provisioning.js';\nimport {toPollDemandResponseDto} from '#presentation/dto/index.js';\n\nconst TERMINATE_INTENT_LIMIT = 1000;\n\nfunction toReservationTemplates(\n templates: PollDemandTemplateDto[],\n scope: 'installation' | 'workspace',\n): ReservationTemplate[] {\n return templates.map((template) => ({\n templateKey: template.template_key,\n labels: sanitizeRunnerLabels(template.labels, {\n scope,\n logLevel: 'debug',\n source: 'provisioner template advertisement',\n }),\n availableSlots: template.available_slots,\n starting: template.starting,\n running: template.running,\n }));\n}\n\nexport function createPollDemandRoute(options: CreateRunnersModuleOptions = {}) {\n return defineRoute({\n method: 'POST',\n path: '/demand/poll',\n description: 'Poll aggregate runner demand and reserve capacity for a provisioner',\n schema: {\n body: pollDemandBodySchema,\n response: {\n 200: pollDemandResponseSchema,\n },\n },\n handler: async (request, reply) => {\n const abortController = new AbortController();\n let responseFinished = false;\n let responseReservations: ReservationGrant[] = [];\n reply.raw.on('finish', () => {\n responseFinished = true;\n });\n reply.raw.on('close', () => {\n if (!responseFinished) {\n abortController.abort();\n void releaseReservationGrants(responseReservations).catch((error) => {\n logger().error(\n {err: error, reservationCount: responseReservations.length},\n 'Failed to release reservations after provisioner disconnect',\n );\n reportError(error, {\n boundary: 'runners.cleanup',\n operation: 'release-disconnected-reservations',\n extra: {reservationCount: responseReservations.length},\n });\n });\n }\n });\n const provisionerContext = requireProvisionerContext(request);\n const ttlSeconds = Math.min(\n request.body.reservation_ttl_seconds ?? config.RESERVATION_TTL_SECONDS,\n config.RESERVATION_TTL_MAX_SECONDS,\n );\n if (provisionerContext.scope === 'installation') {\n if (!options.installationProvisioning) {\n throw new ClientError(\n 'Installation provisioner credentials are not accepted on this host',\n 'forbidden',\n {\n status: 403,\n },\n );\n }\n const candidateWorkspaceIds = await listQueuedDemandWorkspaceIds();\n const eligibleWorkspaceIds =\n await options.installationProvisioning.policy.filterEligibleWorkspaceIds(\n candidateWorkspaceIds,\n );\n const templates = toReservationTemplates(request.body.templates, 'installation');\n const result = await pollInstallationDemandAndReserve({\n provisionerId: provisionerContext.provisionerTokenId,\n maxReservations: request.body.max_reservations,\n ttlSeconds,\n templates,\n capabilityWindowSeconds: config.PROVISIONER_ACTIVE_WINDOW_SECONDS,\n eligibleWorkspaceIds,\n signal: abortController.signal,\n onReservations: (reservations) => {\n responseReservations.push(...reservations);\n },\n });\n return toPollDemandResponseDto({\n ...result,\n terminateRunnerInstanceIds: [],\n });\n }\n const {provisionerTokenId, workspaceId} = requireWorkspaceProvisionerContext(request);\n\n const templates = toReservationTemplates(request.body.templates, 'workspace');\n await publishWorkspaceProvisionerCapabilitySnapshot({\n workspaceId,\n provisionerId: provisionerTokenId,\n templates,\n });\n\n const result = await pollDemand({\n workspaceId,\n provisionerId: provisionerTokenId,\n maxReservations: request.body.max_reservations,\n waitSeconds: request.body.wait_seconds,\n ttlSeconds,\n terminateIntentLimit: TERMINATE_INTENT_LIMIT,\n templates,\n signal: abortController.signal,\n });\n responseReservations = result.reservations;\n\n return toPollDemandResponseDto(result);\n },\n });\n}\n\nexport const pollDemandRoute = createPollDemandRoute();\n"],"names":["requireProvisionerContext","requireWorkspaceProvisionerContext","pollDemandBodySchema","pollDemandResponseSchema","reportError","ClientError","defineRoute","logger","config","pollDemand","releaseReservationGrants","sanitizeRunnerLabels","publishWorkspaceProvisionerCapabilitySnapshot","listQueuedDemandWorkspaceIds","pollInstallationDemandAndReserve","toPollDemandResponseDto","TERMINATE_INTENT_LIMIT","toReservationTemplates","templates","scope","map","template","templateKey","template_key","labels","logLevel","source","availableSlots","available_slots","starting","running","createPollDemandRoute","options","method","path","description","schema","body","response","handler","request","reply","abortController","AbortController","responseFinished","responseReservations","raw","on","abort","catch","error","err","reservationCount","length","boundary","operation","extra","provisionerContext","ttlSeconds","Math","min","reservation_ttl_seconds","RESERVATION_TTL_SECONDS","RESERVATION_TTL_MAX_SECONDS","installationProvisioning","status","candidateWorkspaceIds","eligibleWorkspaceIds","policy","filterEligibleWorkspaceIds","result","provisionerId","provisionerTokenId","maxReservations","max_reservations","capabilityWindowSeconds","PROVISIONER_ACTIVE_WINDOW_SECONDS","signal","onReservations","reservations","push","terminateRunnerInstanceIds","workspaceId","waitSeconds","wait_seconds","terminateIntentLimit","pollDemandRoute"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/rate-limit.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,YAAY,EAAE,KAAK,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAoD1F,wBAAgB,wCAAwC,
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/rate-limit.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,YAAY,EAAE,KAAK,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAoD1F,wBAAgB,wCAAwC,cAC/B,cAAc,SAAS,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CAY3E;AAED,wBAAgB,0CAA0C,cACjC,cAAc,SAAS,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CAc3E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/register.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/register.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,oCAAoC,CAAC;AAa9E,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,qBAAqB,mDAwE9D"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { registerRunnerBodySchema, registerRunnerResponseSchema } from '@shipfox/api-runners-dto';
|
|
2
2
|
import { ClientError, defineRoute } from '@shipfox/node-fastify';
|
|
3
|
-
import { EmptyRunnerLabelsError, RegistrationTokenConsumedError, RegistrationTokenExpiredError } from '#core/errors.js';
|
|
3
|
+
import { EmptyRunnerLabelsError, RegistrationTokenConsumedError, RegistrationTokenExpiredError, RunnerLabelsReservedError } from '#core/errors.js';
|
|
4
4
|
import { registerRunnerSession } from '#core/runner-sessions.js';
|
|
5
5
|
import { getRunnerContext } from '#presentation/auth/index.js';
|
|
6
6
|
import { createEphemeralRegisterRateLimitPreHandler } from './rate-limit.js';
|
|
@@ -17,6 +17,14 @@ export function createRegisterRoute(auth) {
|
|
|
17
17
|
},
|
|
18
18
|
preHandler: createEphemeralRegisterRateLimitPreHandler(),
|
|
19
19
|
errorHandler: (error, request)=>{
|
|
20
|
+
if (error instanceof RunnerLabelsReservedError) {
|
|
21
|
+
throw new ClientError(error.message, 'runner-labels-reserved', {
|
|
22
|
+
details: {
|
|
23
|
+
labels: error.labels
|
|
24
|
+
},
|
|
25
|
+
status: 400
|
|
26
|
+
});
|
|
27
|
+
}
|
|
20
28
|
if (error instanceof EmptyRunnerLabelsError) {
|
|
21
29
|
throw new ClientError(error.message, 'empty-runner-labels', {
|
|
22
30
|
status: 400
|