@nosana/node 1.1.14-rc → 1.1.15
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/.env.dev +1 -2
- package/dist/.env.prd +1 -2
- package/dist/package.json +4 -2
- package/dist/src/NodeManager/checkForMaintenance.d.ts +1 -0
- package/dist/src/NodeManager/checkForMaintenance.js +40 -0
- package/dist/src/NodeManager/clients/hostManager/index.d.ts +4 -0
- package/dist/src/NodeManager/clients/hostManager/index.js +25 -0
- package/dist/src/NodeManager/clients/maintenanceMiddleware.d.ts +2 -0
- package/dist/src/NodeManager/clients/maintenanceMiddleware.js +11 -0
- package/dist/src/NodeManager/clients/maintenanceState.d.ts +10 -0
- package/dist/src/NodeManager/clients/maintenanceState.js +66 -0
- package/dist/src/NodeManager/clients/types.utils.d.ts +45 -0
- package/dist/src/NodeManager/configs/configs.d.ts +1 -3
- package/dist/src/NodeManager/configs/configs.js +1 -3
- package/dist/src/NodeManager/errors/NodeBannedError.d.ts +3 -0
- package/dist/src/NodeManager/errors/NodeBannedError.js +6 -0
- package/dist/src/NodeManager/errors/NodeNotQualifiedError.d.ts +3 -0
- package/dist/src/NodeManager/errors/NodeNotQualifiedError.js +6 -0
- package/dist/src/NodeManager/errors/NodeNotRegisteredError.d.ts +3 -0
- package/dist/src/NodeManager/errors/NodeNotRegisteredError.js +6 -0
- package/dist/src/NodeManager/index.js +25 -57
- package/dist/src/NodeManager/monitoring/log/NodeLog.d.ts +0 -1
- package/dist/src/NodeManager/monitoring/log/NodeLog.js +11 -38
- package/dist/src/NodeManager/monitoring/log/console/ConsoleLogger.d.ts +3 -0
- package/dist/src/NodeManager/monitoring/log/console/ConsoleLogger.js +33 -5
- package/dist/src/NodeManager/monitoring/ping/PingHandler.d.ts +2 -4
- package/dist/src/NodeManager/monitoring/ping/PingHandler.js +31 -26
- package/dist/src/NodeManager/monitoring/proxy/loggingProxy.d.ts +2 -1
- package/dist/src/NodeManager/monitoring/proxy/loggingProxy.js +2 -3
- package/dist/src/NodeManager/node/Node.d.ts +4 -6
- package/dist/src/NodeManager/node/Node.js +16 -29
- package/dist/src/NodeManager/node/api/ApiHandler.js +2 -3
- package/dist/src/NodeManager/node/api/middlewares/index.d.ts +0 -1
- package/dist/src/NodeManager/node/api/middlewares/index.js +0 -1
- package/dist/src/NodeManager/node/api/routes/post/index.d.ts +0 -1
- package/dist/src/NodeManager/node/api/routes/post/index.js +0 -1
- package/dist/src/NodeManager/node/grid/gridHandler.d.ts +2 -8
- package/dist/src/NodeManager/node/grid/gridHandler.js +10 -143
- package/dist/src/NodeManager/node/health/healthHandler.d.ts +1 -1
- package/dist/src/NodeManager/node/health/healthHandler.js +13 -11
- package/dist/src/NodeManager/node/job/JobRegistry.js +5 -3
- package/dist/src/NodeManager/node/job/defination/strategy/IpfsJobDefinitionStrategy.d.ts +1 -3
- package/dist/src/NodeManager/node/job/defination/strategy/IpfsJobDefinitionStrategy.js +2 -4
- package/dist/src/NodeManager/node/job/jobExternalUtil.d.ts +2 -3
- package/dist/src/NodeManager/node/job/jobExternalUtil.js +4 -4
- package/dist/src/NodeManager/node/job/jobHandler.js +5 -3
- package/dist/src/NodeManager/node/key/keyHandler.d.ts +0 -1
- package/dist/src/NodeManager/node/key/keyHandler.js +1 -38
- package/dist/src/NodeManager/node/market/benchmark.d.ts +15 -0
- package/dist/src/NodeManager/node/market/benchmark.js +84 -0
- package/dist/src/NodeManager/node/market/hostManager.d.ts +114 -0
- package/dist/src/NodeManager/node/market/hostManager.js +112 -0
- package/dist/src/NodeManager/node/market/marketAccess.d.ts +8 -0
- package/dist/src/NodeManager/node/market/marketAccess.js +53 -0
- package/dist/src/NodeManager/node/market/marketHandler.d.ts +10 -3
- package/dist/src/NodeManager/node/market/marketHandler.js +88 -6
- package/dist/src/NodeManager/node/register/index.d.ts +2 -12
- package/dist/src/NodeManager/node/register/index.js +12 -56
- package/dist/src/NodeManager/node/resource/resourceManager.d.ts +2 -1
- package/dist/src/NodeManager/node/resource/resourceManager.js +4 -4
- package/dist/src/NodeManager/sdk/index.js +4 -14
- package/dist/src/NodeManager/utils/wslCheck.js +1 -1
- package/dist/src/cli/createNosanaCli.js +2 -0
- package/dist/src/ipfs/IpfsClient.d.ts +7 -0
- package/dist/src/ipfs/IpfsClient.js +17 -0
- package/npm-shrinkwrap.json +30 -2
- package/package.json +5 -3
- package/dist/src/NodeManager/client/index.d.ts +0 -4
- package/dist/src/NodeManager/client/index.js +0 -14
- package/dist/src/NodeManager/node/api/middlewares/rest/verifyBackendSignatureMiddleware.d.ts +0 -3
- package/dist/src/NodeManager/node/api/middlewares/rest/verifyBackendSignatureMiddleware.js +0 -20
- package/dist/src/NodeManager/node/api/routes/post/node-validation.d.ts +0 -4
- package/dist/src/NodeManager/node/api/routes/post/node-validation.js +0 -1787
- package/dist/src/NodeManager/node/specs/specsHandler.d.ts +0 -17
- package/dist/src/NodeManager/node/specs/specsHandler.js +0 -135
- package/dist/src/NodeManager/node/specs/type.d.ts +0 -15
- /package/dist/src/NodeManager/{node/specs/type.js → clients/types.utils.js} +0 -0
package/dist/.env.dev
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
BACKEND_AUTHORIZATION_ADDRESS=3R1YEz9crQR3tRbtSAuufjSsjQXMqtDr1D4f1YprMUSE
|
|
1
|
+
HOST_MANAGER_BASE_URL=https://host-manager.k8s.dev.nos.ci
|
|
3
2
|
EXPLORER_URL=https://devnet.nosana.io
|
|
4
3
|
FRP_SERVER_ADDRESS=node.k8s.dev.nos.ci
|
|
5
4
|
MIN_DISK_SPACE=20
|
package/dist/.env.prd
CHANGED
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nosana/node",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.15",
|
|
4
4
|
"description": "",
|
|
5
5
|
"bin": {
|
|
6
6
|
"nosana-node": "./dist/src/index.js"
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
"dev:podman:start": "./podman-run.sh start",
|
|
13
13
|
"dev:podman:run": "./podman-run.sh run",
|
|
14
14
|
"build": "npm run prepare && tsc && cp .env ./dist/ && cp .env.prd ./dist/ && cp .env.dev ./dist/",
|
|
15
|
-
"generate": "
|
|
15
|
+
"generate": "npm run generate:host-manager",
|
|
16
|
+
"generate:host-manager": "openapi-typescript https://host-manager.k8s.dev.nos.ci/swagger/json -o ./src/NodeManager/clients/hostManager/schema.d.ts",
|
|
16
17
|
"test": "APP_ENV=development DOCKER_CERT_PATH= vitest run",
|
|
17
18
|
"ci:test": "APP_ENV=development DOCKER_CERT_PATH= vitest run --coverage --reporter=junit --outputFile=./test-report.xml",
|
|
18
19
|
"test:watch": "APP_ENV=development DOCKER_CERT_PATH= vitest",
|
|
@@ -71,6 +72,7 @@
|
|
|
71
72
|
"dependencies": {
|
|
72
73
|
"@coral-xyz/anchor": "^0.28.1-beta.1",
|
|
73
74
|
"@inquirer/prompts": "^4.3.0",
|
|
75
|
+
"@nosana/ipfs": "^2.2.6",
|
|
74
76
|
"@nosana/sdk": "^0.4.81",
|
|
75
77
|
"@solana/web3.js": "^1.78.0",
|
|
76
78
|
"bn.js": "^5.2.1",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function checkForMaintenance(): Promise<void>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { getMaintenanceStatus, waitForMaintenance, } from "./clients/maintenanceState.js";
|
|
3
|
+
import { sleep } from "./utils/utils.js";
|
|
4
|
+
import { validateCLIVersion } from "../version/index.js";
|
|
5
|
+
const NPM_POLL_INTERVAL_S = 5 * 60;
|
|
6
|
+
function displayUpcomingMaintenanceNotice(status) {
|
|
7
|
+
console.log("");
|
|
8
|
+
console.log(chalk.bgBlue.white.bold(" 🛠 SCHEDULED MAINTENANCE "));
|
|
9
|
+
console.log("");
|
|
10
|
+
if (status.startsAt) {
|
|
11
|
+
console.log(chalk.cyan(`• ${chalk.bold("Starts:")} ${status.startsAt}`));
|
|
12
|
+
}
|
|
13
|
+
if (status.expectedEndAt) {
|
|
14
|
+
console.log(chalk.cyan(`• ${chalk.bold("Expected end:")} ${status.expectedEndAt}`));
|
|
15
|
+
}
|
|
16
|
+
if (status.reason) {
|
|
17
|
+
console.log(chalk.cyan(`• ${chalk.bold("Reason:")} ${status.reason}`));
|
|
18
|
+
}
|
|
19
|
+
console.log("");
|
|
20
|
+
}
|
|
21
|
+
export async function checkForMaintenance() {
|
|
22
|
+
const status = await getMaintenanceStatus();
|
|
23
|
+
if (!status?.maintenance) {
|
|
24
|
+
if (status?.startsAt || status?.expectedEndAt || status?.reason) {
|
|
25
|
+
displayUpcomingMaintenanceNotice(status);
|
|
26
|
+
}
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
// Re-poll npm during the maintenance window so a published fix triggers
|
|
30
|
+
// a wrapper restart instead of resuming on the stale version.
|
|
31
|
+
const maintenanceFinished = waitForMaintenance().catch(() => undefined);
|
|
32
|
+
let cleared = false;
|
|
33
|
+
maintenanceFinished.then(() => {
|
|
34
|
+
cleared = true;
|
|
35
|
+
});
|
|
36
|
+
while (!cleared) {
|
|
37
|
+
await validateCLIVersion();
|
|
38
|
+
await Promise.race([sleep(NPM_POLL_INTERVAL_S), maintenanceFinished]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import createClient from 'openapi-fetch';
|
|
2
|
+
import { getSDK } from '../../sdk/index.js';
|
|
3
|
+
import { configs } from '../../configs/configs.js';
|
|
4
|
+
import { maintenanceMiddleware } from '../maintenanceMiddleware.js';
|
|
5
|
+
let instance = undefined;
|
|
6
|
+
export const hostManagerClientSelector = () => {
|
|
7
|
+
if (!instance) {
|
|
8
|
+
const sdk = getSDK();
|
|
9
|
+
const address = sdk.solana.provider.wallet.publicKey.toString();
|
|
10
|
+
instance = createClient({
|
|
11
|
+
baseUrl: configs().hostManagerBaseUrl,
|
|
12
|
+
headers: {
|
|
13
|
+
'Content-Type': 'application/json',
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
instance.use(maintenanceMiddleware);
|
|
17
|
+
instance.use({
|
|
18
|
+
async onRequest({ request }) {
|
|
19
|
+
const authHeader = await sdk.authorization.generate(address);
|
|
20
|
+
request.headers.set('Authorization', authHeader);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return instance;
|
|
25
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { isMaintenanceResponse, waitForMaintenance, } from "./maintenanceState.js";
|
|
2
|
+
export const maintenanceMiddleware = {
|
|
3
|
+
onResponse: async ({ response, request, options }) => {
|
|
4
|
+
let current = response;
|
|
5
|
+
while (await isMaintenanceResponse(current)) {
|
|
6
|
+
await waitForMaintenance();
|
|
7
|
+
current = await options.fetch(request.clone());
|
|
8
|
+
}
|
|
9
|
+
return current === response ? undefined : current;
|
|
10
|
+
},
|
|
11
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const MAINTENANCE_BODY = "under maintenance";
|
|
2
|
+
export type MaintenanceResponse = {
|
|
3
|
+
maintenance: boolean;
|
|
4
|
+
startsAt?: string;
|
|
5
|
+
expectedEndAt?: string;
|
|
6
|
+
reason?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare const isMaintenanceResponse: (response: Response) => Promise<boolean>;
|
|
9
|
+
export declare const getMaintenanceStatus: () => Promise<MaintenanceResponse | null>;
|
|
10
|
+
export declare const waitForMaintenance: () => Promise<void>;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { configs } from "../configs/configs.js";
|
|
3
|
+
import { consoleLogging } from "../monitoring/log/console/ConsoleLogger.js";
|
|
4
|
+
import { sleep } from "../utils/utils.js";
|
|
5
|
+
export const MAINTENANCE_BODY = "under maintenance";
|
|
6
|
+
const MAINTENANCE_PATH = "/node-under-maintenance";
|
|
7
|
+
const POLL_INTERVAL_S = 5;
|
|
8
|
+
let maintenancePromise = null;
|
|
9
|
+
const getMaintenanceUrl = () => {
|
|
10
|
+
return `${configs().hostManagerBaseUrl}${MAINTENANCE_PATH}`;
|
|
11
|
+
};
|
|
12
|
+
// Sibling endpoints signal maintenance via 503 + plain text body.
|
|
13
|
+
export const isMaintenanceResponse = async (response) => {
|
|
14
|
+
if (response.status !== 503)
|
|
15
|
+
return false;
|
|
16
|
+
try {
|
|
17
|
+
const text = await response.clone().text();
|
|
18
|
+
return text.trim().toLowerCase() === MAINTENANCE_BODY;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
export const getMaintenanceStatus = async () => {
|
|
25
|
+
try {
|
|
26
|
+
const response = await fetch(getMaintenanceUrl());
|
|
27
|
+
return (await response.json());
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const formatSpinnerText = (body) => {
|
|
34
|
+
const parts = ["Node under maintenance"];
|
|
35
|
+
if (body?.reason)
|
|
36
|
+
parts.push(body.reason);
|
|
37
|
+
if (body?.expectedEndAt)
|
|
38
|
+
parts.push(`ETA ${body.expectedEndAt}`);
|
|
39
|
+
return chalk.yellow(parts.join(" — "));
|
|
40
|
+
};
|
|
41
|
+
export const waitForMaintenance = () => {
|
|
42
|
+
if (maintenancePromise)
|
|
43
|
+
return maintenancePromise;
|
|
44
|
+
const spinner = consoleLogging().spinner;
|
|
45
|
+
const previousText = spinner?.text;
|
|
46
|
+
if (spinner) {
|
|
47
|
+
spinner.text = formatSpinnerText(null);
|
|
48
|
+
if (!spinner.isSpinning)
|
|
49
|
+
spinner.start();
|
|
50
|
+
}
|
|
51
|
+
maintenancePromise = (async () => {
|
|
52
|
+
for (;;) {
|
|
53
|
+
const body = await getMaintenanceStatus();
|
|
54
|
+
if (body && !body.maintenance)
|
|
55
|
+
return;
|
|
56
|
+
if (spinner)
|
|
57
|
+
spinner.text = formatSpinnerText(body);
|
|
58
|
+
await sleep(POLL_INTERVAL_S);
|
|
59
|
+
}
|
|
60
|
+
})().finally(() => {
|
|
61
|
+
if (spinner && previousText !== undefined)
|
|
62
|
+
spinner.text = previousText;
|
|
63
|
+
maintenancePromise = null;
|
|
64
|
+
});
|
|
65
|
+
return maintenancePromise;
|
|
66
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import createClient from "openapi-fetch";
|
|
2
|
+
export type EnumValues<T> = T[keyof T];
|
|
3
|
+
/**
|
|
4
|
+
* Utility type to remove header requirements from OpenAPI parameters
|
|
5
|
+
* This preserves the original structure but removes headers and makes undefined params optional
|
|
6
|
+
* We only modify the parameters, leaving responses and requestBody untouched
|
|
7
|
+
*/
|
|
8
|
+
type OmitHeaders<T> = T extends {
|
|
9
|
+
parameters: {
|
|
10
|
+
header?: any;
|
|
11
|
+
path?: infer Path;
|
|
12
|
+
query?: infer Query;
|
|
13
|
+
cookie?: infer Cookie;
|
|
14
|
+
};
|
|
15
|
+
responses?: infer Responses;
|
|
16
|
+
requestBody?: infer RequestBody;
|
|
17
|
+
} ? {
|
|
18
|
+
parameters: {
|
|
19
|
+
header?: never;
|
|
20
|
+
} & (Path extends undefined ? {} : {
|
|
21
|
+
path: Path;
|
|
22
|
+
}) & (Query extends undefined ? {} : {
|
|
23
|
+
query: Query;
|
|
24
|
+
}) & (Cookie extends undefined ? {} : {
|
|
25
|
+
cookie: Cookie;
|
|
26
|
+
});
|
|
27
|
+
} & (Responses extends undefined ? {} : {
|
|
28
|
+
responses: Responses;
|
|
29
|
+
}) & (RequestBody extends undefined ? {} : {
|
|
30
|
+
requestBody: RequestBody;
|
|
31
|
+
}) : T;
|
|
32
|
+
/**
|
|
33
|
+
* Type that removes header requirements from all endpoints in the paths
|
|
34
|
+
* This should preserve response types and other properties
|
|
35
|
+
*/
|
|
36
|
+
export type AuthenticatedPaths<Paths extends Record<string, any>> = {
|
|
37
|
+
[P in keyof Paths]: {
|
|
38
|
+
[M in keyof Paths[P]]: OmitHeaders<Paths[P][M]>;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Explicit client type that should preserve all response typing
|
|
43
|
+
*/
|
|
44
|
+
export type AuthenticatedClient<Paths extends Record<string, any>> = ReturnType<typeof createClient<AuthenticatedPaths<Paths>>>;
|
|
45
|
+
export {};
|
|
@@ -4,9 +4,7 @@ export const configs = (options) => {
|
|
|
4
4
|
NodeConfigsSingleton.getInstance(options);
|
|
5
5
|
return {
|
|
6
6
|
isNodeRun: options?.isNodeRun,
|
|
7
|
-
|
|
8
|
-
backendSolanaAddress: loadConfigurationValue('BACKEND_SOLANA_ADDRESS'),
|
|
9
|
-
backendAuthorizationAddress: loadConfigurationValue('BACKEND_AUTHORIZATION_ADDRESS'),
|
|
7
|
+
hostManagerBaseUrl: loadConfigurationValue('HOST_MANAGER_BASE_URL'),
|
|
10
8
|
explorerUrl: loadConfigurationValue('EXPLORER_URL'),
|
|
11
9
|
signMessage: loadConfigurationValue('SIGN_MESSAGE'),
|
|
12
10
|
frp: {
|
|
@@ -6,11 +6,12 @@ import { log } from './monitoring/log/NodeLog.js';
|
|
|
6
6
|
import { logStreaming } from './monitoring/streaming/LogStreamer.js';
|
|
7
7
|
import { consoleLogging } from './monitoring/log/console/ConsoleLogger.js';
|
|
8
8
|
import { validateCLIVersion } from '../version/index.js';
|
|
9
|
-
import {
|
|
9
|
+
import { checkForMaintenance } from './checkForMaintenance.js';
|
|
10
10
|
import { getSDK } from './sdk/index.js';
|
|
11
11
|
import { ping } from './monitoring/ping/PingHandler.js';
|
|
12
12
|
import { LogMonitoringRegistry } from './monitoring/LogMonitoringRegistry.js';
|
|
13
13
|
import { checkWSLStatus } from './utils/wslCheck.js';
|
|
14
|
+
import { HostManager } from './node/market/hostManager.js';
|
|
14
15
|
export default class NodeManager {
|
|
15
16
|
constructor(options) {
|
|
16
17
|
this.exiting = false;
|
|
@@ -57,9 +58,6 @@ export default class NodeManager {
|
|
|
57
58
|
* the node api, initializing everything that needs to be initialized
|
|
58
59
|
*/
|
|
59
60
|
await this.node.start();
|
|
60
|
-
if (!this.node.isOnboarded) {
|
|
61
|
-
await this.node.register();
|
|
62
|
-
}
|
|
63
61
|
/**
|
|
64
62
|
* start the api of the node and register all the routes of the nodes,
|
|
65
63
|
* we call this here in the init so the api survives restarts between jobs
|
|
@@ -78,28 +76,12 @@ export default class NodeManager {
|
|
|
78
76
|
async start(marketArg) {
|
|
79
77
|
this.exiting = false;
|
|
80
78
|
if (this.inJobLoop) {
|
|
81
|
-
await validateCLIVersion();
|
|
79
|
+
await Promise.all([validateCLIVersion(), checkForMaintenance()]);
|
|
82
80
|
}
|
|
83
81
|
/**
|
|
84
82
|
* maintenance
|
|
85
83
|
*/
|
|
86
84
|
await this.node.maintenance();
|
|
87
|
-
/**
|
|
88
|
-
* specs
|
|
89
|
-
*
|
|
90
|
-
* this retrieves specs from the node to ensure it can run the jobs.
|
|
91
|
-
* It gets the GPUs, CPUs, and internet speed.
|
|
92
|
-
*
|
|
93
|
-
* if the specs fails restart the system
|
|
94
|
-
*/
|
|
95
|
-
if (!(await this.node.specs())) {
|
|
96
|
-
/**
|
|
97
|
-
* start
|
|
98
|
-
*
|
|
99
|
-
* recursively start the the process again by calling the restart function
|
|
100
|
-
*/
|
|
101
|
-
return await this.restart(marketArg);
|
|
102
|
-
}
|
|
103
85
|
/**
|
|
104
86
|
* WSL check
|
|
105
87
|
* - Shows warning message for all WSL hosts
|
|
@@ -107,28 +89,19 @@ export default class NodeManager {
|
|
|
107
89
|
*/
|
|
108
90
|
checkWSLStatus(this.node.getSystemEnvironment());
|
|
109
91
|
/**
|
|
110
|
-
*
|
|
92
|
+
* market
|
|
111
93
|
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
94
|
+
* request a market to join from the host manager,
|
|
95
|
+
* we can pass a requested market or let the host manager recommend us one
|
|
114
96
|
*/
|
|
115
|
-
|
|
116
|
-
if (!market || !market.length) {
|
|
117
|
-
market = await this.node.recommend();
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* setup
|
|
121
|
-
*
|
|
122
|
-
* this sets up everything need, downloads needed resources ...
|
|
123
|
-
*/
|
|
124
|
-
await this.node.setup(market);
|
|
97
|
+
const market = await this.node.requestMarket(marketArg);
|
|
125
98
|
/**
|
|
126
99
|
* healthcheck
|
|
127
100
|
*
|
|
128
101
|
* this checks the health of the container tech,
|
|
129
102
|
* the connectivity, and every other critical system.
|
|
130
103
|
*/
|
|
131
|
-
if (!(await this.node.healthcheck(
|
|
104
|
+
if (!(await this.node.healthcheck())) {
|
|
132
105
|
/**
|
|
133
106
|
* start
|
|
134
107
|
*
|
|
@@ -136,6 +109,12 @@ export default class NodeManager {
|
|
|
136
109
|
*/
|
|
137
110
|
return await this.restart(marketArg);
|
|
138
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* setup
|
|
114
|
+
*
|
|
115
|
+
* this sets up everything need, downloads needed resources ...
|
|
116
|
+
*/
|
|
117
|
+
await this.node.setup(market);
|
|
139
118
|
/**
|
|
140
119
|
* this variable was added to know when the node has gone past the setup/checks stages
|
|
141
120
|
* and is now starting job work and queueing,
|
|
@@ -144,7 +123,7 @@ export default class NodeManager {
|
|
|
144
123
|
*/
|
|
145
124
|
this.inJobLoop = true;
|
|
146
125
|
if (!(await this.node.isApiActive())) {
|
|
147
|
-
throw new Error(
|
|
126
|
+
throw new Error("Node API is detected offline");
|
|
148
127
|
}
|
|
149
128
|
/**
|
|
150
129
|
* pending
|
|
@@ -160,7 +139,7 @@ export default class NodeManager {
|
|
|
160
139
|
*
|
|
161
140
|
* Enter the queue to wait for a job since we have no pending jobs.
|
|
162
141
|
*/
|
|
163
|
-
await this.node.queue(market);
|
|
142
|
+
await this.node.queue(market.address.toString());
|
|
164
143
|
}
|
|
165
144
|
/**
|
|
166
145
|
*
|
|
@@ -268,14 +247,14 @@ export default class NodeManager {
|
|
|
268
247
|
await this.stop();
|
|
269
248
|
process.exit();
|
|
270
249
|
};
|
|
271
|
-
process.on(
|
|
272
|
-
process.on(
|
|
250
|
+
process.on("SIGINT", exitHandler); // Handle Ctrl+C
|
|
251
|
+
process.on("SIGTERM", exitHandler); // Handle termination signals
|
|
273
252
|
// log crashes
|
|
274
|
-
process.on(
|
|
253
|
+
process.on("unhandledRejection", async (reason, p) => {
|
|
275
254
|
try {
|
|
276
255
|
const e = reason;
|
|
277
256
|
await reportError({
|
|
278
|
-
error_type:
|
|
257
|
+
error_type: "unhandledRejection",
|
|
279
258
|
error_name: e.name,
|
|
280
259
|
error_message: e.message,
|
|
281
260
|
error_stack: e.stack ?? e.trace,
|
|
@@ -283,11 +262,11 @@ export default class NodeManager {
|
|
|
283
262
|
}
|
|
284
263
|
catch (_) { }
|
|
285
264
|
});
|
|
286
|
-
process.on(
|
|
265
|
+
process.on("uncaughtException", async (reason) => {
|
|
287
266
|
try {
|
|
288
267
|
const e = reason;
|
|
289
268
|
await reportError({
|
|
290
|
-
error_type:
|
|
269
|
+
error_type: "uncaughtException",
|
|
291
270
|
error_name: e.name,
|
|
292
271
|
error_message: e.message,
|
|
293
272
|
error_stack: e.stack ?? e.trace,
|
|
@@ -299,19 +278,8 @@ export default class NodeManager {
|
|
|
299
278
|
}
|
|
300
279
|
const reportError = async (data) => {
|
|
301
280
|
const nosana = getSDK();
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
Authorization: await nosana.authorization.generate(configs().signMessage, {
|
|
306
|
-
includeTime: true,
|
|
307
|
-
}),
|
|
308
|
-
'Content-Type': 'application/json',
|
|
309
|
-
},
|
|
310
|
-
body: JSON.stringify({
|
|
311
|
-
address: nosana.solana.provider.wallet.publicKey.toString(),
|
|
312
|
-
...data,
|
|
313
|
-
}),
|
|
281
|
+
return HostManager.reportError({
|
|
282
|
+
address: nosana.solana.provider.wallet.publicKey.toString(),
|
|
283
|
+
...data,
|
|
314
284
|
});
|
|
315
|
-
const responseBody = await response.json();
|
|
316
|
-
return responseBody;
|
|
317
285
|
};
|
|
@@ -47,7 +47,17 @@ class NodeLog {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
process(data) {
|
|
50
|
-
if (data.class === '
|
|
50
|
+
if (data.class === 'BenchmarkTaskManager' && data.method === 'progress') {
|
|
51
|
+
this.addLog({
|
|
52
|
+
method: `${data.class}.${data.method}`,
|
|
53
|
+
job: this.job,
|
|
54
|
+
log: '',
|
|
55
|
+
timestamp: Date.now(),
|
|
56
|
+
type: 'update',
|
|
57
|
+
payload: data.payload,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (data.class === 'TaskManager' || data.class === 'BenchmarkTaskManager') {
|
|
51
61
|
if (data.method === 'start') {
|
|
52
62
|
if (data.type === 'call') {
|
|
53
63
|
this.addLog({
|
|
@@ -126,9 +136,6 @@ class NodeLog {
|
|
|
126
136
|
(data.method === 'restartDelay' || data.method === 'delay')) {
|
|
127
137
|
this.handleRestart(data);
|
|
128
138
|
}
|
|
129
|
-
if (data.class === 'BasicNode' && data.method === 'specs') {
|
|
130
|
-
this.handleSpecs(data);
|
|
131
|
-
}
|
|
132
139
|
if (data.class === 'BasicNode' && data.method === 'recommend') {
|
|
133
140
|
this.handleRecommend(data);
|
|
134
141
|
}
|
|
@@ -403,40 +410,6 @@ class NodeLog {
|
|
|
403
410
|
// });
|
|
404
411
|
// }
|
|
405
412
|
// }
|
|
406
|
-
handleSpecs(data) {
|
|
407
|
-
if (data.type === 'call') {
|
|
408
|
-
this.addLog({
|
|
409
|
-
method: `${data.class}.${data.method}`,
|
|
410
|
-
job: this.job,
|
|
411
|
-
log: chalk.cyan('Node is checking specs'),
|
|
412
|
-
timestamp: Date.now(),
|
|
413
|
-
// type: 'info',
|
|
414
|
-
type: 'process',
|
|
415
|
-
pending: {
|
|
416
|
-
isPending: true,
|
|
417
|
-
expecting: `${data.class}.${data.method}`,
|
|
418
|
-
},
|
|
419
|
-
});
|
|
420
|
-
}
|
|
421
|
-
if (data.type === 'return') {
|
|
422
|
-
this.addLog({
|
|
423
|
-
method: `${data.class}.${data.method}`,
|
|
424
|
-
job: this.job,
|
|
425
|
-
log: chalk.green('Node specs check completed successfully'),
|
|
426
|
-
timestamp: Date.now(),
|
|
427
|
-
type: 'success',
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
if (data.type === 'error') {
|
|
431
|
-
this.addLog({
|
|
432
|
-
method: `${data.class}.${data.method}`,
|
|
433
|
-
job: this.job,
|
|
434
|
-
log: chalk.red('Node specs check failed'),
|
|
435
|
-
timestamp: Date.now(),
|
|
436
|
-
type: 'error',
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
413
|
handleRegister(data) {
|
|
441
414
|
if (data.type === 'call') {
|
|
442
415
|
this.addLog({
|
|
@@ -11,6 +11,9 @@ export declare class ConsoleLogger implements LogObserver {
|
|
|
11
11
|
private kill;
|
|
12
12
|
private benchmarking;
|
|
13
13
|
private taskManagerActive;
|
|
14
|
+
private taskManagerLabel;
|
|
15
|
+
private taskManagerStartMethod;
|
|
16
|
+
private benchmarkProgress;
|
|
14
17
|
private running;
|
|
15
18
|
private expiry;
|
|
16
19
|
private taskManagerRunInterval;
|