update health check faster
This commit is contained in:
@@ -12,10 +12,9 @@ import {
|
||||
commitHash,
|
||||
driftEnv,
|
||||
endpoint,
|
||||
getSlotHealthCheckInfo,
|
||||
wsEndpoint,
|
||||
} from '..';
|
||||
import { E_ALREADY_LOCKED, tryAcquire } from 'async-mutex';
|
||||
import { SlotSource } from '@drift-labs/sdk';
|
||||
|
||||
/**
|
||||
* Creates {count} buckets of size {increment} starting from {start}. Each bucket stores the count of values within its "size".
|
||||
@@ -129,34 +128,31 @@ let lastHealthCheckPerformed = Date.now() - healthCheckInterval;
|
||||
* We may be hit by multiple sources performing health checks on us, so this middleware will latch
|
||||
* to its health state and only update every `healthCheckInterval`.
|
||||
*/
|
||||
const handleHealthCheck = async (req, res, next) => {
|
||||
if (Date.now() < lastHealthCheckPerformed + healthCheckInterval) {
|
||||
if (lastHealthCheckState) {
|
||||
res.writeHead(200);
|
||||
res.end('OK');
|
||||
lastHealthCheckPerformed = Date.now();
|
||||
return;
|
||||
}
|
||||
// always check if last check was unhealthy (give it another chance to recover)
|
||||
}
|
||||
|
||||
const { lastSlotReceived, lastSlotReceivedMutex } = getSlotHealthCheckInfo();
|
||||
|
||||
try {
|
||||
await tryAcquire(lastSlotReceivedMutex).runExclusive(async () => {
|
||||
// healthy if slot has advanced since the last check
|
||||
lastHealthCheckState = lastSlotReceived > lastHealthCheckSlot;
|
||||
if (!lastHealthCheckState) {
|
||||
logger.error(
|
||||
`Unhealthy: lastSlot: ${lastSlotReceived}, lastHealthCheckSlot: ${lastHealthCheckSlot}, timeSinceLastCheck: ${
|
||||
Date.now() - lastHealthCheckPerformed
|
||||
} ms`
|
||||
);
|
||||
const handleHealthCheck = (slotSource: SlotSource) => {
|
||||
return async (_req, res, _next) => {
|
||||
if (Date.now() < lastHealthCheckPerformed + healthCheckInterval) {
|
||||
if (lastHealthCheckState) {
|
||||
res.writeHead(200);
|
||||
res.end('OK');
|
||||
lastHealthCheckPerformed = Date.now();
|
||||
return;
|
||||
}
|
||||
// always check if last check was unhealthy (give it another chance to recover)
|
||||
}
|
||||
|
||||
lastHealthCheckSlot = lastSlotReceived;
|
||||
lastHealthCheckPerformed = Date.now();
|
||||
});
|
||||
// healthy if slot has advanced since the last check
|
||||
const lastSlotReceived = slotSource.getSlot();
|
||||
lastHealthCheckState = lastSlotReceived > lastHealthCheckSlot;
|
||||
if (!lastHealthCheckState) {
|
||||
logger.error(
|
||||
`Unhealthy: lastSlot: ${lastSlotReceived}, lastHealthCheckSlot: ${lastHealthCheckSlot}, timeSinceLastCheck: ${
|
||||
Date.now() - lastHealthCheckPerformed
|
||||
} ms`
|
||||
);
|
||||
}
|
||||
|
||||
lastHealthCheckSlot = lastSlotReceived;
|
||||
lastHealthCheckPerformed = Date.now();
|
||||
|
||||
if (!lastHealthCheckState) {
|
||||
healthStatus = HEALTH_STATUS.UnhealthySlotSubscriber;
|
||||
@@ -169,24 +165,7 @@ const handleHealthCheck = async (req, res, next) => {
|
||||
healthStatus = HEALTH_STATUS.Ok;
|
||||
res.writeHead(200);
|
||||
res.end('OK');
|
||||
} catch (e) {
|
||||
if (e === E_ALREADY_LOCKED) {
|
||||
// someone else is updating the slot, just return the latched state
|
||||
if (lastHealthCheckState) {
|
||||
logger.error(`DlobServer is healthy (busy mutex)`);
|
||||
res.writeHead(200);
|
||||
res.end('OK');
|
||||
} else {
|
||||
logger.error(`DlobServer is not healthy (busy mutex)`);
|
||||
res.writeHead(500);
|
||||
res.end(`NOK`);
|
||||
}
|
||||
} else {
|
||||
logger.error(`Error in health check: ${e.message}`);
|
||||
console.error(e);
|
||||
next(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export {
|
||||
|
||||
35
src/index.ts
35
src/index.ts
@@ -32,7 +32,6 @@ import {
|
||||
|
||||
import { logger, setLogLevel } from './utils/logger';
|
||||
|
||||
import { Mutex } from 'async-mutex';
|
||||
import * as http from 'http';
|
||||
import { handleHealthCheck } from './core/metrics';
|
||||
import { handleResponseTime } from './core/middleware';
|
||||
@@ -136,13 +135,6 @@ logger.info(`Commit: ${commitHash}`);
|
||||
|
||||
let MARKET_SUBSCRIBERS: SubscriberLookup = {};
|
||||
|
||||
const lastSlotReceivedMutex = new Mutex();
|
||||
let lastSlotReceived: number;
|
||||
|
||||
export const getSlotHealthCheckInfo = () => {
|
||||
return { lastSlotReceived, lastSlotReceivedMutex };
|
||||
};
|
||||
|
||||
const initializeAllMarketSubscribers = async (driftClient: DriftClient) => {
|
||||
const markets: SubscriberLookup = {};
|
||||
|
||||
@@ -272,10 +264,6 @@ const main = async () => {
|
||||
logger.error(e);
|
||||
});
|
||||
|
||||
setInterval(async () => {
|
||||
lastSlotReceived = slotSource.getSlot();
|
||||
}, ORDERBOOK_UPDATE_INTERVAL);
|
||||
|
||||
logger.info(`Initializing DLOB Provider...`);
|
||||
const initDLOBProviderStart = Date.now();
|
||||
await dlobProvider.subscribe();
|
||||
@@ -284,9 +272,15 @@ const main = async () => {
|
||||
);
|
||||
logger.info(`dlob provider size ${dlobProvider.size()}`);
|
||||
if (useWebsocket) {
|
||||
setInterval(async () => {
|
||||
await dlobProvider.fetch();
|
||||
}, WS_FALLBACK_FETCH_INTERVAL);
|
||||
const recursiveFetch = (delay = WS_FALLBACK_FETCH_INTERVAL) => {
|
||||
setTimeout(() => {
|
||||
dlobProvider.fetch().then(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
recursiveFetch();
|
||||
});
|
||||
}, delay);
|
||||
};
|
||||
recursiveFetch();
|
||||
}
|
||||
|
||||
logger.info(`Initializing DLOBSubscriber...`);
|
||||
@@ -302,7 +296,14 @@ const main = async () => {
|
||||
`DLOBSubscriber initialized in ${Date.now() - initDlobSubscriberStart} ms`
|
||||
);
|
||||
|
||||
logger.info(`Initializing all market subscribers...`);
|
||||
const initAllMarketSubscribersStart = Date.now();
|
||||
MARKET_SUBSCRIBERS = await initializeAllMarketSubscribers(driftClient);
|
||||
logger.info(
|
||||
`All market subscribers initialized in ${
|
||||
Date.now() - initAllMarketSubscribersStart
|
||||
} ms`
|
||||
);
|
||||
|
||||
const handleStartup = async (_req, res, _next) => {
|
||||
if (driftClient.isSubscribed && dlobProvider.size() > 0) {
|
||||
@@ -314,9 +315,9 @@ const main = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
app.get('/health', handleHealthCheck);
|
||||
app.get('/health', handleHealthCheck(slotSource));
|
||||
app.get('/startup', handleStartup);
|
||||
app.get('/', handleHealthCheck);
|
||||
app.get('/', handleHealthCheck(slotSource));
|
||||
|
||||
app.get('/orders/json/raw', async (_req, res, next) => {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user