@nosana/node 1.1.60-rc → 1.1.62-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 +1 -1
- package/dist/src/NodeManager/node/api/routes/wss/log.d.ts +1 -1
- package/dist/src/NodeManager/node/api/routes/wss/log.js +15 -3
- package/dist/src/NodeManager/node/job/jobExternalUtil.js +4 -2
- package/dist/src/NodeManager/utils/expose-util.js +3 -1
- package/dist/src/cli/commands/run/generateDeploymentEndpointsTable.js +6 -3
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/package.json
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import WebSocket from 'ws';
|
|
1
2
|
import { logStreaming } from '../../../../monitoring/streaming/LogStreamer.js';
|
|
2
3
|
import { getSDK } from '../../../../sdk/index.js';
|
|
3
4
|
import { TaskManagerRegistry } from '../../../task/TaskManagerRegistry.js';
|
|
@@ -10,8 +11,17 @@ export async function wssLogRoute(ws, _, { jobAddress }) {
|
|
|
10
11
|
const walletAddress = sdk.solana.wallet.toString();
|
|
11
12
|
logStreaming(walletAddress).subscribe(ws, jobAddress);
|
|
12
13
|
}
|
|
13
|
-
export function wssTaskManagerLogRoute(ws, _, { jobAddress, group, opId, type, }) {
|
|
14
|
-
const
|
|
14
|
+
export async function wssTaskManagerLogRoute(ws, _, { jobAddress, group, opId, type, }) {
|
|
15
|
+
const registry = TaskManagerRegistry.getInstance();
|
|
16
|
+
const deadline = Date.now() + 30000;
|
|
17
|
+
let task = registry.get(jobAddress);
|
|
18
|
+
// A run is visible on-chain before the node has finished loading the job
|
|
19
|
+
// definition and registering its TaskManager. Keep the authenticated socket
|
|
20
|
+
// open during that short startup window instead of forcing clients to race it.
|
|
21
|
+
while (!task && Date.now() < deadline && ws.readyState === WebSocket.OPEN) {
|
|
22
|
+
await new Promise((resolve) => setTimeout(resolve, 250));
|
|
23
|
+
task = registry.get(jobAddress);
|
|
24
|
+
}
|
|
15
25
|
if (!task)
|
|
16
26
|
return ws.close(1008, 'Invalid job address');
|
|
17
27
|
task.subscribe(ws, (log) => {
|
|
@@ -29,6 +39,8 @@ export function wssTaskManagerLogRoute(ws, _, { jobAddress, group, opId, type, }
|
|
|
29
39
|
try {
|
|
30
40
|
ws.send(JSON.stringify({ path: 'flog', data: JSON.stringify(log) }));
|
|
31
41
|
}
|
|
32
|
-
catch {
|
|
42
|
+
catch {
|
|
43
|
+
// The client may disconnect while historical logs are being replayed.
|
|
44
|
+
}
|
|
33
45
|
}
|
|
34
46
|
}
|
|
@@ -3,6 +3,7 @@ import { IpfsClientSingleton } from '../../../ipfs/IpfsClient.js';
|
|
|
3
3
|
import { JobDefinitionStrategySelector } from './defination/JobDefinitionStrategy.js';
|
|
4
4
|
import { ResultReturnStrategySelector } from './result/ResultReturnStrategy.js';
|
|
5
5
|
import { createInitialFlow } from '../task/helpers/createInitialFlow.js';
|
|
6
|
+
const JOB_DEFINITION_RETRY_DELAYS_SECONDS = [0.5, 1, 18.5];
|
|
6
7
|
export class JobExternalUtil {
|
|
7
8
|
constructor(repository) {
|
|
8
9
|
this.repository = repository;
|
|
@@ -12,10 +13,11 @@ export class JobExternalUtil {
|
|
|
12
13
|
return await IpfsClientSingleton.retrieve(ipfsHash);
|
|
13
14
|
}
|
|
14
15
|
catch (error) {
|
|
15
|
-
|
|
16
|
+
const retryDelay = JOB_DEFINITION_RETRY_DELAYS_SECONDS[attempts];
|
|
17
|
+
if (retryDelay === undefined) {
|
|
16
18
|
throw error;
|
|
17
19
|
}
|
|
18
|
-
await sleep(
|
|
20
|
+
await sleep(retryDelay);
|
|
19
21
|
return this.retrieveJobDefinitionWithRetry(ipfsHash, attempts + 1);
|
|
20
22
|
}
|
|
21
23
|
}
|
|
@@ -52,8 +52,10 @@ export const generateProxies = (flowId, op, opIndex, ports, name, operationId, d
|
|
|
52
52
|
for (let exposedPort of ports) {
|
|
53
53
|
// TODO: use ids generated in the taskmanager to make secerts
|
|
54
54
|
const generatedId = generateExposeId(flowId, opIndex, exposedPort.port, op.args.private);
|
|
55
|
+
// When an op exposes more than one port, include the port in the id so each
|
|
56
|
+
// port gets a distinct deployment endpoint instead of colliding on a shared one.
|
|
55
57
|
const generatedDeploymentId = deploymentId
|
|
56
|
-
? generateExposeId(deploymentId, op.id, 0, false)
|
|
58
|
+
? generateExposeId(deploymentId, op.id, ports.length > 1 ? exposedPort.port : 0, false)
|
|
57
59
|
: undefined;
|
|
58
60
|
let proxyHTTPHealthCheckPath = undefined;
|
|
59
61
|
if (exposedPort.health_checks && exposedPort.health_checks.length > 0) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Table } from 'console-table-printer';
|
|
2
|
-
import { isOperator, isSpreadMarker, } from '@nosana/sdk';
|
|
2
|
+
import { getExposePorts, isOperator, isSpreadMarker, } from '@nosana/sdk';
|
|
3
3
|
import { generateExposeId } from '../../../NodeManager/utils/expose-util.js';
|
|
4
4
|
import { configs } from '../../../NodeManager/configs/configs.js';
|
|
5
5
|
export function generateDeploymentEndpointsTable(jobDefinition) {
|
|
@@ -14,9 +14,12 @@ export function generateDeploymentEndpointsTable(jobDefinition) {
|
|
|
14
14
|
if (op.type === 'container/run') {
|
|
15
15
|
const { expose } = op.args;
|
|
16
16
|
if (expose) {
|
|
17
|
+
// Mirror generateProxies: only single-port ops fall back to 0, so a
|
|
18
|
+
// multi-port op gets a distinct endpoint per port.
|
|
19
|
+
const exposedPortCount = getExposePorts(op).length;
|
|
17
20
|
if (typeof expose === 'number' ||
|
|
18
21
|
(typeof expose === 'string' && !isOperator(expose))) {
|
|
19
|
-
const generatedId = generateExposeId(jobDefinition.deployment_id, op.id, 0, false);
|
|
22
|
+
const generatedId = generateExposeId(jobDefinition.deployment_id, op.id, exposedPortCount > 1 ? expose : 0, false);
|
|
20
23
|
table.addRow({
|
|
21
24
|
OpId: op.id,
|
|
22
25
|
Port: expose,
|
|
@@ -30,7 +33,7 @@ export function generateDeploymentEndpointsTable(jobDefinition) {
|
|
|
30
33
|
if (typeof port === 'string' && isOperator(port))
|
|
31
34
|
return; // skip dynamic
|
|
32
35
|
const p = typeof port === 'object' ? port.port : port;
|
|
33
|
-
const generatedId = generateExposeId(jobDefinition.deployment_id, op.id, 0, false);
|
|
36
|
+
const generatedId = generateExposeId(jobDefinition.deployment_id, op.id, exposedPortCount > 1 ? p : 0, false);
|
|
34
37
|
table.addRow({
|
|
35
38
|
OpId: op.id,
|
|
36
39
|
Port: p,
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nosana/node",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.62-rc",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@nosana/node",
|
|
9
|
-
"version": "1.1.
|
|
9
|
+
"version": "1.1.62-rc",
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@coral-xyz/anchor": "^0.28.1-beta.1",
|