@highstate/backend 0.9.15 → 0.9.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/dist/chunk-NAAIDR4U.js +8499 -0
  2. package/dist/chunk-NAAIDR4U.js.map +1 -0
  3. package/dist/chunk-OU5OQBLB.js +74 -0
  4. package/dist/chunk-OU5OQBLB.js.map +1 -0
  5. package/dist/chunk-Y7DXREVO.js +1745 -0
  6. package/dist/chunk-Y7DXREVO.js.map +1 -0
  7. package/dist/highstate.manifest.json +4 -4
  8. package/dist/index.js +7227 -2501
  9. package/dist/index.js.map +1 -1
  10. package/dist/library/package-resolution-worker.js +7 -5
  11. package/dist/library/package-resolution-worker.js.map +1 -1
  12. package/dist/library/worker/main.js +76 -185
  13. package/dist/library/worker/main.js.map +1 -1
  14. package/dist/magic-string.es-5ABAC4JN.js +1292 -0
  15. package/dist/magic-string.es-5ABAC4JN.js.map +1 -0
  16. package/dist/shared/index.js +3 -98
  17. package/dist/shared/index.js.map +1 -1
  18. package/package.json +31 -10
  19. package/src/artifact/abstractions.ts +46 -0
  20. package/src/artifact/encryption.ts +109 -0
  21. package/src/artifact/factory.ts +36 -0
  22. package/src/artifact/index.ts +3 -0
  23. package/src/artifact/local.ts +138 -0
  24. package/src/business/__traces__/secret/update-instance-secrets/create-and-delete-secrets-simultaneously.md +356 -0
  25. package/src/business/__traces__/secret/update-instance-secrets/create-new-secrets-for-instance.md +274 -0
  26. package/src/business/__traces__/secret/update-instance-secrets/delete-existing-secrets.md +223 -0
  27. package/src/business/__traces__/secret/update-instance-secrets/no-op-when-no-changes.md +147 -0
  28. package/src/business/__traces__/secret/update-instance-secrets/update-existing-secrets.md +280 -0
  29. package/src/business/__traces__/worker/update-unit-registrations/add-new-unit-registration-when-other-exists.md +360 -0
  30. package/src/business/__traces__/worker/update-unit-registrations/add-new-unit-registration.md +215 -0
  31. package/src/business/__traces__/worker/update-unit-registrations/create-multiple-workers-with-different-identities.md +427 -0
  32. package/src/business/__traces__/worker/update-unit-registrations/handle-nonexistent-registration-id-gracefully.md +217 -0
  33. package/src/business/__traces__/worker/update-unit-registrations/no-op-when-no-changes.md +132 -0
  34. package/src/business/__traces__/worker/update-unit-registrations/recreate-worker-when-image-changes.md +454 -0
  35. package/src/business/__traces__/worker/update-unit-registrations/recreate-worker-when-image-version-changes.md +426 -0
  36. package/src/business/__traces__/worker/update-unit-registrations/recreate-worker-with-same-identity-reuses-service-account.md +372 -0
  37. package/src/business/__traces__/worker/update-unit-registrations/remove-one-of-multiple-unit-registrations.md +383 -0
  38. package/src/business/__traces__/worker/update-unit-registrations/remove-unit-registration.md +245 -0
  39. package/src/business/__traces__/worker/update-unit-registrations/update-existing-unit-registration-when-params-change.md +174 -0
  40. package/src/business/__traces__/worker/update-unit-registrations/update-params-and-image-simultaneously.md +432 -0
  41. package/src/business/__traces__/worker/update-unit-registrations/worker-with-multiple-registrations-not-deleted-when-one-removed.md +220 -0
  42. package/src/business/api-key.ts +65 -0
  43. package/src/business/artifact.ts +289 -0
  44. package/src/business/backend-unlock.ts +10 -0
  45. package/src/business/index.ts +10 -0
  46. package/src/business/instance-lock.ts +125 -0
  47. package/src/business/instance-state.ts +434 -0
  48. package/src/business/operation.ts +251 -0
  49. package/src/business/project-unlock.ts +260 -0
  50. package/src/business/project.ts +299 -0
  51. package/src/business/secret.test.ts +178 -0
  52. package/src/business/secret.ts +281 -0
  53. package/src/business/worker.test.ts +614 -0
  54. package/src/business/worker.ts +398 -0
  55. package/src/common/clock.ts +18 -0
  56. package/src/common/index.ts +5 -1
  57. package/src/common/performance.ts +44 -0
  58. package/src/common/random.ts +68 -0
  59. package/src/common/test/index.ts +2 -0
  60. package/src/common/test/render.ts +98 -0
  61. package/src/common/test/tracer.ts +359 -0
  62. package/src/common/tree.ts +33 -0
  63. package/src/common/utils.ts +40 -1
  64. package/src/config.ts +19 -11
  65. package/src/hotstate/abstractions.ts +48 -0
  66. package/src/hotstate/factory.ts +17 -0
  67. package/src/{secret → hotstate}/index.ts +1 -0
  68. package/src/hotstate/manager.ts +192 -0
  69. package/src/hotstate/memory.ts +100 -0
  70. package/src/hotstate/validation.ts +100 -0
  71. package/src/index.ts +2 -1
  72. package/src/library/abstractions.ts +24 -28
  73. package/src/library/factory.ts +2 -2
  74. package/src/library/local.ts +91 -111
  75. package/src/library/worker/evaluator.ts +36 -73
  76. package/src/library/worker/loader.lite.ts +54 -0
  77. package/src/library/worker/main.ts +15 -66
  78. package/src/library/worker/protocol.ts +6 -33
  79. package/src/lock/abstractions.ts +6 -0
  80. package/src/lock/factory.ts +15 -0
  81. package/src/lock/index.ts +4 -0
  82. package/src/lock/manager.ts +97 -0
  83. package/src/lock/memory.ts +19 -0
  84. package/src/lock/test.ts +108 -0
  85. package/src/orchestrator/manager.ts +118 -90
  86. package/src/orchestrator/operation-workset.ts +181 -93
  87. package/src/orchestrator/operation.ts +1021 -283
  88. package/src/project/abstractions.ts +27 -38
  89. package/src/project/evaluation.ts +248 -0
  90. package/src/project/factory.ts +1 -1
  91. package/src/project/index.ts +1 -2
  92. package/src/project/local.ts +107 -103
  93. package/src/pubsub/abstractions.ts +13 -0
  94. package/src/pubsub/factory.ts +19 -0
  95. package/src/{workspace → pubsub}/index.ts +1 -0
  96. package/src/pubsub/local.ts +36 -0
  97. package/src/pubsub/manager.ts +108 -0
  98. package/src/pubsub/validation.ts +33 -0
  99. package/src/runner/abstractions.ts +155 -68
  100. package/src/runner/artifact-env.ts +160 -0
  101. package/src/runner/factory.ts +20 -5
  102. package/src/runner/force-abort.ts +117 -0
  103. package/src/runner/local.ts +292 -372
  104. package/src/{common → runner}/pulumi.ts +89 -37
  105. package/src/services.ts +251 -40
  106. package/src/shared/index.ts +3 -11
  107. package/src/shared/models/backend/index.ts +3 -0
  108. package/src/shared/{library.ts → models/backend/library.ts} +4 -4
  109. package/src/shared/models/backend/project.ts +82 -0
  110. package/src/shared/models/backend/unlock-method.ts +20 -0
  111. package/src/shared/models/base.ts +68 -0
  112. package/src/shared/models/errors.ts +5 -0
  113. package/src/shared/models/index.ts +4 -0
  114. package/src/shared/models/project/api-key.ts +65 -0
  115. package/src/shared/models/project/artifact.ts +83 -0
  116. package/src/shared/models/project/index.ts +13 -0
  117. package/src/shared/models/project/lock.ts +91 -0
  118. package/src/shared/models/project/model.ts +14 -0
  119. package/src/shared/{operation.ts → models/project/operation.ts} +29 -8
  120. package/src/shared/models/project/page.ts +57 -0
  121. package/src/shared/models/project/secret.ts +98 -0
  122. package/src/shared/models/project/service-account.ts +22 -0
  123. package/src/shared/models/project/state.ts +449 -0
  124. package/src/shared/models/project/terminal.ts +98 -0
  125. package/src/shared/models/project/trigger.ts +56 -0
  126. package/src/shared/models/project/unlock-method.ts +38 -0
  127. package/src/shared/models/project/worker.ts +107 -0
  128. package/src/shared/resolvers/graph-resolver.ts +61 -18
  129. package/src/shared/resolvers/index.ts +5 -0
  130. package/src/shared/resolvers/input-hash.ts +53 -15
  131. package/src/shared/resolvers/input.ts +47 -13
  132. package/src/shared/resolvers/registry.ts +3 -2
  133. package/src/shared/resolvers/state.ts +2 -2
  134. package/src/shared/resolvers/validation.ts +82 -25
  135. package/src/shared/utils/args.ts +25 -0
  136. package/src/shared/{async-batcher.ts → utils/async-batcher.ts} +13 -1
  137. package/src/shared/utils/hash.ts +6 -0
  138. package/src/shared/utils/index.ts +4 -0
  139. package/src/shared/utils/promise-tracker.ts +23 -0
  140. package/src/state/abstractions.ts +199 -131
  141. package/src/state/encryption.ts +98 -0
  142. package/src/state/factory.ts +3 -5
  143. package/src/state/index.ts +4 -0
  144. package/src/state/keyring.ts +22 -0
  145. package/src/state/local/backend.ts +106 -0
  146. package/src/state/local/collection.ts +361 -0
  147. package/src/state/local/index.ts +2 -0
  148. package/src/state/manager.ts +875 -18
  149. package/src/state/memory/backend.ts +70 -0
  150. package/src/state/memory/collection.ts +270 -0
  151. package/src/state/memory/index.ts +2 -0
  152. package/src/state/repository/index.ts +2 -0
  153. package/src/state/repository/repository.index.ts +193 -0
  154. package/src/state/repository/repository.ts +507 -0
  155. package/src/state/test.ts +457 -0
  156. package/src/terminal/{shared.ts → abstractions.ts} +3 -3
  157. package/src/terminal/docker.ts +18 -14
  158. package/src/terminal/factory.ts +3 -3
  159. package/src/terminal/index.ts +1 -1
  160. package/src/terminal/manager.ts +131 -79
  161. package/src/terminal/run.sh.ts +21 -11
  162. package/src/unlock/abstractions.ts +49 -0
  163. package/src/unlock/index.ts +2 -0
  164. package/src/unlock/memory.ts +32 -0
  165. package/src/worker/abstractions.ts +42 -0
  166. package/src/worker/docker.ts +83 -0
  167. package/src/worker/factory.ts +20 -0
  168. package/src/worker/index.ts +3 -0
  169. package/src/worker/manager.ts +167 -0
  170. package/dist/chunk-KTGKNSKM.js +0 -979
  171. package/dist/chunk-KTGKNSKM.js.map +0 -1
  172. package/dist/chunk-WXDYCRTT.js +0 -234
  173. package/dist/chunk-WXDYCRTT.js.map +0 -1
  174. package/src/library/worker/loader.ts +0 -114
  175. package/src/preferences/shared.ts +0 -1
  176. package/src/project/lock.ts +0 -39
  177. package/src/project/manager.ts +0 -433
  178. package/src/secret/abstractions.ts +0 -59
  179. package/src/secret/factory.ts +0 -22
  180. package/src/secret/local.ts +0 -152
  181. package/src/shared/project.ts +0 -62
  182. package/src/shared/state.ts +0 -247
  183. package/src/shared/terminal.ts +0 -14
  184. package/src/state/local.ts +0 -612
  185. package/src/workspace/abstractions.ts +0 -41
  186. package/src/workspace/factory.ts +0 -14
  187. package/src/workspace/local.ts +0 -54
@@ -0,0 +1,167 @@
1
+ import type { Logger } from "pino"
2
+ import type { WorkerBackend } from "./abstractions"
3
+ import type { StateManager } from "../state"
4
+ import type { ApiKeyService, ProjectUnlockService } from "../business"
5
+ import type { LockManager } from "../lock"
6
+ import { PassThrough } from "node:stream"
7
+ import { z } from "zod"
8
+ import c from "ansi-colors"
9
+ import { v7 as uuidv7 } from "uuid"
10
+ import { createAsyncBatcher } from "../shared"
11
+
12
+ export const workerManagerConfig = z.object({
13
+ HIGHSTATE_WORKER_API_PATH: z.string().default("/var/run/highstate.sock"),
14
+ })
15
+
16
+ export class WorkerManager {
17
+ constructor(
18
+ readonly config: z.infer<typeof workerManagerConfig>,
19
+ private readonly workerBackend: WorkerBackend,
20
+ private readonly stateManager: StateManager,
21
+ private readonly projectUnlockService: ProjectUnlockService,
22
+ private readonly lockManager: LockManager,
23
+ private readonly apiKeyService: ApiKeyService,
24
+ private readonly logger: Logger,
25
+ ) {
26
+ this.projectUnlockService.registerUnlockTask(
27
+ //
28
+ "launch-active-workers",
29
+ projectId => this.launchActiveWorkers(projectId),
30
+ )
31
+ }
32
+
33
+ private readonly workerAbortControllers = new Map<string, AbortController>()
34
+
35
+ async startWorker(projectId: string, workerId: string, restart = false): Promise<void> {
36
+ if (this.workerAbortControllers.get(workerId)?.signal.aborted) {
37
+ // if the worker was aborted due to worker deletion, clear logs and exit
38
+ await this.stateManager.getWorkerLogRepository(projectId, workerId).clear()
39
+ return
40
+ }
41
+
42
+ await this.lockManager.acquire(["worker", workerId], async () => {
43
+ const worker = await this.stateManager.getWorkerRepository(projectId).get(workerId)
44
+ if (!worker) {
45
+ throw new Error(`Worker "${workerId}" not found in project "${projectId}"`)
46
+ }
47
+
48
+ if (!worker.apiKeyId) {
49
+ throw new Error(`Worker "${workerId}" does not have an API key associated`)
50
+ }
51
+
52
+ if (worker.failedStartAttempts === 5) {
53
+ this.logger.debug(
54
+ { projectId },
55
+ `skipping worker "%s" start attempt since no attempts left`,
56
+ worker.id,
57
+ )
58
+
59
+ return
60
+ }
61
+
62
+ worker.status = "starting"
63
+
64
+ if (restart) {
65
+ worker.failedStartAttempts += 1
66
+ }
67
+
68
+ await this.stateManager.getWorkerRepository(projectId).putItem(worker)
69
+
70
+ const apiKey = await this.apiKeyService.regenerateToken(projectId, worker.apiKeyId)
71
+ const stdout = new PassThrough()
72
+
73
+ await this.writeSystemMessage(
74
+ projectId,
75
+ worker.id,
76
+ `starting worker container, attempt ${worker.failedStartAttempts + 1}/5`,
77
+ )
78
+
79
+ const logBatcher = createAsyncBatcher<string>(async logs => {
80
+ await this.stateManager
81
+ .getWorkerLogRepository(projectId, worker.id)
82
+ .putMany(logs.map(log => [uuidv7(), log]))
83
+ })
84
+
85
+ stdout.on("data", chunk => {
86
+ const log = String(chunk)
87
+
88
+ logBatcher.call(log)
89
+ })
90
+
91
+ const abortController = new AbortController()
92
+ this.workerAbortControllers.set(workerId, abortController)
93
+
94
+ void this.workerBackend
95
+ .run({
96
+ projectId,
97
+ worker,
98
+ apiPath: this.config.HIGHSTATE_WORKER_API_PATH,
99
+ apiKey: apiKey.token,
100
+ stdout,
101
+ signal: abortController.signal,
102
+ })
103
+ // regardless the exit reason, we want to restart the worker if it has remaining attempts
104
+ .finally(() => void this.startWorker(projectId, worker.id, true))
105
+ })
106
+ }
107
+
108
+ async writeSystemMessage(projectId: string, workerId: string, message: string): Promise<void> {
109
+ const prefix = c.bold.magenta("[runtime]")
110
+
111
+ await this.stateManager
112
+ .getWorkerLogRepository(projectId, workerId)
113
+ .put(uuidv7(), `${prefix} ${message}`)
114
+ }
115
+
116
+ async setWorkerRunning(projectId: string, workerId: string): Promise<void> {
117
+ await this.lockManager.acquire(["worker", workerId], async () => {
118
+ const worker = await this.stateManager.getWorkerRepository(projectId).get(workerId)
119
+ if (!worker) {
120
+ throw new Error(`Worker "${workerId}" not found in project "${projectId}"`)
121
+ }
122
+
123
+ worker.status = "running"
124
+ worker.failedStartAttempts = 0
125
+
126
+ await this.stateManager.getWorkerRepository(projectId).putItem(worker)
127
+
128
+ this.logger.debug(
129
+ { projectId, workerId },
130
+ `worker "%s" is now running in project "%s"`,
131
+ workerId,
132
+ projectId,
133
+ )
134
+ })
135
+ }
136
+
137
+ stopWorker(projectId: string, workerId: string): void {
138
+ const abortController = this.workerAbortControllers.get(workerId)
139
+ if (!abortController) {
140
+ this.logger.warn(
141
+ { projectId, workerId },
142
+ `worker "%s" is not running in project "%s", cannot stop`,
143
+ workerId,
144
+ projectId,
145
+ )
146
+
147
+ return
148
+ }
149
+
150
+ abortController.abort()
151
+ }
152
+
153
+ private async launchActiveWorkers(projectId: string): Promise<void> {
154
+ const workers = await this.stateManager.getWorkerRepository(projectId).getAllItems()
155
+
156
+ this.logger.debug(
157
+ { projectId, workerCount: workers.length },
158
+ `launching %s active workers for project "%s"`,
159
+ workers.length,
160
+ projectId,
161
+ )
162
+
163
+ for (const worker of workers) {
164
+ void this.startWorker(projectId, worker.id)
165
+ }
166
+ }
167
+ }