@shipfox/api-runners 5.0.0 → 7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +6 -6
- package/CHANGELOG.md +80 -0
- package/dist/config.d.ts +5 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +54 -7
- package/dist/config.js.map +1 -1
- package/dist/core/demand.d.ts +6 -6
- package/dist/core/demand.d.ts.map +1 -1
- package/dist/core/demand.js +10 -10
- package/dist/core/demand.js.map +1 -1
- package/dist/core/entities/ephemeral-registration-token.d.ts +1 -1
- package/dist/core/entities/ephemeral-registration-token.d.ts.map +1 -1
- package/dist/core/entities/ephemeral-registration-token.js.map +1 -1
- package/dist/core/entities/provisioner-capability-snapshot.d.ts +13 -0
- package/dist/core/entities/provisioner-capability-snapshot.d.ts.map +1 -0
- package/dist/core/entities/provisioner-capability-snapshot.js +3 -0
- package/dist/core/entities/provisioner-capability-snapshot.js.map +1 -0
- package/dist/core/entities/provisioner-token.d.ts +10 -2
- package/dist/core/entities/provisioner-token.d.ts.map +1 -1
- package/dist/core/entities/provisioner-token.js.map +1 -1
- package/dist/core/entities/{provisioned-runner.d.ts → runner-instance.d.ts} +7 -6
- package/dist/core/entities/runner-instance.d.ts.map +1 -0
- package/dist/core/entities/runner-instance.js +3 -0
- package/dist/core/entities/runner-instance.js.map +1 -0
- package/dist/core/entities/runner-session.d.ts +4 -2
- package/dist/core/entities/runner-session.d.ts.map +1 -1
- package/dist/core/entities/runner-session.js.map +1 -1
- package/dist/core/ephemeral-registration-tokens.d.ts +5 -5
- package/dist/core/ephemeral-registration-tokens.d.ts.map +1 -1
- package/dist/core/ephemeral-registration-tokens.js +12 -12
- package/dist/core/ephemeral-registration-tokens.js.map +1 -1
- package/dist/core/errors.d.ts +16 -4
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +22 -4
- package/dist/core/errors.js.map +1 -1
- package/dist/core/index.d.ts +9 -5
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +6 -3
- package/dist/core/index.js.map +1 -1
- package/dist/core/job-executions.d.ts +2 -0
- package/dist/core/job-executions.d.ts.map +1 -1
- package/dist/core/job-executions.js +1 -2
- package/dist/core/job-executions.js.map +1 -1
- package/dist/core/maintenance.d.ts +1 -1
- package/dist/core/maintenance.d.ts.map +1 -1
- package/dist/core/maintenance.js +5 -5
- package/dist/core/maintenance.js.map +1 -1
- package/dist/core/provisioner-capability-snapshots.d.ts +5 -0
- package/dist/core/provisioner-capability-snapshots.d.ts.map +1 -0
- package/dist/core/provisioner-capability-snapshots.js +10 -0
- package/dist/core/provisioner-capability-snapshots.js.map +1 -0
- package/dist/core/provisioner-tokens.d.ts +10 -0
- package/dist/core/provisioner-tokens.d.ts.map +1 -1
- package/dist/core/provisioner-tokens.js +23 -1
- package/dist/core/provisioner-tokens.js.map +1 -1
- package/dist/core/rate-limit.d.ts.map +1 -1
- package/dist/core/rate-limit.js +2 -7
- package/dist/core/rate-limit.js.map +1 -1
- package/dist/core/runner-activation.d.ts +13 -0
- package/dist/core/runner-activation.d.ts.map +1 -0
- package/dist/core/runner-activation.js +36 -0
- package/dist/core/runner-activation.js.map +1 -0
- package/dist/core/runner-assignments.d.ts +6 -0
- package/dist/core/runner-assignments.d.ts.map +1 -0
- package/dist/core/runner-assignments.js +6 -0
- package/dist/core/runner-assignments.js.map +1 -0
- package/dist/core/runner-control-sessions.d.ts +46 -0
- package/dist/core/runner-control-sessions.d.ts.map +1 -0
- package/dist/core/runner-control-sessions.js +121 -0
- package/dist/core/runner-control-sessions.js.map +1 -0
- package/dist/core/runner-instances.d.ts +72 -0
- package/dist/core/runner-instances.d.ts.map +1 -0
- package/dist/core/runner-instances.js +165 -0
- package/dist/core/runner-instances.js.map +1 -0
- package/dist/core/runner-sessions.d.ts +8 -2
- package/dist/core/runner-sessions.d.ts.map +1 -1
- package/dist/core/runner-sessions.js +8 -5
- package/dist/core/runner-sessions.js.map +1 -1
- package/dist/db/db.d.ts +2698 -1054
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/db.js +9 -2
- package/dist/db/db.js.map +1 -1
- package/dist/db/ephemeral-registration-tokens.d.ts +2 -2
- package/dist/db/ephemeral-registration-tokens.d.ts.map +1 -1
- package/dist/db/ephemeral-registration-tokens.js +21 -21
- package/dist/db/ephemeral-registration-tokens.js.map +1 -1
- package/dist/db/index.d.ts +7 -4
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +5 -2
- package/dist/db/index.js.map +1 -1
- package/dist/db/job-executions.d.ts +6 -6
- package/dist/db/job-executions.d.ts.map +1 -1
- package/dist/db/job-executions.js +20 -19
- package/dist/db/job-executions.js.map +1 -1
- package/dist/db/provisioner-capability-snapshots.d.ts +21 -0
- package/dist/db/provisioner-capability-snapshots.d.ts.map +1 -0
- package/dist/db/provisioner-capability-snapshots.js +57 -0
- package/dist/db/provisioner-capability-snapshots.js.map +1 -0
- package/dist/db/provisioner-tokens.d.ts +7 -2
- package/dist/db/provisioner-tokens.d.ts.map +1 -1
- package/dist/db/provisioner-tokens.js +59 -10
- package/dist/db/provisioner-tokens.js.map +1 -1
- package/dist/db/reservations.d.ts +18 -0
- package/dist/db/reservations.d.ts.map +1 -1
- package/dist/db/reservations.js +88 -1
- package/dist/db/reservations.js.map +1 -1
- package/dist/db/runner-assignments.d.ts +7 -0
- package/dist/db/runner-assignments.d.ts.map +1 -0
- package/dist/db/runner-assignments.js +55 -0
- package/dist/db/runner-assignments.js.map +1 -0
- package/dist/db/runner-instances.d.ts +84 -0
- package/dist/db/runner-instances.d.ts.map +1 -0
- package/dist/db/runner-instances.js +497 -0
- package/dist/db/runner-instances.js.map +1 -0
- package/dist/db/runner-sessions.d.ts +5 -0
- package/dist/db/runner-sessions.d.ts.map +1 -1
- package/dist/db/runner-sessions.js +48 -2
- package/dist/db/runner-sessions.js.map +1 -1
- package/dist/db/schema/ephemeral-registration-tokens.d.ts +2 -2
- package/dist/db/schema/ephemeral-registration-tokens.js +3 -3
- package/dist/db/schema/ephemeral-registration-tokens.js.map +1 -1
- package/dist/db/schema/provisioner-capability-snapshots.d.ts +207 -0
- package/dist/db/schema/provisioner-capability-snapshots.d.ts.map +1 -0
- package/dist/db/schema/provisioner-capability-snapshots.js +38 -0
- package/dist/db/schema/provisioner-capability-snapshots.js.map +1 -0
- package/dist/db/schema/provisioner-tokens.d.ts +19 -1
- package/dist/db/schema/provisioner-tokens.d.ts.map +1 -1
- package/dist/db/schema/provisioner-tokens.js +29 -3
- package/dist/db/schema/provisioner-tokens.js.map +1 -1
- package/dist/db/schema/runner-activation-tokens.d.ts +161 -0
- package/dist/db/schema/runner-activation-tokens.d.ts.map +1 -0
- package/dist/db/schema/runner-activation-tokens.js +27 -0
- package/dist/db/schema/runner-activation-tokens.js.map +1 -0
- package/dist/db/schema/runner-control-sessions.d.ts +338 -0
- package/dist/db/schema/runner-control-sessions.d.ts.map +1 -0
- package/dist/db/schema/runner-control-sessions.js +52 -0
- package/dist/db/schema/runner-control-sessions.js.map +1 -0
- package/dist/db/schema/{provisioned-runners.d.ts → runner-instances.d.ts} +105 -34
- package/dist/db/schema/runner-instances.d.ts.map +1 -0
- package/dist/db/schema/{provisioned-runners.js → runner-instances.js} +23 -14
- package/dist/db/schema/runner-instances.js.map +1 -0
- package/dist/db/schema/runner-sessions.d.ts +39 -5
- package/dist/db/schema/runner-sessions.d.ts.map +1 -1
- package/dist/db/schema/runner-sessions.js +13 -6
- package/dist/db/schema/runner-sessions.js.map +1 -1
- package/dist/db/schema/running-job-executions.d.ts +2 -2
- package/dist/db/schema/running-job-executions.js +4 -4
- package/dist/db/schema/running-job-executions.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +45 -39
- package/dist/index.js.map +1 -1
- package/dist/installation-provisioning.d.ts +14 -0
- package/dist/installation-provisioning.d.ts.map +1 -0
- package/dist/installation-provisioning.js +7 -0
- package/dist/installation-provisioning.js.map +1 -0
- package/dist/metrics/index.d.ts +1 -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 +11 -7
- package/dist/metrics/instance.d.ts.map +1 -1
- package/dist/metrics/instance.js +13 -7
- package/dist/metrics/instance.js.map +1 -1
- package/dist/presentation/auth/index.d.ts +1 -0
- package/dist/presentation/auth/index.d.ts.map +1 -1
- package/dist/presentation/auth/index.js +1 -0
- package/dist/presentation/auth/index.js.map +1 -1
- package/dist/presentation/auth/provisioner-token-auth.d.ts.map +1 -1
- package/dist/presentation/auth/provisioner-token-auth.js +5 -1
- package/dist/presentation/auth/provisioner-token-auth.js.map +1 -1
- package/dist/presentation/auth/runner-control-session-auth.d.ts +4 -0
- package/dist/presentation/auth/runner-control-session-auth.d.ts.map +1 -0
- package/dist/presentation/auth/runner-control-session-auth.js +29 -0
- package/dist/presentation/auth/runner-control-session-auth.js.map +1 -0
- package/dist/presentation/auth/runner-registration-token-auth.d.ts +5 -1
- package/dist/presentation/auth/runner-registration-token-auth.d.ts.map +1 -1
- package/dist/presentation/auth/runner-registration-token-auth.js +21 -1
- package/dist/presentation/auth/runner-registration-token-auth.js.map +1 -1
- package/dist/presentation/dto/index.d.ts +1 -2
- package/dist/presentation/dto/index.d.ts.map +1 -1
- package/dist/presentation/dto/index.js +1 -2
- package/dist/presentation/dto/index.js.map +1 -1
- package/dist/presentation/dto/poll-demand.d.ts.map +1 -1
- package/dist/presentation/dto/poll-demand.js +7 -1
- package/dist/presentation/dto/poll-demand.js.map +1 -1
- package/dist/presentation/dto/provisioner-token.d.ts +1 -0
- package/dist/presentation/dto/provisioner-token.d.ts.map +1 -1
- package/dist/presentation/dto/provisioner-token.js +5 -1
- package/dist/presentation/dto/provisioner-token.js.map +1 -1
- package/dist/presentation/dto/{provisioned-runners.d.ts → runner-instances.d.ts} +9 -9
- package/dist/presentation/dto/runner-instances.d.ts.map +1 -0
- package/dist/presentation/dto/{provisioned-runners.js → runner-instances.js} +6 -6
- package/dist/presentation/dto/runner-instances.js.map +1 -0
- package/dist/presentation/index.d.ts +2 -2
- package/dist/presentation/index.d.ts.map +1 -1
- package/dist/presentation/index.js +2 -2
- package/dist/presentation/index.js.map +1 -1
- package/dist/presentation/inter-module.d.ts +5 -0
- package/dist/presentation/inter-module.d.ts.map +1 -0
- package/dist/presentation/inter-module.js +43 -0
- package/dist/presentation/inter-module.js.map +1 -0
- package/dist/presentation/routes/assign-runner-instances.d.ts +2 -0
- package/dist/presentation/routes/assign-runner-instances.d.ts.map +1 -0
- package/dist/presentation/routes/assign-runner-instances.js +40 -0
- package/dist/presentation/routes/assign-runner-instances.js.map +1 -0
- package/dist/presentation/routes/get-provisioner-me.d.ts.map +1 -1
- package/dist/presentation/routes/get-provisioner-me.js +5 -1
- package/dist/presentation/routes/get-provisioner-me.js.map +1 -1
- package/dist/presentation/routes/heartbeat.d.ts +2 -1
- package/dist/presentation/routes/heartbeat.d.ts.map +1 -1
- package/dist/presentation/routes/heartbeat.js +60 -50
- package/dist/presentation/routes/heartbeat.js.map +1 -1
- package/dist/presentation/routes/index.d.ts +3 -1
- package/dist/presentation/routes/index.d.ts.map +1 -1
- package/dist/presentation/routes/index.js +80 -51
- package/dist/presentation/routes/index.js.map +1 -1
- package/dist/presentation/routes/poll-demand.d.ts +2 -0
- package/dist/presentation/routes/poll-demand.d.ts.map +1 -1
- package/dist/presentation/routes/poll-demand.js +86 -45
- package/dist/presentation/routes/poll-demand.js.map +1 -1
- package/dist/presentation/routes/reconcile-runner-instances.d.ts +2 -0
- package/dist/presentation/routes/reconcile-runner-instances.d.ts.map +1 -0
- package/dist/presentation/routes/reconcile-runner-instances.js +27 -0
- package/dist/presentation/routes/reconcile-runner-instances.js.map +1 -0
- package/dist/presentation/routes/register.d.ts +2 -1
- package/dist/presentation/routes/register.d.ts.map +1 -1
- package/dist/presentation/routes/register.js +55 -52
- package/dist/presentation/routes/register.js.map +1 -1
- package/dist/presentation/routes/report-runner-instances.d.ts +2 -0
- package/dist/presentation/routes/report-runner-instances.d.ts.map +1 -0
- package/dist/presentation/routes/report-runner-instances.js +37 -0
- package/dist/presentation/routes/report-runner-instances.js.map +1 -0
- package/dist/presentation/routes/request-job.d.ts +2 -1
- package/dist/presentation/routes/request-job.d.ts.map +1 -1
- package/dist/presentation/routes/request-job.js +39 -36
- package/dist/presentation/routes/request-job.js.map +1 -1
- package/dist/presentation/routes/runner-enrollment.d.ts +8 -0
- package/dist/presentation/routes/runner-enrollment.d.ts.map +1 -0
- package/dist/presentation/routes/runner-enrollment.js +212 -0
- package/dist/presentation/routes/runner-enrollment.js.map +1 -0
- package/dist/temporal/activities/index.d.ts +2 -2
- package/dist/temporal/activities/index.d.ts.map +1 -1
- package/dist/temporal/activities/index.js +2 -2
- package/dist/temporal/activities/index.js.map +1 -1
- package/dist/temporal/activities/maintenance-activities.d.ts +1 -1
- package/dist/temporal/activities/maintenance-activities.d.ts.map +1 -1
- package/dist/temporal/activities/maintenance-activities.js +3 -3
- package/dist/temporal/activities/maintenance-activities.js.map +1 -1
- package/dist/temporal/workflows/index.bundle.js +3 -3
- package/dist/temporal/workflows/stuck-job-detector.js +2 -2
- package/dist/temporal/workflows/stuck-job-detector.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/drizzle/0000_initial.sql +91 -24
- package/drizzle/meta/0000_snapshot.json +392 -63
- package/package.json +21 -16
- package/src/config.test.ts +0 -26
- package/src/config.ts +48 -7
- package/src/core/demand.test.ts +29 -29
- package/src/core/demand.ts +22 -22
- package/src/core/entities/ephemeral-registration-token.ts +1 -1
- package/src/core/entities/provisioner-capability-snapshot.ts +12 -0
- package/src/core/entities/provisioner-token.ts +8 -2
- package/src/core/entities/{provisioned-runner.ts → runner-instance.ts} +6 -5
- package/src/core/entities/runner-session.ts +4 -2
- package/src/core/ephemeral-registration-tokens.test.ts +11 -11
- package/src/core/ephemeral-registration-tokens.ts +18 -20
- package/src/core/errors.ts +23 -4
- package/src/core/index.ts +37 -22
- package/src/core/job-executions.ts +3 -2
- package/src/core/maintenance.test.ts +13 -17
- package/src/core/maintenance.ts +5 -5
- package/src/core/provisioner-capability-snapshots.test.ts +35 -0
- package/src/core/provisioner-capability-snapshots.ts +12 -0
- package/src/core/provisioner-tokens.test.ts +20 -0
- package/src/core/provisioner-tokens.ts +33 -0
- package/src/core/rate-limit.test.ts +11 -27
- package/src/core/rate-limit.ts +3 -11
- package/src/core/runner-activation.ts +72 -0
- package/src/core/runner-assignments.ts +9 -0
- package/src/core/runner-control-sessions.ts +190 -0
- package/src/core/{provisioned-runners.test.ts → runner-instances.test.ts} +24 -24
- package/src/core/runner-instances.ts +301 -0
- package/src/core/runner-sessions.test.ts +112 -22
- package/src/core/runner-sessions.ts +25 -14
- package/src/db/db.ts +9 -2
- package/src/db/ephemeral-registration-tokens.test.ts +9 -9
- package/src/db/ephemeral-registration-tokens.ts +26 -26
- package/src/db/index.ts +30 -21
- package/src/db/job-executions.test.ts +13 -11
- package/src/db/job-executions.ts +33 -27
- package/src/db/provisioner-capability-snapshots.test.ts +175 -0
- package/src/db/provisioner-capability-snapshots.ts +130 -0
- package/src/db/provisioner-tokens.test.ts +139 -2
- package/src/db/provisioner-tokens.ts +123 -15
- package/src/db/reservations.test.ts +49 -0
- package/src/db/reservations.ts +146 -1
- package/src/db/runner-assignments.test.ts +163 -0
- package/src/db/runner-assignments.ts +115 -0
- package/src/db/{provisioned-runners.test.ts → runner-instances.test.ts} +442 -353
- package/src/db/runner-instances.ts +922 -0
- package/src/db/runner-sessions.test.ts +19 -6
- package/src/db/runner-sessions.ts +78 -2
- package/src/db/schema/ephemeral-registration-tokens.ts +4 -4
- package/src/db/schema/provisioner-capability-snapshots.ts +46 -0
- package/src/db/schema/provisioner-tokens.ts +33 -2
- package/src/db/schema/runner-activation-tokens.ts +22 -0
- package/src/db/schema/runner-control-sessions.ts +46 -0
- package/src/db/schema/{provisioned-runners.ts → runner-instances.ts} +28 -27
- package/src/db/schema/runner-sessions.ts +11 -7
- package/src/db/schema/running-job-executions.ts +5 -5
- package/src/index.test.ts +26 -0
- package/src/index.ts +38 -27
- package/src/installation-provisioning.ts +14 -0
- package/src/metrics/index.ts +5 -5
- package/src/metrics/instance.ts +25 -14
- package/src/presentation/auth/index.ts +4 -0
- package/src/presentation/auth/provisioner-token-auth.ts +8 -4
- package/src/presentation/auth/runner-control-session-auth.ts +31 -0
- package/src/presentation/auth/runner-registration-token-auth.ts +39 -3
- package/src/presentation/dto/index.ts +4 -8
- package/src/presentation/dto/poll-demand.ts +3 -1
- package/src/presentation/dto/provisioner-token.ts +5 -0
- package/src/presentation/dto/{provisioned-runners.ts → runner-instances.ts} +13 -15
- package/src/presentation/index.ts +2 -1
- package/src/presentation/inter-module.test.ts +15 -0
- package/src/presentation/inter-module.ts +53 -0
- package/src/presentation/routes/assign-runner-instances.ts +49 -0
- package/src/presentation/routes/get-provisioner-me.ts +3 -4
- package/src/presentation/routes/heartbeat.test.ts +4 -3
- package/src/presentation/routes/heartbeat.ts +67 -64
- package/src/presentation/routes/index.ts +91 -44
- package/src/presentation/routes/list-active-runners.test.ts +23 -23
- package/src/presentation/routes/manual-registration-tokens.test.ts +4 -3
- package/src/presentation/routes/poll-demand-release.test.ts +4 -4
- package/src/presentation/routes/poll-demand.test.ts +161 -22
- package/src/presentation/routes/poll-demand.ts +105 -45
- package/src/presentation/routes/provisioner-me.test.ts +37 -3
- package/src/presentation/routes/{reconcile-provisioned-runners.test.ts → reconcile-runner-instances.test.ts} +66 -61
- package/src/presentation/routes/reconcile-runner-instances.ts +30 -0
- package/src/presentation/routes/register.test.ts +9 -5
- package/src/presentation/routes/register.ts +61 -57
- package/src/presentation/routes/{report-provisioned-runners.test.ts → report-runner-instances.test.ts} +28 -28
- package/src/presentation/routes/{report-provisioned-runners.ts → report-runner-instances.ts} +14 -14
- package/src/presentation/routes/request-job.test.ts +5 -3
- package/src/presentation/routes/request-job.ts +41 -37
- package/src/presentation/routes/runner-enrollment.test.ts +319 -0
- package/src/presentation/routes/runner-enrollment.ts +196 -0
- package/src/temporal/activities/index.ts +2 -2
- package/src/temporal/activities/maintenance-activities.test.ts +7 -7
- package/src/temporal/activities/maintenance-activities.ts +3 -3
- package/src/temporal/workflows/stuck-job-detector.test.ts +3 -3
- package/src/temporal/workflows/stuck-job-detector.ts +2 -2
- package/test/env.ts +1 -3
- package/test/factories/ephemeral-registration-token.ts +2 -2
- package/test/factories/provisioner-token.ts +3 -1
- package/test/factories/runner-instance.ts +57 -0
- package/test/factories/runner-session.ts +3 -1
- package/test/fixtures/auth-inter-module.ts +30 -0
- package/test/globalSetup.ts +4 -1
- package/test/index.ts +2 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/dist/core/entities/provisioned-runner.d.ts.map +0 -1
- package/dist/core/entities/provisioned-runner.js +0 -3
- package/dist/core/entities/provisioned-runner.js.map +0 -1
- package/dist/core/provisioned-runners.d.ts +0 -67
- package/dist/core/provisioned-runners.d.ts.map +0 -1
- package/dist/core/provisioned-runners.js +0 -162
- package/dist/core/provisioned-runners.js.map +0 -1
- package/dist/db/provisioned-runners.d.ts +0 -79
- package/dist/db/provisioned-runners.d.ts.map +0 -1
- package/dist/db/provisioned-runners.js +0 -466
- package/dist/db/provisioned-runners.js.map +0 -1
- package/dist/db/schema/provisioned-runners.d.ts.map +0 -1
- package/dist/db/schema/provisioned-runners.js.map +0 -1
- package/dist/presentation/dto/mint-registration-tokens.d.ts +0 -5
- package/dist/presentation/dto/mint-registration-tokens.d.ts.map +0 -1
- package/dist/presentation/dto/mint-registration-tokens.js +0 -19
- package/dist/presentation/dto/mint-registration-tokens.js.map +0 -1
- package/dist/presentation/dto/provisioned-runners.d.ts.map +0 -1
- package/dist/presentation/dto/provisioned-runners.js.map +0 -1
- package/dist/presentation/routes/mint-registration-tokens.d.ts +0 -2
- package/dist/presentation/routes/mint-registration-tokens.d.ts.map +0 -1
- package/dist/presentation/routes/mint-registration-tokens.js +0 -74
- package/dist/presentation/routes/mint-registration-tokens.js.map +0 -1
- package/dist/presentation/routes/reconcile-provisioned-runners.d.ts +0 -2
- package/dist/presentation/routes/reconcile-provisioned-runners.d.ts.map +0 -1
- package/dist/presentation/routes/reconcile-provisioned-runners.js +0 -27
- package/dist/presentation/routes/reconcile-provisioned-runners.js.map +0 -1
- package/dist/presentation/routes/report-provisioned-runners.d.ts +0 -2
- package/dist/presentation/routes/report-provisioned-runners.d.ts.map +0 -1
- package/dist/presentation/routes/report-provisioned-runners.js +0 -37
- package/dist/presentation/routes/report-provisioned-runners.js.map +0 -1
- package/src/core/provisioned-runners.ts +0 -301
- package/src/db/provisioned-runners.ts +0 -886
- package/src/presentation/dto/mint-registration-tokens.ts +0 -35
- package/src/presentation/routes/mint-registration-tokens.test.ts +0 -453
- package/src/presentation/routes/mint-registration-tokens.ts +0 -82
- package/src/presentation/routes/reconcile-provisioned-runners.ts +0 -30
- package/test/factories/provisioned-runner.ts +0 -78
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shipfox/api-runners",
|
|
3
3
|
"license": "MIT",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "7.0.1",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/ShipfoxHQ/shipfox.git",
|
|
@@ -25,21 +25,23 @@
|
|
|
25
25
|
"@temporalio/workflow": "1.18.1",
|
|
26
26
|
"drizzle-orm": "^0.45.2",
|
|
27
27
|
"zod": "^4.4.3",
|
|
28
|
-
"@shipfox/api-auth": "
|
|
29
|
-
"@shipfox/api-
|
|
30
|
-
"@shipfox/api-
|
|
31
|
-
"@shipfox/api-workflows-dto": "
|
|
28
|
+
"@shipfox/api-auth-context": "6.0.0",
|
|
29
|
+
"@shipfox/api-auth-dto": "6.0.0",
|
|
30
|
+
"@shipfox/api-runners-dto": "7.0.1",
|
|
31
|
+
"@shipfox/api-workflows-dto": "6.0.0",
|
|
32
32
|
"@shipfox/config": "1.2.2",
|
|
33
|
-
"@shipfox/
|
|
34
|
-
"@shipfox/node-
|
|
35
|
-
"@shipfox/node-
|
|
33
|
+
"@shipfox/inter-module": "0.2.0",
|
|
34
|
+
"@shipfox/node-drizzle": "0.3.2",
|
|
35
|
+
"@shipfox/node-auth-root-key": "0.2.0",
|
|
36
|
+
"@shipfox/node-fastify": "0.2.4",
|
|
37
|
+
"@shipfox/node-module": "0.4.0",
|
|
36
38
|
"@shipfox/node-opentelemetry": "0.5.2",
|
|
37
|
-
"@shipfox/node-outbox": "0.2.
|
|
39
|
+
"@shipfox/node-outbox": "0.2.4",
|
|
38
40
|
"@shipfox/node-postgres": "0.4.2",
|
|
39
|
-
"@shipfox/node-rate-limit": "0.
|
|
40
|
-
"@shipfox/node-
|
|
41
|
-
"@shipfox/
|
|
42
|
-
"@shipfox/
|
|
41
|
+
"@shipfox/node-rate-limit": "0.3.0",
|
|
42
|
+
"@shipfox/node-temporal": "0.3.2",
|
|
43
|
+
"@shipfox/node-tokens": "0.3.0",
|
|
44
|
+
"@shipfox/runner-labels": "0.1.1"
|
|
43
45
|
},
|
|
44
46
|
"devDependencies": {
|
|
45
47
|
"@temporalio/activity": "1.18.1",
|
|
@@ -52,18 +54,21 @@
|
|
|
52
54
|
"fastify": "^5.3.3",
|
|
53
55
|
"fastify-type-provider-zod": "^6.0.0",
|
|
54
56
|
"fishery": "^2.4.0",
|
|
55
|
-
"@shipfox/api-auth
|
|
57
|
+
"@shipfox/api-auth": "7.0.1",
|
|
58
|
+
"@shipfox/api-auth-dto": "6.0.0",
|
|
56
59
|
"@shipfox/biome": "1.8.2",
|
|
57
|
-
"@shipfox/
|
|
60
|
+
"@shipfox/depcruise": "1.0.2",
|
|
61
|
+
"@shipfox/node-jwt": "0.3.0",
|
|
58
62
|
"@shipfox/swc": "1.2.6",
|
|
59
|
-
"@shipfox/typescript": "1.1.7",
|
|
60
63
|
"@shipfox/ts-config": "1.3.8",
|
|
64
|
+
"@shipfox/typescript": "1.1.7",
|
|
61
65
|
"@shipfox/vitest": "1.2.3"
|
|
62
66
|
},
|
|
63
67
|
"scripts": {
|
|
64
68
|
"build": "shipfox-swc && shipfox-temporal-bundle dist/temporal/workflows/index.js",
|
|
65
69
|
"check": "shipfox-biome-check",
|
|
66
70
|
"check:fix": "shipfox-biome-check --write",
|
|
71
|
+
"depcruise": "shipfox-depcruise",
|
|
67
72
|
"test": "shipfox-vitest-run",
|
|
68
73
|
"test:watch": "shipfox-vitest-watch",
|
|
69
74
|
"type": "shipfox-tsc-check",
|
package/src/config.test.ts
CHANGED
|
@@ -27,7 +27,6 @@ describe('EPHEMERAL_REGISTRATION_TOKEN_TTL_SECONDS validation', () => {
|
|
|
27
27
|
expect(config.EPHEMERAL_REGISTRATION_TOKEN_TTL_SECONDS).toBe(3600);
|
|
28
28
|
});
|
|
29
29
|
});
|
|
30
|
-
|
|
31
30
|
describe('REGISTRATION_TOKEN_BATCH_MAX validation', () => {
|
|
32
31
|
afterEach(() => {
|
|
33
32
|
vi.unstubAllEnvs();
|
|
@@ -85,31 +84,6 @@ describe.each([
|
|
|
85
84
|
});
|
|
86
85
|
});
|
|
87
86
|
|
|
88
|
-
describe('RATE_LIMIT_IDENTIFIER_SECRET validation', () => {
|
|
89
|
-
afterEach(() => {
|
|
90
|
-
vi.unstubAllEnvs();
|
|
91
|
-
vi.resetModules();
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it('allows the secret to be omitted', async () => {
|
|
95
|
-
const previous = process.env.RATE_LIMIT_IDENTIFIER_SECRET;
|
|
96
|
-
delete process.env.RATE_LIMIT_IDENTIFIER_SECRET;
|
|
97
|
-
vi.resetModules();
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
const {config} = await import('#config.js');
|
|
101
|
-
|
|
102
|
-
expect(config.RATE_LIMIT_IDENTIFIER_SECRET).toBeUndefined();
|
|
103
|
-
} finally {
|
|
104
|
-
if (previous === undefined) {
|
|
105
|
-
delete process.env.RATE_LIMIT_IDENTIFIER_SECRET;
|
|
106
|
-
} else {
|
|
107
|
-
process.env.RATE_LIMIT_IDENTIFIER_SECRET = previous;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
|
|
113
87
|
describe('RUNNER_NO_FIRST_HEARTBEAT_GRACE_SECONDS validation', () => {
|
|
114
88
|
afterEach(() => {
|
|
115
89
|
vi.unstubAllEnvs();
|
package/src/config.ts
CHANGED
|
@@ -1,10 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {bool, createConfig, num, str} from '@shipfox/config';
|
|
1
|
+
import {bool, createConfig, num} from '@shipfox/config';
|
|
3
2
|
import {STUCK_JOB_THRESHOLD_SECONDS} from '#core/maintenance-policy.js';
|
|
4
3
|
|
|
5
4
|
const EPHEMERAL_REGISTRATION_TOKEN_TTL_HARD_MAX_SECONDS = 3600;
|
|
5
|
+
const REGISTRATION_TOKEN_BATCH_HARD_MAX = 1000;
|
|
6
|
+
const RUNNER_CONTROL_PLANE_TOKEN_TTL_HARD_MAX_SECONDS = 3600;
|
|
6
7
|
|
|
7
8
|
export const config = createConfig({
|
|
9
|
+
RUNNER_BOOTSTRAP_TOKEN_TTL_SECONDS: num({
|
|
10
|
+
desc: 'Lifetime of a one-use runner bootstrap token in seconds. The token can only create one runner-control session before it expires.',
|
|
11
|
+
default: 300,
|
|
12
|
+
}),
|
|
13
|
+
RUNNER_CONTROL_SESSION_TTL_SECONDS: num({
|
|
14
|
+
desc: 'Lifetime of a pre-workspace runner-control session in seconds. This session can only enroll, attach its provider identity, and report its own liveness.',
|
|
15
|
+
default: 3600,
|
|
16
|
+
}),
|
|
17
|
+
RUNNER_ACTIVATION_TOKEN_TTL_SECONDS: num({
|
|
18
|
+
desc: 'Lifetime of a one-use activation token in seconds. The token is issued only to an assigned runner-control session and creates one workspace runner session.',
|
|
19
|
+
default: 300,
|
|
20
|
+
}),
|
|
21
|
+
RUNNER_ASSIGNMENT_POLL_MAX_WAIT_SECONDS: num({
|
|
22
|
+
desc: 'Maximum time the runner assignment poll waits before returning no assignment, in seconds.',
|
|
23
|
+
default: 30,
|
|
24
|
+
}),
|
|
25
|
+
RUNNER_ASSIGNMENT_POLL_INTERVAL_MS: num({
|
|
26
|
+
desc: 'Delay between durable assignment reads while a runner-control session waits for an assignment, in milliseconds.',
|
|
27
|
+
default: 1000,
|
|
28
|
+
}),
|
|
8
29
|
EPHEMERAL_REGISTRATION_TOKEN_TTL_SECONDS: num({
|
|
9
30
|
desc: `Lifetime of a provisioner-minted runner registration token, in seconds. The token can be exchanged once by a runner before this time passes. Set this between 1 and ${EPHEMERAL_REGISTRATION_TOKEN_TTL_HARD_MAX_SECONDS}.`,
|
|
10
31
|
default: 300,
|
|
@@ -33,10 +54,6 @@ export const config = createConfig({
|
|
|
33
54
|
desc: 'Maximum time, in milliseconds, a runners rate-limit storage check may wait before the request fails closed.',
|
|
34
55
|
default: 250,
|
|
35
56
|
}),
|
|
36
|
-
RATE_LIMIT_IDENTIFIER_SECRET: str({
|
|
37
|
-
desc: 'Optional secret used to HMAC identifiers before storing rate-limit counters. Leave it unset to derive a stable key from AUTH_JWT_SECRET.',
|
|
38
|
-
default: undefined,
|
|
39
|
-
}),
|
|
40
57
|
RESERVATION_TTL_SECONDS: num({
|
|
41
58
|
desc: 'Lifetime of a count-based runner reservation, in seconds. Expired reservations stop counting against queued demand.',
|
|
42
59
|
default: 60,
|
|
@@ -110,7 +127,7 @@ export const config = createConfig({
|
|
|
110
127
|
default: 10,
|
|
111
128
|
}),
|
|
112
129
|
PROVISIONED_RUNNER_COUNT_DIVERGENCE_TEMPLATE_KEY_LABEL_ENABLED: bool({
|
|
113
|
-
desc: 'Whether
|
|
130
|
+
desc: 'Whether runners_provider_runner_count_divergence includes template_key as a metric label. Use true or false. Defaults to false because template keys can create high-cardinality metric series. Set true only when template keys are bounded and stable.',
|
|
114
131
|
default: false,
|
|
115
132
|
}),
|
|
116
133
|
});
|
|
@@ -126,6 +143,30 @@ if (
|
|
|
126
143
|
);
|
|
127
144
|
}
|
|
128
145
|
|
|
146
|
+
for (const [name, value] of [
|
|
147
|
+
['RUNNER_BOOTSTRAP_TOKEN_TTL_SECONDS', config.RUNNER_BOOTSTRAP_TOKEN_TTL_SECONDS],
|
|
148
|
+
['RUNNER_CONTROL_SESSION_TTL_SECONDS', config.RUNNER_CONTROL_SESSION_TTL_SECONDS],
|
|
149
|
+
['RUNNER_ACTIVATION_TOKEN_TTL_SECONDS', config.RUNNER_ACTIVATION_TOKEN_TTL_SECONDS],
|
|
150
|
+
] as const) {
|
|
151
|
+
if (
|
|
152
|
+
!Number.isInteger(value) ||
|
|
153
|
+
value < 1 ||
|
|
154
|
+
value > RUNNER_CONTROL_PLANE_TOKEN_TTL_HARD_MAX_SECONDS
|
|
155
|
+
) {
|
|
156
|
+
throw new Error(
|
|
157
|
+
`${name} (${value}) must be a whole number of seconds between 1 and ${RUNNER_CONTROL_PLANE_TOKEN_TTL_HARD_MAX_SECONDS}.`,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
for (const [name, value] of [
|
|
163
|
+
['RUNNER_ASSIGNMENT_POLL_MAX_WAIT_SECONDS', config.RUNNER_ASSIGNMENT_POLL_MAX_WAIT_SECONDS],
|
|
164
|
+
['RUNNER_ASSIGNMENT_POLL_INTERVAL_MS', config.RUNNER_ASSIGNMENT_POLL_INTERVAL_MS],
|
|
165
|
+
] as const) {
|
|
166
|
+
if (!Number.isInteger(value) || value < 0)
|
|
167
|
+
throw new Error(`${name} (${value}) must be a whole number >= 0.`);
|
|
168
|
+
}
|
|
169
|
+
|
|
129
170
|
if (
|
|
130
171
|
!Number.isInteger(config.REGISTRATION_TOKEN_BATCH_MAX) ||
|
|
131
172
|
config.REGISTRATION_TOKEN_BATCH_MAX < 1 ||
|
package/src/core/demand.test.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
calculateRunnerInstanceCountDivergences,
|
|
3
3
|
nextBackoffInterval,
|
|
4
4
|
pollDemand,
|
|
5
5
|
shouldReturn,
|
|
6
6
|
} from '#core/demand.js';
|
|
7
7
|
|
|
8
8
|
describe('shouldReturn', () => {
|
|
9
|
-
const emptyResult = {stats: [], reservations: [],
|
|
9
|
+
const emptyResult = {stats: [], reservations: [], terminateRunnerInstanceIds: []};
|
|
10
10
|
|
|
11
11
|
it('returns true for observe-only requests', () => {
|
|
12
12
|
const result = shouldReturn(emptyResult, 0, 1, false);
|
|
@@ -27,7 +27,7 @@ describe('shouldReturn', () => {
|
|
|
27
27
|
reservations: [
|
|
28
28
|
{reservationId: crypto.randomUUID(), labels: ['linux'], count: 1, expiresAt: new Date()},
|
|
29
29
|
],
|
|
30
|
-
|
|
30
|
+
terminateRunnerInstanceIds: [],
|
|
31
31
|
},
|
|
32
32
|
1,
|
|
33
33
|
1,
|
|
@@ -39,7 +39,7 @@ describe('shouldReturn', () => {
|
|
|
39
39
|
|
|
40
40
|
it('returns true when terminate intents exist', () => {
|
|
41
41
|
const result = shouldReturn(
|
|
42
|
-
{...emptyResult,
|
|
42
|
+
{...emptyResult, terminateRunnerInstanceIds: ['provisioned-runner-1']},
|
|
43
43
|
1,
|
|
44
44
|
1,
|
|
45
45
|
false,
|
|
@@ -76,7 +76,7 @@ describe('pollDemand', () => {
|
|
|
76
76
|
signal: new AbortController().signal,
|
|
77
77
|
});
|
|
78
78
|
|
|
79
|
-
expect(result).toEqual({stats: [], reservations: [],
|
|
79
|
+
expect(result).toEqual({stats: [], reservations: [], terminateRunnerInstanceIds: []});
|
|
80
80
|
});
|
|
81
81
|
|
|
82
82
|
it('returns immediately when terminate intents exist without reservation demand', async () => {
|
|
@@ -84,8 +84,8 @@ describe('pollDemand', () => {
|
|
|
84
84
|
const pollDemandAndReserveTx = vi.fn().mockResolvedValue({stats: [], reservations: []});
|
|
85
85
|
const listProvisionerTerminateIntentRowsTx = vi
|
|
86
86
|
.fn()
|
|
87
|
-
.mockResolvedValue([{
|
|
88
|
-
const
|
|
87
|
+
.mockResolvedValue([{providerRunnerId: 'provisioned-runner-1', reason: 'job-cancelled'}]);
|
|
88
|
+
const listActiveRunnerInstanceCountsByTemplateTx = vi.fn().mockResolvedValue([]);
|
|
89
89
|
vi.doMock('#db/db.js', () => ({
|
|
90
90
|
db: () => ({transaction: (callback: (tx: unknown) => Promise<unknown>) => callback({})}),
|
|
91
91
|
}));
|
|
@@ -93,8 +93,8 @@ describe('pollDemand', () => {
|
|
|
93
93
|
deleteReservationsByIds: vi.fn(),
|
|
94
94
|
pollDemandAndReserveTx,
|
|
95
95
|
}));
|
|
96
|
-
vi.doMock('#db/
|
|
97
|
-
|
|
96
|
+
vi.doMock('#db/runner-instances.js', () => ({
|
|
97
|
+
listActiveRunnerInstanceCountsByTemplateTx,
|
|
98
98
|
listProvisionerTerminateIntentRowsTx,
|
|
99
99
|
}));
|
|
100
100
|
|
|
@@ -117,14 +117,14 @@ describe('pollDemand', () => {
|
|
|
117
117
|
expect(result).toEqual({
|
|
118
118
|
stats: [],
|
|
119
119
|
reservations: [],
|
|
120
|
-
|
|
120
|
+
terminateRunnerInstanceIds: ['provisioned-runner-1'],
|
|
121
121
|
});
|
|
122
122
|
expect(pollDemandAndReserveTx).toHaveBeenCalledOnce();
|
|
123
123
|
expect(listProvisionerTerminateIntentRowsTx).toHaveBeenCalledOnce();
|
|
124
124
|
} finally {
|
|
125
125
|
vi.doUnmock('#db/db.js');
|
|
126
126
|
vi.doUnmock('#db/reservations.js');
|
|
127
|
-
vi.doUnmock('#db/
|
|
127
|
+
vi.doUnmock('#db/runner-instances.js');
|
|
128
128
|
vi.resetModules();
|
|
129
129
|
}
|
|
130
130
|
});
|
|
@@ -137,7 +137,7 @@ describe('pollDemand', () => {
|
|
|
137
137
|
abortController.abort();
|
|
138
138
|
return [];
|
|
139
139
|
});
|
|
140
|
-
const
|
|
140
|
+
const listActiveRunnerInstanceCountsByTemplateTx = vi.fn().mockResolvedValue([]);
|
|
141
141
|
vi.doMock('#db/db.js', () => ({
|
|
142
142
|
db: () => ({transaction: (callback: (tx: unknown) => Promise<unknown>) => callback({})}),
|
|
143
143
|
}));
|
|
@@ -145,8 +145,8 @@ describe('pollDemand', () => {
|
|
|
145
145
|
deleteReservationsByIds: vi.fn(),
|
|
146
146
|
pollDemandAndReserveTx,
|
|
147
147
|
}));
|
|
148
|
-
vi.doMock('#db/
|
|
149
|
-
|
|
148
|
+
vi.doMock('#db/runner-instances.js', () => ({
|
|
149
|
+
listActiveRunnerInstanceCountsByTemplateTx,
|
|
150
150
|
listProvisionerTerminateIntentRowsTx,
|
|
151
151
|
}));
|
|
152
152
|
|
|
@@ -166,12 +166,12 @@ describe('pollDemand', () => {
|
|
|
166
166
|
signal: abortController.signal,
|
|
167
167
|
});
|
|
168
168
|
|
|
169
|
-
expect(result).toEqual({stats: [], reservations: [],
|
|
170
|
-
expect(
|
|
169
|
+
expect(result).toEqual({stats: [], reservations: [], terminateRunnerInstanceIds: []});
|
|
170
|
+
expect(listActiveRunnerInstanceCountsByTemplateTx).not.toHaveBeenCalled();
|
|
171
171
|
} finally {
|
|
172
172
|
vi.doUnmock('#db/db.js');
|
|
173
173
|
vi.doUnmock('#db/reservations.js');
|
|
174
|
-
vi.doUnmock('#db/
|
|
174
|
+
vi.doUnmock('#db/runner-instances.js');
|
|
175
175
|
vi.resetModules();
|
|
176
176
|
}
|
|
177
177
|
});
|
|
@@ -182,7 +182,7 @@ describe('pollDemand', () => {
|
|
|
182
182
|
const divergenceAdd = vi.fn();
|
|
183
183
|
const pollDemandAndReserveTx = vi.fn().mockResolvedValue({stats: [], reservations: []});
|
|
184
184
|
const listProvisionerTerminateIntentRowsTx = vi.fn().mockResolvedValue([]);
|
|
185
|
-
const
|
|
185
|
+
const listActiveRunnerInstanceCountsByTemplateTx = vi
|
|
186
186
|
.fn()
|
|
187
187
|
.mockResolvedValue([{templateKey: 'linux', state: 'running', count: 2}]);
|
|
188
188
|
vi.doMock('#db/db.js', () => ({
|
|
@@ -192,13 +192,13 @@ describe('pollDemand', () => {
|
|
|
192
192
|
deleteReservationsByIds: vi.fn(),
|
|
193
193
|
pollDemandAndReserveTx,
|
|
194
194
|
}));
|
|
195
|
-
vi.doMock('#db/
|
|
196
|
-
|
|
195
|
+
vi.doMock('#db/runner-instances.js', () => ({
|
|
196
|
+
listActiveRunnerInstanceCountsByTemplateTx,
|
|
197
197
|
listProvisionerTerminateIntentRowsTx,
|
|
198
198
|
}));
|
|
199
199
|
vi.doMock('#metrics/instance.js', () => ({
|
|
200
|
-
|
|
201
|
-
|
|
200
|
+
providerRunnerCountDivergenceCount: {add: divergenceAdd},
|
|
201
|
+
providerRunnerTerminateIntentIssuedCount: {add: vi.fn()},
|
|
202
202
|
}));
|
|
203
203
|
|
|
204
204
|
try {
|
|
@@ -217,7 +217,7 @@ describe('pollDemand', () => {
|
|
|
217
217
|
signal: new AbortController().signal,
|
|
218
218
|
});
|
|
219
219
|
|
|
220
|
-
expect(result).toEqual({stats: [], reservations: [],
|
|
220
|
+
expect(result).toEqual({stats: [], reservations: [], terminateRunnerInstanceIds: []});
|
|
221
221
|
expect(divergenceAdd).toHaveBeenCalledWith(1, {
|
|
222
222
|
template_key: 'linux',
|
|
223
223
|
state: 'running',
|
|
@@ -227,16 +227,16 @@ describe('pollDemand', () => {
|
|
|
227
227
|
vi.unstubAllEnvs();
|
|
228
228
|
vi.doUnmock('#db/db.js');
|
|
229
229
|
vi.doUnmock('#db/reservations.js');
|
|
230
|
-
vi.doUnmock('#db/
|
|
230
|
+
vi.doUnmock('#db/runner-instances.js');
|
|
231
231
|
vi.doUnmock('#metrics/instance.js');
|
|
232
232
|
vi.resetModules();
|
|
233
233
|
}
|
|
234
234
|
});
|
|
235
235
|
});
|
|
236
236
|
|
|
237
|
-
describe('
|
|
237
|
+
describe('calculateRunnerInstanceCountDivergences', () => {
|
|
238
238
|
it('returns no divergences when advertised and backend counts match', () => {
|
|
239
|
-
const result =
|
|
239
|
+
const result = calculateRunnerInstanceCountDivergences({
|
|
240
240
|
advertisedTemplates: [template('linux', 1, 2)],
|
|
241
241
|
backendCounts: [
|
|
242
242
|
{templateKey: 'linux', state: 'starting', count: 1},
|
|
@@ -248,7 +248,7 @@ describe('calculateProvisionedRunnerCountDivergences', () => {
|
|
|
248
248
|
});
|
|
249
249
|
|
|
250
250
|
it('detects backend-higher and advertised-higher counts', () => {
|
|
251
|
-
const result =
|
|
251
|
+
const result = calculateRunnerInstanceCountDivergences({
|
|
252
252
|
advertisedTemplates: [template('linux', 1, 5)],
|
|
253
253
|
backendCounts: [
|
|
254
254
|
{templateKey: 'linux', state: 'starting', count: 3},
|
|
@@ -263,7 +263,7 @@ describe('calculateProvisionedRunnerCountDivergences', () => {
|
|
|
263
263
|
});
|
|
264
264
|
|
|
265
265
|
it('aggregates duplicate advertised template keys before comparing', () => {
|
|
266
|
-
const result =
|
|
266
|
+
const result = calculateRunnerInstanceCountDivergences({
|
|
267
267
|
advertisedTemplates: [template('linux', 1, 1), template('linux', 2, 3)],
|
|
268
268
|
backendCounts: [
|
|
269
269
|
{templateKey: 'linux', state: 'starting', count: 3},
|
|
@@ -275,7 +275,7 @@ describe('calculateProvisionedRunnerCountDivergences', () => {
|
|
|
275
275
|
});
|
|
276
276
|
|
|
277
277
|
it('detects backend-only template keys as backend-higher', () => {
|
|
278
|
-
const result =
|
|
278
|
+
const result = calculateRunnerInstanceCountDivergences({
|
|
279
279
|
advertisedTemplates: [template('linux', 0, 0)],
|
|
280
280
|
backendCounts: [{templateKey: 'gpu', state: 'running', count: 2}],
|
|
281
281
|
});
|
package/src/core/demand.ts
CHANGED
|
@@ -2,12 +2,6 @@ import {setTimeout as sleep} from 'node:timers/promises';
|
|
|
2
2
|
import {logger} from '@shipfox/node-opentelemetry';
|
|
3
3
|
import {config} from '#config.js';
|
|
4
4
|
import {db} from '#db/db.js';
|
|
5
|
-
import {
|
|
6
|
-
type ActiveProvisionedRunnerTemplateCount,
|
|
7
|
-
listActiveProvisionedRunnerCountsByTemplateTx,
|
|
8
|
-
listProvisionerTerminateIntentRowsTx,
|
|
9
|
-
type ProvisionedRunnerTerminateIntent,
|
|
10
|
-
} from '#db/provisioned-runners.js';
|
|
11
5
|
import {
|
|
12
6
|
type DemandStat,
|
|
13
7
|
deleteReservationsByIds,
|
|
@@ -16,8 +10,14 @@ import {
|
|
|
16
10
|
type ReservationTemplate,
|
|
17
11
|
} from '#db/reservations.js';
|
|
18
12
|
import {
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
type ActiveRunnerInstanceTemplateCount,
|
|
14
|
+
listActiveRunnerInstanceCountsByTemplateTx,
|
|
15
|
+
listProvisionerTerminateIntentRowsTx,
|
|
16
|
+
type RunnerInstanceTerminateIntent,
|
|
17
|
+
} from '#db/runner-instances.js';
|
|
18
|
+
import {
|
|
19
|
+
providerRunnerCountDivergenceCount,
|
|
20
|
+
providerRunnerTerminateIntentIssuedCount,
|
|
21
21
|
} from '#metrics/instance.js';
|
|
22
22
|
|
|
23
23
|
export interface PollDemandParams {
|
|
@@ -34,10 +34,10 @@ export interface PollDemandParams {
|
|
|
34
34
|
export interface PollDemandResult {
|
|
35
35
|
stats: DemandStat[];
|
|
36
36
|
reservations: ReservationGrant[];
|
|
37
|
-
|
|
37
|
+
terminateRunnerInstanceIds: string[];
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
export interface
|
|
40
|
+
export interface RunnerInstanceCountDivergence {
|
|
41
41
|
templateKey: string;
|
|
42
42
|
state: 'starting' | 'running';
|
|
43
43
|
direction: 'backend-higher' | 'advertised-higher';
|
|
@@ -46,8 +46,8 @@ export interface ProvisionedRunnerCountDivergence {
|
|
|
46
46
|
|
|
47
47
|
interface PollDemandSnapshot {
|
|
48
48
|
result: PollDemandResult;
|
|
49
|
-
divergences:
|
|
50
|
-
terminateIntents:
|
|
49
|
+
divergences: RunnerInstanceCountDivergence[];
|
|
50
|
+
terminateIntents: RunnerInstanceTerminateIntent[];
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export async function pollDemand(params: PollDemandParams): Promise<PollDemandResult> {
|
|
@@ -62,7 +62,7 @@ export async function pollDemand(params: PollDemandParams): Promise<PollDemandRe
|
|
|
62
62
|
);
|
|
63
63
|
let interval = config.RESERVATION_POLL_INTERVAL_MS;
|
|
64
64
|
let lastSnapshot: PollDemandSnapshot = {
|
|
65
|
-
result: {stats: [], reservations: [],
|
|
65
|
+
result: {stats: [], reservations: [], terminateRunnerInstanceIds: []},
|
|
66
66
|
divergences: [],
|
|
67
67
|
terminateIntents: [],
|
|
68
68
|
};
|
|
@@ -87,7 +87,7 @@ export async function pollDemand(params: PollDemandParams): Promise<PollDemandRe
|
|
|
87
87
|
});
|
|
88
88
|
const result: PollDemandResult = {
|
|
89
89
|
...demand,
|
|
90
|
-
|
|
90
|
+
terminateRunnerInstanceIds: terminateIntents.map((intent) => intent.providerRunnerId),
|
|
91
91
|
};
|
|
92
92
|
|
|
93
93
|
if (!shouldReturn(result, params.maxReservations, totalCapacity, deadlinePassed)) {
|
|
@@ -97,9 +97,9 @@ export async function pollDemand(params: PollDemandParams): Promise<PollDemandRe
|
|
|
97
97
|
return {
|
|
98
98
|
result,
|
|
99
99
|
terminateIntents,
|
|
100
|
-
divergences:
|
|
100
|
+
divergences: calculateRunnerInstanceCountDivergences({
|
|
101
101
|
advertisedTemplates: params.templates,
|
|
102
|
-
backendCounts: await
|
|
102
|
+
backendCounts: await listActiveRunnerInstanceCountsByTemplateTx(tx, {
|
|
103
103
|
workspaceId: params.workspaceId,
|
|
104
104
|
provisionerId: params.provisionerId,
|
|
105
105
|
}),
|
|
@@ -145,7 +145,7 @@ export function shouldReturn(
|
|
|
145
145
|
maxReservations === 0 ||
|
|
146
146
|
totalCapacity === 0 ||
|
|
147
147
|
result.reservations.length > 0 ||
|
|
148
|
-
result.
|
|
148
|
+
result.terminateRunnerInstanceIds.length > 0 ||
|
|
149
149
|
deadlinePassed
|
|
150
150
|
);
|
|
151
151
|
}
|
|
@@ -158,10 +158,10 @@ export function withJitter(ms: number): number {
|
|
|
158
158
|
return Math.random() * ms;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
export function
|
|
161
|
+
export function calculateRunnerInstanceCountDivergences(params: {
|
|
162
162
|
advertisedTemplates: ReservationTemplate[];
|
|
163
|
-
backendCounts:
|
|
164
|
-
}):
|
|
163
|
+
backendCounts: ActiveRunnerInstanceTemplateCount[];
|
|
164
|
+
}): RunnerInstanceCountDivergence[] {
|
|
165
165
|
const advertisedCounts = new Map<string, number>();
|
|
166
166
|
const backendCounts = new Map<string, number>();
|
|
167
167
|
|
|
@@ -212,10 +212,10 @@ function recordPollDemandMetrics(params: PollDemandParams, snapshot: PollDemandS
|
|
|
212
212
|
? {template_key: divergence.templateKey}
|
|
213
213
|
: {}),
|
|
214
214
|
};
|
|
215
|
-
|
|
215
|
+
providerRunnerCountDivergenceCount.add(divergence.delta, attributes);
|
|
216
216
|
}
|
|
217
217
|
for (const intent of snapshot.terminateIntents) {
|
|
218
|
-
|
|
218
|
+
providerRunnerTerminateIntentIssuedCount.add(1, {
|
|
219
219
|
surface: 'poll-demand',
|
|
220
220
|
reason: intent.reason,
|
|
221
221
|
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface ProvisionerCapabilitySnapshot {
|
|
2
|
+
id: string;
|
|
3
|
+
workspaceId: string;
|
|
4
|
+
provisionerId: string;
|
|
5
|
+
templateKey: string;
|
|
6
|
+
labels: string[];
|
|
7
|
+
availableSlots: number;
|
|
8
|
+
starting: number;
|
|
9
|
+
running: number;
|
|
10
|
+
advertisedAt: Date;
|
|
11
|
+
createdAt: Date;
|
|
12
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type ProvisionerScope = 'installation' | 'workspace';
|
|
2
|
+
|
|
3
|
+
export interface ProvisionerTokenBase {
|
|
2
4
|
id: string;
|
|
3
|
-
|
|
5
|
+
scope: ProvisionerScope;
|
|
4
6
|
hashedToken: string;
|
|
5
7
|
prefix: string;
|
|
6
8
|
name: string | null;
|
|
@@ -13,4 +15,8 @@ export interface ProvisionerToken {
|
|
|
13
15
|
updatedAt: Date;
|
|
14
16
|
}
|
|
15
17
|
|
|
18
|
+
export type ProvisionerToken =
|
|
19
|
+
| (ProvisionerTokenBase & {scope: 'installation'; workspaceId: null})
|
|
20
|
+
| (ProvisionerTokenBase & {scope: 'workspace'; workspaceId: string});
|
|
21
|
+
|
|
16
22
|
export type ActiveProvisionerToken = ProvisionerToken & {lastSeenAt: Date};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export type RunnerInstanceState =
|
|
2
2
|
| 'starting'
|
|
3
3
|
| 'running'
|
|
4
4
|
| 'stopping'
|
|
@@ -6,15 +6,16 @@ export type ProvisionedRunnerState =
|
|
|
6
6
|
| 'failed'
|
|
7
7
|
| 'terminated';
|
|
8
8
|
|
|
9
|
-
export interface
|
|
9
|
+
export interface RunnerInstance {
|
|
10
10
|
id: string;
|
|
11
|
-
workspaceId: string;
|
|
11
|
+
workspaceId: string | null;
|
|
12
12
|
provisionerId: string;
|
|
13
|
-
|
|
13
|
+
providerRunnerId: string;
|
|
14
14
|
reservationId: string | null;
|
|
15
|
+
assignedAt?: Date | null;
|
|
15
16
|
templateKey: string | null;
|
|
16
17
|
labels: string[];
|
|
17
|
-
state:
|
|
18
|
+
state: RunnerInstanceState;
|
|
18
19
|
reason: string | null;
|
|
19
20
|
runnerSessionId: string | null;
|
|
20
21
|
providerKind: string | null;
|
|
@@ -5,14 +5,16 @@ export interface RunnerSession {
|
|
|
5
5
|
workspaceId: string;
|
|
6
6
|
scope: 'workspace';
|
|
7
7
|
registrationTokenId: string;
|
|
8
|
-
registrationTokenKind: 'manual' | 'ephemeral';
|
|
8
|
+
registrationTokenKind: 'manual' | 'ephemeral' | 'activation';
|
|
9
|
+
runnerInstanceId: string | null;
|
|
9
10
|
provisionerId: string | null;
|
|
10
|
-
|
|
11
|
+
providerRunnerId: string | null;
|
|
11
12
|
labels: string[];
|
|
12
13
|
toolCapabilities: RunnerToolCapabilitiesDto | null;
|
|
13
14
|
toolCapabilitiesReportedAt: Date | null;
|
|
14
15
|
maxClaims: number | null;
|
|
15
16
|
claimsUsed: number;
|
|
17
|
+
revokedAt: Date | null;
|
|
16
18
|
createdAt: Date;
|
|
17
19
|
updatedAt: Date;
|
|
18
20
|
}
|