@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.
@@ -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.hash, artifact.chunkSize)
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", hash: artifact.hash, path: artifactPath })
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 })
@@ -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-${unitId}-`))
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
  }