wilfredwake 1.0.6 → 1.0.7
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
package/src/cli/commands/wake.js
CHANGED
|
@@ -82,13 +82,22 @@ export async function wakeCommand(target, options) {
|
|
|
82
82
|
_displayWakeResults(results);
|
|
83
83
|
|
|
84
84
|
// ═══════════════════════════════════════════════════════════════
|
|
85
|
-
// DISPLAY FINAL STATUS
|
|
85
|
+
// DISPLAY FINAL STATUS AND START MONITORING
|
|
86
86
|
// ═══════════════════════════════════════════════════════════════
|
|
87
87
|
if (shouldWait) {
|
|
88
88
|
_displayFinalStatus(results);
|
|
89
|
+
|
|
90
|
+
// Start 5-minute monitoring period
|
|
91
|
+
await _monitorServicesForDuration(
|
|
92
|
+
config.orchestratorUrl,
|
|
93
|
+
config.token,
|
|
94
|
+
env,
|
|
95
|
+
wakeTarget,
|
|
96
|
+
5 * 60 * 1000 // 5 minutes in milliseconds
|
|
97
|
+
);
|
|
89
98
|
}
|
|
90
99
|
|
|
91
|
-
process.exit(
|
|
100
|
+
process.exit(0);
|
|
92
101
|
} catch (error) {
|
|
93
102
|
stopSpinner?.();
|
|
94
103
|
throw error;
|
|
@@ -180,3 +189,167 @@ function _displayFinalStatus(results) {
|
|
|
180
189
|
|
|
181
190
|
console.log('');
|
|
182
191
|
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Monitor services for a duration and display live status updates
|
|
195
|
+
* @private
|
|
196
|
+
* @param {string} orchestratorUrl - Orchestrator URL
|
|
197
|
+
* @param {string} token - Authorization token
|
|
198
|
+
* @param {string} env - Environment name
|
|
199
|
+
* @param {string} wakeTarget - Wake target (all, <service>, or <group>)
|
|
200
|
+
* @param {number} duration - Duration in milliseconds
|
|
201
|
+
*/
|
|
202
|
+
async function _monitorServicesForDuration(
|
|
203
|
+
orchestratorUrl,
|
|
204
|
+
token,
|
|
205
|
+
env,
|
|
206
|
+
wakeTarget,
|
|
207
|
+
duration
|
|
208
|
+
) {
|
|
209
|
+
const pollInterval = 10000; // Poll every 10 seconds
|
|
210
|
+
const startTime = Date.now();
|
|
211
|
+
const endTime = startTime + duration;
|
|
212
|
+
let pollCount = 0;
|
|
213
|
+
|
|
214
|
+
console.log(
|
|
215
|
+
chalk.magentaBright.bold(
|
|
216
|
+
`📡 Monitoring services for ${Math.round(duration / 1000)}s...\n`
|
|
217
|
+
)
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
while (Date.now() < endTime) {
|
|
221
|
+
pollCount++;
|
|
222
|
+
const elapsedSeconds = Math.round((Date.now() - startTime) / 1000);
|
|
223
|
+
|
|
224
|
+
try {
|
|
225
|
+
// Fetch current status from orchestrator
|
|
226
|
+
const response = await axios.get(
|
|
227
|
+
`${orchestratorUrl}/api/status`,
|
|
228
|
+
{
|
|
229
|
+
params: {
|
|
230
|
+
environment: env,
|
|
231
|
+
},
|
|
232
|
+
timeout: 5000,
|
|
233
|
+
headers: {
|
|
234
|
+
Authorization: token ? `Bearer ${token}` : undefined,
|
|
235
|
+
},
|
|
236
|
+
}
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
const services = response.data.services || [];
|
|
240
|
+
|
|
241
|
+
// Clear screen and display updated status
|
|
242
|
+
console.clear();
|
|
243
|
+
console.log(chalk.cyanBright.bold('📡 Live Service Monitoring\n'));
|
|
244
|
+
console.log(
|
|
245
|
+
chalk.gray(`Elapsed: ${chalk.yellow(elapsedSeconds)}s / ${Math.round(duration / 1000)}s | Poll #${pollCount}\n`)
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
// Display table with current status
|
|
249
|
+
_displayLiveMonitoringTable(services, env);
|
|
250
|
+
|
|
251
|
+
// Display summary stats
|
|
252
|
+
_displayLiveMonitoringSummary(services);
|
|
253
|
+
} catch (error) {
|
|
254
|
+
console.clear();
|
|
255
|
+
console.log(chalk.cyanBright.bold('📡 Live Service Monitoring\n'));
|
|
256
|
+
console.log(
|
|
257
|
+
chalk.gray(`Elapsed: ${chalk.yellow(elapsedSeconds)}s / ${Math.round(duration / 1000)}s | Poll #${pollCount}\n`)
|
|
258
|
+
);
|
|
259
|
+
logger.warn(`Status check failed: ${error.message}`);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Wait before next poll (unless we're at the end)
|
|
263
|
+
if (Date.now() < endTime) {
|
|
264
|
+
await new Promise(resolve => setTimeout(resolve, pollInterval));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Final summary
|
|
269
|
+
console.clear();
|
|
270
|
+
console.log(chalk.cyanBright.bold('📡 Monitoring Complete\n'));
|
|
271
|
+
console.log(chalk.yellow(`Total monitoring duration: ${Math.round(duration / 1000)}s\n`));
|
|
272
|
+
|
|
273
|
+
try {
|
|
274
|
+
// Fetch final status
|
|
275
|
+
const response = await axios.get(
|
|
276
|
+
`${orchestratorUrl}/api/status`,
|
|
277
|
+
{
|
|
278
|
+
params: {
|
|
279
|
+
environment: env,
|
|
280
|
+
},
|
|
281
|
+
timeout: 5000,
|
|
282
|
+
headers: {
|
|
283
|
+
Authorization: token ? `Bearer ${token}` : undefined,
|
|
284
|
+
},
|
|
285
|
+
}
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
const services = response.data.services || [];
|
|
289
|
+
_displayLiveMonitoringTable(services, env);
|
|
290
|
+
_displayLiveMonitoringSummary(services);
|
|
291
|
+
} catch (error) {
|
|
292
|
+
logger.warn(`Could not fetch final status: ${error.message}`);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
console.log('');
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Display live monitoring status table
|
|
300
|
+
* @private
|
|
301
|
+
* @param {Array} services - Services array
|
|
302
|
+
* @param {string} environment - Environment name
|
|
303
|
+
*/
|
|
304
|
+
function _displayLiveMonitoringTable(services, environment) {
|
|
305
|
+
if (services.length === 0) {
|
|
306
|
+
logger.info('No services to display.');
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
console.log(chalk.cyanBright.bold(`Services (${environment.toUpperCase()})\n`));
|
|
311
|
+
|
|
312
|
+
const headers = ['Service', 'Status', 'Last Woken', 'URL'];
|
|
313
|
+
console.log(format.tableHeader(headers));
|
|
314
|
+
|
|
315
|
+
services.forEach((service) => {
|
|
316
|
+
const statusColor = colors.status[service.status] || colors.status.unknown;
|
|
317
|
+
const lastWoken = service.lastWakeTime
|
|
318
|
+
? new Date(service.lastWakeTime).toLocaleString()
|
|
319
|
+
: 'Never';
|
|
320
|
+
const cells = [
|
|
321
|
+
chalk.cyan(service.name.padEnd(20)),
|
|
322
|
+
statusColor(service.status.toUpperCase().padEnd(20)),
|
|
323
|
+
chalk.yellow(lastWoken.padEnd(20)),
|
|
324
|
+
chalk.gray((service.url || '').substring(0, 20).padEnd(20)),
|
|
325
|
+
];
|
|
326
|
+
console.log(format.tableRow(cells));
|
|
327
|
+
console.log('');
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
console.log('');
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Display live monitoring summary stats
|
|
335
|
+
* @private
|
|
336
|
+
* @param {Array} services - Services array
|
|
337
|
+
*/
|
|
338
|
+
function _displayLiveMonitoringSummary(services) {
|
|
339
|
+
if (services.length === 0) return;
|
|
340
|
+
|
|
341
|
+
const stats = {
|
|
342
|
+
total: services.length,
|
|
343
|
+
live: services.filter(s => s.status === 'live').length,
|
|
344
|
+
dead: services.filter(s => s.status === 'dead').length,
|
|
345
|
+
waking: services.filter(s => s.status === 'waking').length,
|
|
346
|
+
failed: services.filter(s => s.status === 'failed').length,
|
|
347
|
+
unknown: services.filter(s => s.status === 'unknown').length,
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
console.log(chalk.magentaBright.bold('Summary'));
|
|
351
|
+
console.log(
|
|
352
|
+
` ${colors.status.live('✓')} Live: ${colors.status.live(stats.live)} | ${colors.status.dead('⚫')} Dead: ${colors.status.dead(stats.dead)} | ${colors.status.waking('⟳')} Waking: ${colors.status.waking(stats.waking)} | ${colors.status.failed('✗')} Failed: ${colors.status.failed(stats.failed)} | ${colors.status.unknown('?')} Unknown: ${colors.status.unknown(stats.unknown)}`
|
|
353
|
+
);
|
|
354
|
+
console.log(` Total: ${stats.total} services\n`);
|
|
355
|
+
}
|
|
@@ -283,14 +283,13 @@ export class Orchestrator {
|
|
|
283
283
|
// ═══════════════════════════════════════════════════════════════
|
|
284
284
|
// DETERMINE STATE FROM STATUS CODE
|
|
285
285
|
// ═══════════════════════════════════════════════════════════════
|
|
286
|
-
//
|
|
287
|
-
//
|
|
288
|
-
//
|
|
289
|
-
// response is received" behavior.
|
|
286
|
+
// NEW LOGIC: If we get ANY response from the API (2xx, 3xx, 4xx, 5xx),
|
|
287
|
+
// mark the service as LIVE. This means the service is responsive.
|
|
288
|
+
// Only mark as FAILED if no response is received at all.
|
|
290
289
|
let state = ServiceState.LIVE;
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
290
|
+
|
|
291
|
+
// If we got a response, the service is responsive = LIVE
|
|
292
|
+
// No need to check status code, any response means service can be reached
|
|
294
293
|
|
|
295
294
|
this._logTimestamp(
|
|
296
295
|
service.name,
|
|
@@ -313,7 +312,7 @@ export class Orchestrator {
|
|
|
313
312
|
);
|
|
314
313
|
|
|
315
314
|
return {
|
|
316
|
-
state: ServiceState.DEAD, //
|
|
315
|
+
state: ServiceState.DEAD, // Only dead if no response received
|
|
317
316
|
statusCode: null,
|
|
318
317
|
responseTime,
|
|
319
318
|
error: error.message,
|