@nosana/node 1.1.54-rc → 1.1.55-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.54-rc",
3
+ "version": "1.1.55-rc",
4
4
  "description": "",
5
5
  "bin": {
6
6
  "nosana-node": "./dist/src/index.js"
@@ -1,12 +1,21 @@
1
+ import { DockerAuth } from '@nosana/sdk';
1
2
  import { ContainerOrchestrationInterface } from '../../../provider/containerOrchestration/interface.js';
2
3
  import { NodeRepository } from '../../../repository/NodeRepository.js';
4
+ /**
5
+ * An image the market requires, and the registry credentials it takes to pull
6
+ * it. Public images carry none.
7
+ */
8
+ export type RequiredImage = {
9
+ name: string;
10
+ auth?: DockerAuth;
11
+ };
3
12
  export declare class ImageManager {
4
13
  private containerOrchestration;
5
14
  private repository;
6
15
  private fetched;
7
16
  private market_required_images;
8
17
  constructor(containerOrchestration: ContainerOrchestrationInterface, repository: NodeRepository);
9
- pullMarketRequiredImages(required_images: string[]): Promise<void>;
18
+ pullMarketRequiredImages(required_images: RequiredImage[]): Promise<void>;
10
19
  pruneImages(): Promise<void>;
11
20
  resyncImagesDB(): Promise<void>;
12
21
  setImage(image: string, isPrivate?: boolean): Promise<void>;
@@ -11,18 +11,24 @@ export class ImageManager {
11
11
  }
12
12
  async pullMarketRequiredImages(required_images) {
13
13
  this.fetched = true;
14
- this.market_required_images = required_images;
15
- for (const image of required_images) {
16
- if (!(await this.containerOrchestration.hasImage(image))) {
17
- await this.containerOrchestration.pullImage(image);
18
- }
19
- if (!this.repository.getImageResource(image)) {
20
- this.repository.updateImageResource(image, {
21
- required: true,
22
- lastUsed: new Date(),
23
- usage: 1,
24
- });
14
+ this.market_required_images = required_images.map(({ name }) => name);
15
+ for (const { name, auth } of required_images) {
16
+ if (!(await this.containerOrchestration.hasImage(name))) {
17
+ await this.containerOrchestration.pullImage(name, auth);
25
18
  }
19
+ // Written whether or not the image is already known: an image a job
20
+ // pulled first has an entry that says nothing about the market requiring
21
+ // it, and `pruneImages` deletes anything not marked required. `isPrivate`
22
+ // carries the same weight it does for a job image — a credentialed image
23
+ // is dropped rather than left cached — and only takes effect once the
24
+ // market stops requiring this one.
25
+ const known = this.repository.getImageResource(name);
26
+ this.repository.updateImageResource(name, {
27
+ required: true,
28
+ isPrivate: !!auth,
29
+ lastUsed: known?.lastUsed ?? new Date(),
30
+ usage: known?.usage ?? 1,
31
+ });
26
32
  }
27
33
  }
28
34
  async pruneImages() {
@@ -2,7 +2,7 @@ import { Market, RequiredResource } from '@nosana/sdk';
2
2
  import { Resource } from '@nosana/sdk/dist/types/resources.js';
3
3
  import { ContainerOrchestrationInterface } from '../../provider/containerOrchestration/interface.js';
4
4
  import { NodeRepository } from '../../repository/NodeRepository.js';
5
- import { ImageManager } from './image/imageManager.js';
5
+ import { ImageManager, RequiredImage } from './image/imageManager.js';
6
6
  import { JobContext, VolumeManager } from './volume/volumeManager.js';
7
7
  /**
8
8
  * The market endpoint reports an HF resource's model as `url`, the field it
@@ -14,6 +14,27 @@ import { JobContext, VolumeManager } from './volume/volumeManager.js';
14
14
  * boundary, but the same manager serves job resources.
15
15
  */
16
16
  export declare function normalizeMarketResources(resources: RequiredResource[]): RequiredResource[];
17
+ /**
18
+ * A required image as the market endpoint reports it. It reported bare image
19
+ * names before it could carry registry credentials, and the node and the host
20
+ * manager release independently, so a node has to read both shapes: the string
21
+ * form outlives the field it was replaced by.
22
+ */
23
+ export type MarketRequiredImage = string | {
24
+ name: string;
25
+ server?: string;
26
+ username?: string;
27
+ password?: string;
28
+ };
29
+ /**
30
+ * Translates market required images into the shape the pull path reads.
31
+ *
32
+ * Credentials ride along only when the market names an account to pull as. A
33
+ * `server` on its own names a registry without authenticating to it, and the
34
+ * node still pulls from it anonymously, so it is not enough on its own to make
35
+ * the image a private one.
36
+ */
37
+ export declare function normalizeMarketImages(required_images: MarketRequiredImage[]): RequiredImage[];
17
38
  export declare class ResourceManager {
18
39
  private containerOrchestration;
19
40
  private repository;
@@ -21,6 +21,24 @@ export function normalizeMarketResources(resources) {
21
21
  return { ...hf, repo: hf.url };
22
22
  });
23
23
  }
24
+ /**
25
+ * Translates market required images into the shape the pull path reads.
26
+ *
27
+ * Credentials ride along only when the market names an account to pull as. A
28
+ * `server` on its own names a registry without authenticating to it, and the
29
+ * node still pulls from it anonymously, so it is not enough on its own to make
30
+ * the image a private one.
31
+ */
32
+ export function normalizeMarketImages(required_images) {
33
+ return required_images.map((image) => {
34
+ if (typeof image === 'string')
35
+ return { name: image };
36
+ const { name, server, username, password } = image;
37
+ if (!username && !password)
38
+ return { name };
39
+ return { name, auth: { server, username, password } };
40
+ });
41
+ }
24
42
  export class ResourceManager {
25
43
  constructor(containerOrchestration, repository) {
26
44
  this.containerOrchestration = containerOrchestration;
@@ -42,7 +60,7 @@ export class ResourceManager {
42
60
  if (!data) {
43
61
  return;
44
62
  }
45
- await this.images.pullMarketRequiredImages(data.required_images);
63
+ await this.images.pullMarketRequiredImages(normalizeMarketImages(data.required_images));
46
64
  await this.volumes.pullMarketRequiredVolumes(normalizeMarketResources(data.required_remote_resources));
47
65
  }
48
66
  catch (error) {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@nosana/node",
3
- "version": "1.1.54-rc",
3
+ "version": "1.1.55-rc",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@nosana/node",
9
- "version": "1.1.54-rc",
9
+ "version": "1.1.55-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.54-rc",
3
+ "version": "1.1.55-rc",
4
4
  "description": "",
5
5
  "bin": {
6
6
  "nosana-node": "./dist/src/index.js"