Files
trade-drift-dlob/src/core/healthCheck.ts
2025-07-15 13:06:42 -07:00

100 lines
2.4 KiB
TypeScript

export enum HEALTH_STATUS {
Ok = 0,
StaleBulkAccountLoader,
UnhealthySlotSubscriber,
LivenessTesting,
Restart,
}
/**
* Health check configuration
*/
const HEALTH_CHECK_CONFIG = {
CHECK_INTERVAL_MS: 2000,
// Maximum time allowed between slot updates
MAX_SLOT_STALENESS_MS: 5000,
// Minimum expected slot advancement rate (slots slower than 1 per second is problematic)
MIN_SLOT_RATE: 1,
} as const;
/**
* Tracks the health state of the slot subscriber
*/
type HealthState = {
lastSlot: number;
lastSlotTimestamp: number;
};
const globalHealthState: HealthState = {
lastSlot: -1,
lastSlotTimestamp: Date.now(),
};
/**
* Evaluates if the current state is healthy based on slot progression
*/
function evaluateHealth(currentSlot: number): {
isHealthy: boolean;
reason?: string;
} {
const now = Date.now();
// First health check
if (globalHealthState.lastSlot === -1) {
globalHealthState.lastSlot = currentSlot;
globalHealthState.lastSlotTimestamp = now;
return { isHealthy: true };
}
const timeDelta = now - globalHealthState.lastSlotTimestamp;
const slotDelta = currentSlot - globalHealthState.lastSlot;
// If slot has progressed, we are healthy, check rate and update state.
if (currentSlot > globalHealthState.lastSlot) {
// Update state
globalHealthState.lastSlot = currentSlot;
globalHealthState.lastSlotTimestamp = now;
// Check if slot update rate is too low
const slotRate = (slotDelta / timeDelta) * 1000; // Convert to per second
if (slotRate < HEALTH_CHECK_CONFIG.MIN_SLOT_RATE) {
return {
isHealthy: false,
reason: `Slot update rate ${slotRate.toFixed(
2
)} slots/sec below minimum ${HEALTH_CHECK_CONFIG.MIN_SLOT_RATE}`,
};
}
return { isHealthy: true };
}
// If slot has NOT progressed, check for staleness.
if (timeDelta > HEALTH_CHECK_CONFIG.MAX_SLOT_STALENESS_MS) {
return {
isHealthy: false,
reason: `No slot updates in ${timeDelta}ms (max ${HEALTH_CHECK_CONFIG.MAX_SLOT_STALENESS_MS}ms)`,
};
}
// Slot has not progressed, but not stale yet. Still healthy.
return { isHealthy: true };
}
let healthStatus: HEALTH_STATUS = HEALTH_STATUS.Ok;
const setHealthStatus = (status: HEALTH_STATUS): void => {
healthStatus = status;
};
const getHealthStatus = (): HEALTH_STATUS => {
return healthStatus;
};
export {
evaluateHealth,
globalHealthState,
HEALTH_CHECK_CONFIG,
setHealthStatus,
getHealthStatus,
};