Compare commits
1 Commits
feat/f3-wa
...
feat/f3-pi
| Author | SHA1 | Date | |
|---|---|---|---|
| 6a80378e73 |
@@ -6,7 +6,7 @@ MOSAIC_TMUX_SOCKET=${MOSAIC_TMUX_SOCKET:-mosaic-factory}
|
||||
MOSAIC_AGENT_RUNTIME=${MOSAIC_AGENT_RUNTIME:-pi}
|
||||
MOSAIC_AGENT_WORKDIR=${MOSAIC_AGENT_WORKDIR:-$HOME}
|
||||
MOSAIC_AGENT_COMMAND=${MOSAIC_AGENT_COMMAND:-}
|
||||
MOSAIC_HEARTBEAT_RUN_DIR=${MOSAIC_HEARTBEAT_RUN_DIR:-$HOME/.config/mosaic/fleet/run}
|
||||
MOSAIC_HEARTBEAT_RUN_DIR=${MOSAIC_HEARTBEAT_RUN_DIR:-${MOSAIC_HOME:-$HOME/.config/mosaic}/fleet/run}
|
||||
MOSAIC_HEARTBEAT_INTERVAL=${MOSAIC_HEARTBEAT_INTERVAL:-15}
|
||||
|
||||
if [ -z "$AGENT_NAME" ]; then
|
||||
|
||||
@@ -851,6 +851,23 @@ describe('fleet ps — heartbeat parsing', () => {
|
||||
expect(hb.health).toBe('unknown');
|
||||
expect(hb.ts).toBeNull();
|
||||
});
|
||||
|
||||
it('honors MOSAIC_HEARTBEAT_INTERVAL for the freshness threshold', () => {
|
||||
const prev = process.env.MOSAIC_HEARTBEAT_INTERVAL;
|
||||
try {
|
||||
// A 60s-old beat is STALE at the default 15s interval (3x15 = 45s)...
|
||||
const ts = new Date(NOW - 60_000).toISOString();
|
||||
const content = `ts=${ts}\npid=1\nstatus=ok\n`;
|
||||
delete process.env.MOSAIC_HEARTBEAT_INTERVAL;
|
||||
expect(parseHeartbeat(content, NOW).health).toBe('stale');
|
||||
// ...but HEALTHY when the operator widened the interval to 30s (3x30 = 90s).
|
||||
process.env.MOSAIC_HEARTBEAT_INTERVAL = '30';
|
||||
expect(parseHeartbeat(content, NOW).health).toBe('healthy');
|
||||
} finally {
|
||||
if (prev === undefined) delete process.env.MOSAIC_HEARTBEAT_INTERVAL;
|
||||
else process.env.MOSAIC_HEARTBEAT_INTERVAL = prev;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('fleet ps — systemd show parsing', () => {
|
||||
|
||||
@@ -368,6 +368,16 @@ export function buildAgentTailCommand(
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const HEARTBEAT_INTERVAL_MS = 15_000;
|
||||
|
||||
/**
|
||||
* Heartbeat interval in ms, honoring MOSAIC_HEARTBEAT_INTERVAL (seconds) so the
|
||||
* `fleet ps` freshness threshold matches the writer sidecar's actual cadence
|
||||
* (start-agent-session.sh). Falls back to HEARTBEAT_INTERVAL_MS (15s).
|
||||
*/
|
||||
export function heartbeatIntervalMs(): number {
|
||||
const sec = Number.parseInt(process.env.MOSAIC_HEARTBEAT_INTERVAL ?? '', 10);
|
||||
return Number.isFinite(sec) && sec > 0 ? sec * 1000 : HEARTBEAT_INTERVAL_MS;
|
||||
}
|
||||
export const HEARTBEAT_HEALTHY_MULTIPLIER = 3;
|
||||
|
||||
export interface HeartbeatInfo {
|
||||
@@ -496,7 +506,7 @@ export function parseHeartbeat(content: string | null, nowMs = Date.now()): Hear
|
||||
status = val;
|
||||
}
|
||||
}
|
||||
const thresholdMs = HEARTBEAT_INTERVAL_MS * HEARTBEAT_HEALTHY_MULTIPLIER;
|
||||
const thresholdMs = heartbeatIntervalMs() * HEARTBEAT_HEALTHY_MULTIPLIER;
|
||||
let health: 'healthy' | 'stale' | 'unknown' = 'unknown';
|
||||
let ageMs: number | null = null;
|
||||
if (ts !== null) {
|
||||
|
||||
Reference in New Issue
Block a user