@highstate/backend 0.9.33 → 0.9.34
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/dist/index.js +415 -194
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
- package/src/artifact/local.ts +10 -7
- package/src/business/artifact.test.ts +7 -337
- package/src/business/artifact.ts +5 -56
- package/src/business/instance-state.test.ts +6 -1
- package/src/business/instance-state.ts +16 -0
- package/src/business/unit-extra.test.ts +113 -0
- package/src/business/unit-extra.ts +40 -0
- package/src/library/local.ts +431 -141
- package/src/orchestrator/operation.ts +8 -3
- package/src/runner/abstractions.ts +7 -0
- package/src/runner/artifact-env.ts +6 -4
- package/src/runner/local.ts +15 -2
|
@@ -566,9 +566,6 @@ export class RuntimeOperation {
|
|
|
566
566
|
|
|
567
567
|
await this.watchStateStream(state, type, name, logger)
|
|
568
568
|
|
|
569
|
-
// clean up artifacts after successful destruction
|
|
570
|
-
await this.artifactService.clearInstanceArtifactReferences(this.project.id, instance.id)
|
|
571
|
-
|
|
572
569
|
logger.info("unit destroyed")
|
|
573
570
|
})
|
|
574
571
|
}
|
|
@@ -736,6 +733,10 @@ export class RuntimeOperation {
|
|
|
736
733
|
statusFields: update.statusFields ?? null,
|
|
737
734
|
}
|
|
738
735
|
|
|
736
|
+
const artifactIds = update.exportedArtifactIds
|
|
737
|
+
? Object.values(update.exportedArtifactIds).flat()
|
|
738
|
+
: []
|
|
739
|
+
|
|
739
740
|
if (update.operationType !== "destroy") {
|
|
740
741
|
// давайте еще больше усложним и без того сложную штуку
|
|
741
742
|
// set output hash before calculating input hash to capture up-to-date output hash for dependencies
|
|
@@ -749,6 +750,8 @@ export class RuntimeOperation {
|
|
|
749
750
|
data.dependencyOutputHash = dependencyOutputHash
|
|
750
751
|
data.outputHash = update.outputHash
|
|
751
752
|
|
|
753
|
+
data.exportedArtifactIds = update.exportedArtifactIds
|
|
754
|
+
|
|
752
755
|
// also update the parent ID
|
|
753
756
|
if (instance.parentId) {
|
|
754
757
|
const parentState = this.context.getState(instance.parentId)
|
|
@@ -763,6 +766,7 @@ export class RuntimeOperation {
|
|
|
763
766
|
data.parentId = null
|
|
764
767
|
data.model = null
|
|
765
768
|
data.resolvedInputs = null
|
|
769
|
+
data.exportedArtifactIds = null
|
|
766
770
|
}
|
|
767
771
|
|
|
768
772
|
// update the operation state
|
|
@@ -786,6 +790,7 @@ export class RuntimeOperation {
|
|
|
786
790
|
triggers: update.triggers ?? [],
|
|
787
791
|
workers: update.workers ?? [],
|
|
788
792
|
secrets: update.secrets ?? {},
|
|
793
|
+
artifactIds,
|
|
789
794
|
}
|
|
790
795
|
: undefined,
|
|
791
796
|
})
|
|
@@ -90,6 +90,13 @@ export type UnitStateUpdate = {
|
|
|
90
90
|
* The workers produced by the unit.
|
|
91
91
|
*/
|
|
92
92
|
workers?: UnitWorker[] | null
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* The IDs of the artifacts exported by the unit.
|
|
96
|
+
*
|
|
97
|
+
* The keys are the output names, and the values are the IDs of the artifacts exported for that output.
|
|
98
|
+
*/
|
|
99
|
+
exportedArtifactIds?: Record<string, string[]> | null
|
|
93
100
|
}
|
|
94
101
|
)
|
|
95
102
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { UnitArtifact } from "@highstate/contract"
|
|
2
1
|
import type { Logger } from "pino"
|
|
3
2
|
import type { ArtifactBackend, ArtifactService } from "../artifact"
|
|
4
3
|
import type { Artifact } from "../database"
|
|
@@ -7,6 +6,7 @@ import { createReadStream, createWriteStream } from "node:fs"
|
|
|
7
6
|
import { mkdtemp, readdir } from "node:fs/promises"
|
|
8
7
|
import { join } from "node:path"
|
|
9
8
|
import { pipeline } from "node:stream/promises"
|
|
9
|
+
import { type UnitArtifact, unitArtifactId } from "@highstate/contract"
|
|
10
10
|
|
|
11
11
|
export interface ArtifactEnvironment {
|
|
12
12
|
readPath: string | null
|
|
@@ -45,7 +45,7 @@ export async function setupArtifactEnvironment(
|
|
|
45
45
|
await Promise.all(
|
|
46
46
|
artifacts.map(async artifact => {
|
|
47
47
|
const artifactPath = join(readDir!, `${artifact.hash}.tgz`)
|
|
48
|
-
const stream = await artifactBackend.retrieve(projectId, artifact.
|
|
48
|
+
const stream = await artifactBackend.retrieve(projectId, artifact.id, artifact.chunkSize)
|
|
49
49
|
|
|
50
50
|
if (!stream) {
|
|
51
51
|
throw new Error(`artifact not found: ${artifact.hash}`)
|
|
@@ -54,7 +54,7 @@ export async function setupArtifactEnvironment(
|
|
|
54
54
|
const writeStream = createWriteStream(artifactPath)
|
|
55
55
|
await pipeline(stream, writeStream)
|
|
56
56
|
|
|
57
|
-
logger.debug({ msg: "downloaded artifact",
|
|
57
|
+
logger.debug({ msg: "downloaded artifact", id: artifact.id, path: artifactPath })
|
|
58
58
|
}),
|
|
59
59
|
)
|
|
60
60
|
} else {
|
|
@@ -123,7 +123,7 @@ export async function collectAndStoreArtifacts(
|
|
|
123
123
|
|
|
124
124
|
await using readStream = createReadStream(filePath)
|
|
125
125
|
|
|
126
|
-
await artifactManager.store(
|
|
126
|
+
const storedArtifact = await artifactManager.store(
|
|
127
127
|
projectId,
|
|
128
128
|
expectedHash,
|
|
129
129
|
fileSize,
|
|
@@ -141,6 +141,8 @@ export async function collectAndStoreArtifacts(
|
|
|
141
141
|
},
|
|
142
142
|
)
|
|
143
143
|
|
|
144
|
+
artifact[unitArtifactId] = storedArtifact.id
|
|
145
|
+
|
|
144
146
|
logger.debug({ msg: "stored artifact", hash: expectedHash, file: filePath })
|
|
145
147
|
} catch (error) {
|
|
146
148
|
logger.error({ msg: "failed to store artifact", file: filePath, error })
|
package/src/runner/local.ts
CHANGED
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
HighstateConfigKey,
|
|
25
25
|
type InstanceId,
|
|
26
26
|
instanceStatusFieldSchema,
|
|
27
|
+
unitArtifactId,
|
|
27
28
|
unitArtifactSchema,
|
|
28
29
|
unitPageSchema,
|
|
29
30
|
unitTerminalSchema,
|
|
@@ -33,7 +34,7 @@ import {
|
|
|
33
34
|
import { encode } from "@msgpack/msgpack"
|
|
34
35
|
import { sha256 } from "@noble/hashes/sha2"
|
|
35
36
|
import { ensureDependencyInstalled } from "nypm"
|
|
36
|
-
import { omitBy } from "remeda"
|
|
37
|
+
import { mapValues, omitBy } from "remeda"
|
|
37
38
|
import { z } from "zod"
|
|
38
39
|
import { runWithRetryOnError } from "../common"
|
|
39
40
|
import {
|
|
@@ -109,7 +110,7 @@ export class LocalRunnerBackend implements RunnerBackend {
|
|
|
109
110
|
|
|
110
111
|
try {
|
|
111
112
|
// create unit-specific temp directory for better cleanup reliability
|
|
112
|
-
unitTempPath = await mkdtemp(join(tmpdir(), `highstate-unit-${
|
|
113
|
+
unitTempPath = await mkdtemp(join(tmpdir(), `highstate-unit-${options.stateId}-`))
|
|
113
114
|
childLogger.debug({ msg: "created unit temp directory", unitTempPath })
|
|
114
115
|
options.signal?.throwIfAborted()
|
|
115
116
|
|
|
@@ -221,6 +222,18 @@ export class LocalRunnerBackend implements RunnerBackend {
|
|
|
221
222
|
Object.values(artifacts).flat(),
|
|
222
223
|
childLogger,
|
|
223
224
|
)
|
|
225
|
+
|
|
226
|
+
completionUpdate.exportedArtifactIds = mapValues(artifacts, artifacts => {
|
|
227
|
+
return artifacts.map(artifact => {
|
|
228
|
+
if (artifact[unitArtifactId]) {
|
|
229
|
+
return artifact[unitArtifactId]
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
throw new Error(
|
|
233
|
+
`Failed to determine artifact ID for artifact with hash ${artifact.hash}`,
|
|
234
|
+
)
|
|
235
|
+
})
|
|
236
|
+
})
|
|
224
237
|
} else if (preview && outputs["$artifacts"]) {
|
|
225
238
|
childLogger.debug({ msg: "skipping artifact persistence for preview" })
|
|
226
239
|
}
|