@highstate/backend 0.9.15 → 0.9.16

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 (144) hide show
  1. package/dist/chunk-RCB4AFGD.js +159 -0
  2. package/dist/chunk-RCB4AFGD.js.map +1 -0
  3. package/dist/chunk-WHALQHEZ.js +2017 -0
  4. package/dist/chunk-WHALQHEZ.js.map +1 -0
  5. package/dist/highstate.manifest.json +3 -3
  6. package/dist/index.js +6158 -2178
  7. package/dist/index.js.map +1 -1
  8. package/dist/library/worker/main.js +47 -155
  9. package/dist/library/worker/main.js.map +1 -1
  10. package/dist/shared/index.js +159 -41
  11. package/package.json +25 -7
  12. package/src/artifact/abstractions.ts +46 -0
  13. package/src/artifact/encryption.ts +69 -0
  14. package/src/artifact/factory.ts +36 -0
  15. package/src/artifact/index.ts +3 -0
  16. package/src/artifact/local.ts +142 -0
  17. package/src/business/api-key.ts +65 -0
  18. package/src/business/artifact.ts +288 -0
  19. package/src/business/backend-unlock.ts +10 -0
  20. package/src/business/index.ts +9 -0
  21. package/src/business/instance-lock.ts +124 -0
  22. package/src/business/instance-state.ts +292 -0
  23. package/src/business/operation.ts +251 -0
  24. package/src/business/project-unlock.ts +242 -0
  25. package/src/business/secret.ts +187 -0
  26. package/src/business/worker.ts +161 -0
  27. package/src/common/index.ts +2 -1
  28. package/src/common/performance.ts +44 -0
  29. package/src/common/tree.ts +33 -0
  30. package/src/common/utils.ts +40 -1
  31. package/src/config.ts +14 -10
  32. package/src/hotstate/abstractions.ts +48 -0
  33. package/src/hotstate/factory.ts +17 -0
  34. package/src/{secret → hotstate}/index.ts +1 -0
  35. package/src/hotstate/manager.ts +192 -0
  36. package/src/hotstate/memory.ts +100 -0
  37. package/src/hotstate/validation.ts +101 -0
  38. package/src/index.ts +2 -1
  39. package/src/library/abstractions.ts +10 -23
  40. package/src/library/factory.ts +2 -2
  41. package/src/library/local.ts +89 -102
  42. package/src/library/worker/evaluator.ts +9 -42
  43. package/src/library/worker/loader.lite.ts +41 -0
  44. package/src/library/worker/main.ts +14 -65
  45. package/src/library/worker/protocol.ts +8 -24
  46. package/src/lock/abstractions.ts +6 -0
  47. package/src/lock/factory.ts +15 -0
  48. package/src/{workspace → lock}/index.ts +1 -0
  49. package/src/lock/manager.ts +82 -0
  50. package/src/lock/memory.ts +19 -0
  51. package/src/orchestrator/manager.ts +129 -82
  52. package/src/orchestrator/operation-workset.ts +168 -77
  53. package/src/orchestrator/operation.ts +967 -284
  54. package/src/project/abstractions.ts +20 -7
  55. package/src/project/factory.ts +1 -1
  56. package/src/project/index.ts +0 -1
  57. package/src/project/local.ts +73 -17
  58. package/src/project/manager.ts +272 -131
  59. package/src/pubsub/abstractions.ts +13 -0
  60. package/src/pubsub/factory.ts +19 -0
  61. package/src/pubsub/index.ts +3 -0
  62. package/src/pubsub/local.ts +36 -0
  63. package/src/pubsub/manager.ts +100 -0
  64. package/src/pubsub/validation.ts +33 -0
  65. package/src/runner/abstractions.ts +135 -68
  66. package/src/runner/artifact-env.ts +160 -0
  67. package/src/runner/factory.ts +20 -5
  68. package/src/runner/force-abort.ts +117 -0
  69. package/src/runner/local.ts +281 -371
  70. package/src/{common → runner}/pulumi.ts +86 -37
  71. package/src/services.ts +193 -35
  72. package/src/shared/index.ts +3 -11
  73. package/src/shared/models/backend/index.ts +3 -0
  74. package/src/shared/models/backend/project.ts +63 -0
  75. package/src/shared/models/backend/unlock-method.ts +20 -0
  76. package/src/shared/models/base.ts +151 -0
  77. package/src/shared/models/errors.ts +5 -0
  78. package/src/shared/models/index.ts +4 -0
  79. package/src/shared/models/project/api-key.ts +62 -0
  80. package/src/shared/models/project/artifact.ts +113 -0
  81. package/src/shared/models/project/component.ts +45 -0
  82. package/src/shared/models/project/index.ts +14 -0
  83. package/src/shared/{project.ts → models/project/instance.ts} +12 -0
  84. package/src/shared/models/project/lock.ts +91 -0
  85. package/src/shared/{operation.ts → models/project/operation.ts} +28 -7
  86. package/src/shared/models/project/page.ts +57 -0
  87. package/src/shared/models/project/secret.ts +112 -0
  88. package/src/shared/models/project/service-account.ts +22 -0
  89. package/src/shared/models/project/state.ts +432 -0
  90. package/src/shared/models/project/terminal.ts +99 -0
  91. package/src/shared/models/project/trigger.ts +56 -0
  92. package/src/shared/models/project/unlock-method.ts +31 -0
  93. package/src/shared/models/project/worker.ts +105 -0
  94. package/src/shared/resolvers/graph-resolver.ts +28 -0
  95. package/src/shared/resolvers/index.ts +5 -0
  96. package/src/shared/resolvers/input-hash.ts +53 -15
  97. package/src/shared/resolvers/input.ts +1 -9
  98. package/src/shared/resolvers/registry.ts +3 -2
  99. package/src/shared/resolvers/state.ts +2 -2
  100. package/src/shared/resolvers/validation.ts +61 -20
  101. package/src/shared/{async-batcher.ts → utils/async-batcher.ts} +13 -1
  102. package/src/shared/utils/hash.ts +6 -0
  103. package/src/shared/utils/index.ts +3 -0
  104. package/src/shared/utils/promise-tracker.ts +23 -0
  105. package/src/state/abstractions.ts +330 -101
  106. package/src/state/encryption.ts +59 -0
  107. package/src/state/factory.ts +3 -5
  108. package/src/state/index.ts +3 -0
  109. package/src/state/keyring.ts +22 -0
  110. package/src/state/local/backend.ts +299 -0
  111. package/src/state/local/collection.ts +342 -0
  112. package/src/state/local/index.ts +2 -0
  113. package/src/state/manager.ts +804 -18
  114. package/src/state/repository/index.ts +2 -0
  115. package/src/state/repository/repository.index.ts +193 -0
  116. package/src/state/repository/repository.ts +458 -0
  117. package/src/terminal/{shared.ts → abstractions.ts} +3 -3
  118. package/src/terminal/docker.ts +18 -14
  119. package/src/terminal/factory.ts +3 -3
  120. package/src/terminal/index.ts +1 -1
  121. package/src/terminal/manager.ts +131 -79
  122. package/src/terminal/run.sh.ts +21 -11
  123. package/src/worker/abstractions.ts +42 -0
  124. package/src/worker/docker.ts +83 -0
  125. package/src/worker/factory.ts +20 -0
  126. package/src/worker/index.ts +3 -0
  127. package/src/worker/manager.ts +139 -0
  128. package/dist/chunk-KTGKNSKM.js +0 -979
  129. package/dist/chunk-KTGKNSKM.js.map +0 -1
  130. package/dist/chunk-WXDYCRTT.js +0 -234
  131. package/dist/chunk-WXDYCRTT.js.map +0 -1
  132. package/src/library/worker/loader.ts +0 -114
  133. package/src/preferences/shared.ts +0 -1
  134. package/src/project/lock.ts +0 -39
  135. package/src/secret/abstractions.ts +0 -59
  136. package/src/secret/factory.ts +0 -22
  137. package/src/secret/local.ts +0 -152
  138. package/src/shared/state.ts +0 -247
  139. package/src/shared/terminal.ts +0 -14
  140. package/src/state/local.ts +0 -612
  141. package/src/workspace/abstractions.ts +0 -41
  142. package/src/workspace/factory.ts +0 -14
  143. package/src/workspace/local.ts +0 -54
  144. /package/src/shared/{library.ts → models/backend/library.ts} +0 -0
@@ -0,0 +1,139 @@
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
+ async startWorker(projectId: string, workerId: string, restart = false): Promise<void> {
34
+ await this.lockManager.acquire(["worker", workerId], async () => {
35
+ const worker = await this.stateManager.getWorkerRepository(projectId).get(workerId)
36
+ if (!worker) {
37
+ throw new Error(`Worker "${workerId}" not found in project "${projectId}"`)
38
+ }
39
+
40
+ if (!worker.apiKeyId) {
41
+ throw new Error(`Worker "${workerId}" does not have an API key associated`)
42
+ }
43
+
44
+ if (worker.failedStartAttempts === 5) {
45
+ this.logger.debug(
46
+ { projectId },
47
+ `skipping worker "%s" start attempt since no attempts left`,
48
+ worker.id,
49
+ )
50
+
51
+ return
52
+ }
53
+
54
+ worker.status = "starting"
55
+
56
+ if (restart) {
57
+ worker.failedStartAttempts += 1
58
+ }
59
+
60
+ await this.stateManager.getWorkerRepository(projectId).putItem(worker)
61
+
62
+ const apiKey = await this.apiKeyService.regenerateToken(projectId, worker.apiKeyId)
63
+ const stdout = new PassThrough()
64
+
65
+ await this.writeSystemMessage(
66
+ projectId,
67
+ worker.id,
68
+ `starting worker container, attempt ${worker.failedStartAttempts + 1}/5`,
69
+ )
70
+
71
+ const logBatcher = createAsyncBatcher<string>(async logs => {
72
+ await this.stateManager
73
+ .getWorkerLogRepository(projectId, worker.id)
74
+ .putMany(logs.map(log => [uuidv7(), log]))
75
+ })
76
+
77
+ stdout.on("data", chunk => {
78
+ const log = String(chunk)
79
+
80
+ logBatcher.call(log)
81
+ })
82
+
83
+ void this.workerBackend
84
+ .run({
85
+ projectId,
86
+ worker,
87
+ apiPath: this.config.HIGHSTATE_WORKER_API_PATH,
88
+ apiKey: apiKey.token,
89
+ stdout,
90
+ })
91
+ // regardless the exit reason, we want to restart the worker if it has remaining attempts
92
+ .finally(() => void this.startWorker(projectId, worker.id, true))
93
+ })
94
+ }
95
+
96
+ async writeSystemMessage(projectId: string, workerId: string, message: string): Promise<void> {
97
+ const prefix = c.bold.magenta("[runtime]")
98
+
99
+ await this.stateManager
100
+ .getWorkerLogRepository(projectId, workerId)
101
+ .put(uuidv7(), `${prefix} ${message}`)
102
+ }
103
+
104
+ async setWorkerRunning(projectId: string, workerId: string): Promise<void> {
105
+ await this.lockManager.acquire(["worker", workerId], async () => {
106
+ const worker = await this.stateManager.getWorkerRepository(projectId).get(workerId)
107
+ if (!worker) {
108
+ throw new Error(`Worker "${workerId}" not found in project "${projectId}"`)
109
+ }
110
+
111
+ worker.status = "running"
112
+ worker.failedStartAttempts = 0
113
+
114
+ await this.stateManager.getWorkerRepository(projectId).putItem(worker)
115
+
116
+ this.logger.debug(
117
+ { projectId, workerId },
118
+ `worker "%s" is now running in project "%s"`,
119
+ workerId,
120
+ projectId,
121
+ )
122
+ })
123
+ }
124
+
125
+ private async launchActiveWorkers(projectId: string): Promise<void> {
126
+ const workers = await this.stateManager.getWorkerRepository(projectId).getAllItems()
127
+
128
+ this.logger.debug(
129
+ { projectId, workerCount: workers.length },
130
+ `launching %s active workers for project "%s"`,
131
+ workers.length,
132
+ projectId,
133
+ )
134
+
135
+ for (const worker of workers) {
136
+ void this.startWorker(projectId, worker.id)
137
+ }
138
+ }
139
+ }