nodio-cli 1.0.7 → 1.0.8
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/package.json +1 -1
- package/src/server/config.js +1 -1
- package/src/server/models.js +3 -1
- package/src/server/routes.js +17 -0
- package/src/user/commands.js +23 -3
package/package.json
CHANGED
package/src/server/config.js
CHANGED
|
@@ -5,7 +5,7 @@ function getServerConfig() {
|
|
|
5
5
|
return {
|
|
6
6
|
port: Number(process.env.PORT || process.env.NODIO_SERVER_PORT || 4000),
|
|
7
7
|
mongoUri: process.env.NODIO_MONGO_URI || 'mongodb://127.0.0.1:27017/nodio',
|
|
8
|
-
heartbeatIntervalMs: Number(process.env.NODIO_HEARTBEAT_INTERVAL_MS ||
|
|
8
|
+
heartbeatIntervalMs: Number(process.env.NODIO_HEARTBEAT_INTERVAL_MS || 10000),
|
|
9
9
|
offlineAfterMisses: Number(process.env.NODIO_OFFLINE_AFTER_MISSES || 3),
|
|
10
10
|
minReplicas: Number(process.env.NODIO_MIN_REPLICAS || 5),
|
|
11
11
|
emergencyReplicaFloor: Number(process.env.NODIO_EMERGENCY_REPLICA_FLOOR || 2)
|
package/src/server/models.js
CHANGED
|
@@ -9,7 +9,9 @@ const nodeSchema = new mongoose.Schema(
|
|
|
9
9
|
capacityBytes: { type: Number, required: true, min: 1 },
|
|
10
10
|
freeBytes: { type: Number, required: true, min: 0 },
|
|
11
11
|
status: { type: String, enum: ['online', 'offline'], default: 'online', index: true },
|
|
12
|
-
lastHeartbeatAt: { type: Date, default: Date.now, index: true }
|
|
12
|
+
lastHeartbeatAt: { type: Date, default: Date.now, index: true },
|
|
13
|
+
pendingRelayAlert: { type: Boolean, default: false },
|
|
14
|
+
pendingRelayAlertAt: { type: Date, default: null }
|
|
13
15
|
},
|
|
14
16
|
{ timestamps: true }
|
|
15
17
|
);
|
package/src/server/routes.js
CHANGED
|
@@ -271,6 +271,23 @@ function buildRoutes(config) {
|
|
|
271
271
|
}
|
|
272
272
|
});
|
|
273
273
|
|
|
274
|
+
router.post('/nodes/:nodeId/alert-relay-pending', async (req, res, next) => {
|
|
275
|
+
try {
|
|
276
|
+
const { nodeId } = req.params;
|
|
277
|
+
const node = await NodeModel.findOne({ nodeId });
|
|
278
|
+
if (!node) {
|
|
279
|
+
return res.status(404).json({ error: 'node not found' });
|
|
280
|
+
}
|
|
281
|
+
// Set pending relay flag so donor knows to check urgently
|
|
282
|
+
node.pendingRelayAlert = true;
|
|
283
|
+
node.pendingRelayAlertAt = new Date();
|
|
284
|
+
await node.save();
|
|
285
|
+
res.json({ ok: true, message: 'relay pending alert sent' });
|
|
286
|
+
} catch (error) {
|
|
287
|
+
next(error);
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
|
|
274
291
|
router.post('/replication-tasks/:taskId/complete', async (req, res, next) => {
|
|
275
292
|
try {
|
|
276
293
|
const { taskId } = req.params;
|
package/src/user/commands.js
CHANGED
|
@@ -31,7 +31,7 @@ function sleep(ms) {
|
|
|
31
31
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
async function relayStoreShard(api, { shardId, fileId, nodeIds, dataBuffer, timeoutMs =
|
|
34
|
+
async function relayStoreShard(api, { shardId, fileId, nodeIds, dataBuffer, timeoutMs = 90000, pollMs = 500 }) {
|
|
35
35
|
const opId = uuidv4();
|
|
36
36
|
await api.post('/relay/shards/store', {
|
|
37
37
|
opId,
|
|
@@ -41,6 +41,16 @@ async function relayStoreShard(api, { shardId, fileId, nodeIds, dataBuffer, time
|
|
|
41
41
|
dataBase64: dataBuffer.toString('base64')
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
+
// Alert server that relay tasks are pending so donors check urgently
|
|
45
|
+
try {
|
|
46
|
+
for (const nodeId of nodeIds) {
|
|
47
|
+
// eslint-disable-next-line no-await-in-loop
|
|
48
|
+
await api.post(`/nodes/${nodeId}/alert-relay-pending`);
|
|
49
|
+
}
|
|
50
|
+
} catch (alertError) {
|
|
51
|
+
console.warn('relay alert failed:', alertError.message);
|
|
52
|
+
}
|
|
53
|
+
|
|
44
54
|
const deadline = Date.now() + timeoutMs;
|
|
45
55
|
while (Date.now() < deadline) {
|
|
46
56
|
const response = await api.get(`/relay/shards/store/${opId}`);
|
|
@@ -51,7 +61,7 @@ async function relayStoreShard(api, { shardId, fileId, nodeIds, dataBuffer, time
|
|
|
51
61
|
failed: payload.failed || []
|
|
52
62
|
};
|
|
53
63
|
}
|
|
54
|
-
//
|
|
64
|
+
// Polls every 500ms; with 10s heartbeat, donor should respond within 10s+network latency
|
|
55
65
|
// eslint-disable-next-line no-await-in-loop
|
|
56
66
|
await sleep(pollMs);
|
|
57
67
|
}
|
|
@@ -59,7 +69,7 @@ async function relayStoreShard(api, { shardId, fileId, nodeIds, dataBuffer, time
|
|
|
59
69
|
throw new Error(`relay store timed out for shard ${shardId}`);
|
|
60
70
|
}
|
|
61
71
|
|
|
62
|
-
async function relayFetchShard(api, { shardId, nodeIds, timeoutMs =
|
|
72
|
+
async function relayFetchShard(api, { shardId, nodeIds, timeoutMs = 90000, pollMs = 500 }) {
|
|
63
73
|
const opId = uuidv4();
|
|
64
74
|
await api.post('/relay/shards/fetch', {
|
|
65
75
|
opId,
|
|
@@ -67,6 +77,16 @@ async function relayFetchShard(api, { shardId, nodeIds, timeoutMs = 120000, poll
|
|
|
67
77
|
nodeIds
|
|
68
78
|
});
|
|
69
79
|
|
|
80
|
+
// Alert server that relay tasks are pending so donors check urgently
|
|
81
|
+
try {
|
|
82
|
+
for (const nodeId of nodeIds) {
|
|
83
|
+
// eslint-disable-next-line no-await-in-loop
|
|
84
|
+
await api.post(`/nodes/${nodeId}/alert-relay-pending`);
|
|
85
|
+
}
|
|
86
|
+
} catch (alertError) {
|
|
87
|
+
console.warn('relay alert failed:', alertError.message);
|
|
88
|
+
}
|
|
89
|
+
|
|
70
90
|
const deadline = Date.now() + timeoutMs;
|
|
71
91
|
while (Date.now() < deadline) {
|
|
72
92
|
const response = await api.get(`/relay/shards/fetch/${opId}`);
|