@shipfox/api-runners 7.0.2 → 7.1.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.
@@ -1,21 +1,19 @@
1
1
  $ shipfox-swc && shipfox-temporal-bundle dist/temporal/workflows/index.js
2
- Successfully compiled: 94 files with swc (349.8ms)
3
- 2026-07-22T08:48:42.723Z [INFO] asset workflow-bundle-f2e085cb6b2d30f8e259.js 1.45 MiB [emitted] [immutable] (name: main)
4
- runtime modules 670 bytes 3 modules
5
- modules by path ../../../node_modules/.pnpm/ 424 KiB
6
- modules by path ../../../node_modules/.pnpm/@temporalio+common@1.18.1/node_modules/@temporal...(truncated) 155 KiB 34 modules
7
- modules by path ../../../node_modules/.pnpm/@temporalio+workflow@1.18.1/node_modules/@tempor...(truncated) 201 KiB 26 modules
8
- modules by path ../../../node_modules/.pnpm/nexus-rpc@0.0.2/node_modules/nexus-rpc/lib/ 22.3 KiB 13 modules
9
- + 2 modules
10
- modules by path ./dist/ 2.91 KiB
2
+ Successfully compiled: 94 files with swc (690.58ms)
3
+ 2026-07-22T13:11:53.643Z [INFO] asset workflow-bundle-0c3da2487e29e352d64e.js 3.17 MiB [emitted] [immutable] (name: main)
4
+ orphan modules 33.5 KiB [orphan] 21 modules
5
+ runtime modules 1.13 KiB 5 modules
6
+ modules by path ../../../node_modules/.pnpm/ 970 KiB 196 modules
7
+ modules by path ./dist/ 3.31 KiB
11
8
  modules by path ./dist/temporal/workflows/*.js 2.35 KiB
12
9
  ./dist/temporal/workflows/index.js 61 bytes [built] [code generated]
13
10
  ./dist/temporal/workflows/stuck-job-detector.js 2.29 KiB [built] [code generated]
14
- ./dist/temporal/workflows/index-autogenerated-entrypoint.cjs 526 bytes [built] [code generated]
11
+ ./dist/temporal/workflows/index-autogenerated-entrypoint.cjs 932 bytes [built] [code generated]
15
12
  ./dist/core/maintenance-policy.js 49 bytes [built] [code generated]
16
13
  optional modules 30 bytes [optional]
17
14
  __temporal_custom_payload_converter (ignored) 15 bytes [optional] [built] [code generated]
18
15
  __temporal_custom_failure_converter (ignored) 15 bytes [optional] [built] [code generated]
19
- webpack 5.107.2 compiled successfully in 1755 ms
20
- 2026-07-22T08:48:42.728Z [INFO] Workflow bundle created { size: '1.45MB' }
21
- /home/runner/work/shipfox/shipfox/libs/api/runners/dist/temporal/workflows/index.js: 1521943 bytes
16
+ ../../shared/node/temporal/dist/workflow-error-interceptor.js 1.21 KiB [built] [code generated]
17
+ webpack 5.107.2 compiled successfully in 8618 ms
18
+ 2026-07-22T13:11:53.658Z [INFO] Workflow bundle created { size: '3.17MB' }
19
+ /home/runner/work/shipfox/shipfox/libs/api/runners/dist/temporal/workflows/index.js: 3326598 bytes
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @shipfox/api-runners
2
2
 
3
+ ## 7.1.0
4
+
5
+ ### Patch Changes
6
+
7
+ - ac42c96: Adds boundary-owned reporting for unexpected API runtime failures while preserving expected client and provider outcomes.
8
+ - Updated dependencies [ac42c96]
9
+ - Updated dependencies [769d919]
10
+ - Updated dependencies [6ce08c0]
11
+ - @shipfox/node-error-monitoring@0.2.0
12
+ - @shipfox/node-fastify@0.3.0
13
+ - @shipfox/node-module@0.5.0
14
+ - @shipfox/node-temporal@0.4.0
15
+ - @shipfox/api-auth-dto@7.1.0
16
+ - @shipfox/node-opentelemetry@0.6.0
17
+ - @shipfox/api-auth-context@7.1.0
18
+
3
19
  ## 7.0.2
4
20
 
5
21
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"poll-demand.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/poll-demand.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAC,0BAA0B,EAAC,MAAM,+BAA+B,CAAC;AAe9E,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,0BAA+B,mDAkF7E;AAED,eAAO,MAAM,eAAe,iDAA0B,CAAC"}
1
+ {"version":3,"file":"poll-demand.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/poll-demand.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAC,0BAA0B,EAAC,MAAM,+BAA+B,CAAC;AAe9E,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,0BAA+B,mDA4F7E;AAED,eAAO,MAAM,eAAe,iDAA0B,CAAC"}
@@ -1,6 +1,8 @@
1
1
  import { requireProvisionerContext, requireWorkspaceProvisionerContext } from '@shipfox/api-auth-context';
2
2
  import { pollDemandBodySchema, pollDemandResponseSchema } from '@shipfox/api-runners-dto';
3
+ import { reportError } from '@shipfox/node-error-monitoring';
3
4
  import { ClientError, defineRoute } from '@shipfox/node-fastify';
5
+ import { logger } from '@shipfox/node-opentelemetry';
4
6
  import { config } from '#config.js';
5
7
  import { pollDemand, releaseReservationGrants } from '#core/demand.js';
6
8
  import { publishWorkspaceProvisionerCapabilitySnapshot } from '#db/provisioner-capability-snapshots.js';
@@ -37,7 +39,19 @@ export function createPollDemandRoute(options = {}) {
37
39
  reply.raw.on('close', ()=>{
38
40
  if (!responseFinished) {
39
41
  abortController.abort();
40
- void releaseReservationGrants(responseReservations).catch(()=>undefined);
42
+ void releaseReservationGrants(responseReservations).catch((error)=>{
43
+ logger().error({
44
+ err: error,
45
+ reservationCount: responseReservations.length
46
+ }, 'Failed to release reservations after provisioner disconnect');
47
+ reportError(error, {
48
+ boundary: 'runners.cleanup',
49
+ operation: 'release-disconnected-reservations',
50
+ extra: {
51
+ reservationCount: responseReservations.length
52
+ }
53
+ });
54
+ });
41
55
  }
42
56
  });
43
57
  const provisionerContext = requireProvisionerContext(request);
@@ -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 {ClientError, defineRoute} from '@shipfox/node-fastify';\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(() => undefined);\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: config.RESERVATION_TTL_SECONDS,\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);\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: config.RESERVATION_TTL_SECONDS,\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","ClientError","defineRoute","config","pollDemand","releaseReservationGrants","publishWorkspaceProvisionerCapabilitySnapshot","listQueuedDemandWorkspaceIds","pollInstallationDemandAndReserve","toPollDemandResponseDto","TERMINATE_INTENT_LIMIT","toReservationTemplates","templates","map","template","templateKey","template_key","labels","availableSlots","available_slots","starting","running","createPollDemandRoute","options","method","path","description","schema","body","response","handler","request","reply","abortController","AbortController","responseFinished","responseReservations","raw","on","abort","catch","undefined","provisionerContext","scope","installationProvisioning","status","candidateWorkspaceIds","eligibleWorkspaceIds","policy","filterEligibleWorkspaceIds","result","provisionerId","provisionerTokenId","maxReservations","max_reservations","ttlSeconds","RESERVATION_TTL_SECONDS","capabilityWindowSeconds","PROVISIONER_ACTIVE_WINDOW_SECONDS","signal","onReservations","reservations","push","terminateRunnerInstanceIds","workspaceId","waitSeconds","wait_seconds","terminateIntentLimit","pollDemandRoute"],"mappings":"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"}
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: config.RESERVATION_TTL_SECONDS,\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);\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: config.RESERVATION_TTL_SECONDS,\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","publishWorkspaceProvisionerCapabilitySnapshot","listQueuedDemandWorkspaceIds","pollInstallationDemandAndReserve","toPollDemandResponseDto","TERMINATE_INTENT_LIMIT","toReservationTemplates","templates","map","template","templateKey","template_key","labels","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","scope","installationProvisioning","status","candidateWorkspaceIds","eligibleWorkspaceIds","policy","filterEligibleWorkspaceIds","result","provisionerId","provisionerTokenId","maxReservations","max_reservations","ttlSeconds","RESERVATION_TTL_SECONDS","capabilityWindowSeconds","PROVISIONER_ACTIVE_WINDOW_SECONDS","signal","onReservations","reservations","push","terminateRunnerInstanceIds","workspaceId","waitSeconds","wait_seconds","terminateIntentLimit","pollDemandRoute"],"mappings":"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"}