@nosana/node 1.1.28-rc → 1.1.29-rc

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nosana/node",
3
- "version": "1.1.28-rc",
3
+ "version": "1.1.29-rc",
4
4
  "description": "",
5
5
  "bin": {
6
6
  "nosana-node": "./dist/src/index.js"
@@ -2,6 +2,16 @@ import { Resource } from '@nosana/sdk/dist/types/resources.js';
2
2
  import { RequiredResource } from '@nosana/sdk';
3
3
  import { ContainerOrchestrationInterface } from '../../../provider/containerOrchestration/interface.js';
4
4
  import { NodeRepository } from '../../../repository/NodeRepository.js';
5
+ /**
6
+ * The reason the resource manager gave for failing, if it gave one.
7
+ *
8
+ * It reports failures as a JSON line on stderr — `{"event":"error","message":
9
+ * "..."}` — from every service it implements, then exits non-zero. Read the
10
+ * last such line, since a run may log several before giving up.
11
+ */
12
+ export declare function findReportedError(logs: {
13
+ log?: string;
14
+ }[]): string | undefined;
5
15
  export declare class VolumeManager {
6
16
  private containerOrchestration;
7
17
  private repository;
@@ -11,6 +11,43 @@ import { createHFArgs } from '../helpers/createHFArgs.js';
11
11
  import { createS3Args } from '../helpers/createS3Args.js';
12
12
  import { createOllamaArgs } from '../helpers/createOllamaArgs.js';
13
13
  import { liveAbortSignal } from '../../../utils/liveAbortSignal.js';
14
+ /**
15
+ * Renders the runtime state that says why the download stopped, for inclusion in
16
+ * the error message. A process that is killed rather than failing logs nothing,
17
+ * so this is the only evidence of an OOM.
18
+ *
19
+ * Optional because the caller inspects on a best-effort basis; the fields
20
+ * themselves are always present when it succeeds.
21
+ */
22
+ function describeContainerState(state) {
23
+ if (!state)
24
+ return '';
25
+ const parts = [
26
+ `exitCode: ${state.ExitCode}`,
27
+ `OOMKilled: ${state.OOMKilled}`
28
+ ];
29
+ return ` [${parts.join(', ')}]`;
30
+ }
31
+ /**
32
+ * The reason the resource manager gave for failing, if it gave one.
33
+ *
34
+ * It reports failures as a JSON line on stderr — `{"event":"error","message":
35
+ * "..."}` — from every service it implements, then exits non-zero. Read the
36
+ * last such line, since a run may log several before giving up.
37
+ */
38
+ export function findReportedError(logs) {
39
+ for (const log of logs.reverse()) {
40
+ if (log.log?.includes('{"event":"error"')) {
41
+ try {
42
+ const parsed = JSON.parse(log.log.slice(log.log.indexOf('{')));
43
+ if (typeof parsed.message === 'string')
44
+ return parsed.message;
45
+ }
46
+ catch { }
47
+ }
48
+ }
49
+ return undefined;
50
+ }
14
51
  export class VolumeManager {
15
52
  constructor(containerOrchestration, repository) {
16
53
  this.containerOrchestration = containerOrchestration;
@@ -149,12 +186,21 @@ export class VolumeManager {
149
186
  timestamps: true,
150
187
  });
151
188
  const { logs } = extractLogsAndResultsFromLogBuffer(errrorBuffer, undefined);
189
+ // Read the state before removing it: a killed process logs nothing, so
190
+ // the runtime's own record is the only account of why.
191
+ const state = await container
192
+ .inspect()
193
+ .then(({ State }) => State)
194
+ .catch(() => undefined);
152
195
  await container.remove({ force: true });
153
196
  await this.containerOrchestration.deleteVolume(volume);
154
- const errorLog = logs.find(({ log }) => log?.startsWith('Error:'));
155
- if (errorLog) {
156
- throw new Error(errorLog.log?.replace('Error: ', ''));
157
- }
197
+ // A non-zero exit is a failed download whether or not the container
198
+ // managed to report a reason, so this must throw either way: returning
199
+ // normally here reports success for a volume already deleted, and the run
200
+ // then fails later with the cause lost.
201
+ const reason = findReportedError(logs) ??
202
+ `resource download failed (exit code ${StatusCode})`;
203
+ throw new Error(`${reason}${describeContainerState(state)}`);
158
204
  }
159
205
  this.progressBarReporter.stop(`${syncing ? 'Synced' : 'Downloaded'} resource ${name} completed`);
160
206
  await this.containerOrchestration.stopAndDeleteContainer(container.id);
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@nosana/node",
3
- "version": "1.1.28-rc",
3
+ "version": "1.1.29-rc",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@nosana/node",
9
- "version": "1.1.28-rc",
9
+ "version": "1.1.29-rc",
10
10
  "license": "ISC",
11
11
  "dependencies": {
12
12
  "@coral-xyz/anchor": "^0.28.1-beta.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nosana/node",
3
- "version": "1.1.28-rc",
3
+ "version": "1.1.29-rc",
4
4
  "description": "",
5
5
  "bin": {
6
6
  "nosana-node": "./dist/src/index.js"