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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodio-cli",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "Nodio distributed storage network",
5
5
  "main": "src/server/index.js",
6
6
  "type": "commonjs",
@@ -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 || 30000),
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)
@@ -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
  );
@@ -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;
@@ -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 = 120000, pollMs = 1500 }) {
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
- // Wait for donor heartbeats to pull relay tasks.
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 = 120000, pollMs = 1500 }) {
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}`);