UNPKG

@clickup/pg-microsharding

Version:
84 lines (79 loc) 2.24 kB
import { createConnectedClient } from "./createConnectedClient"; import { subtractLsn } from "./parseLsn"; export interface SlotInfo { srcLsn: string; dstLsn: string; gap: number; gapTillLatch: number; lagSec: number | null; latched: { srcLsn: string; at: number; }; } /** * Returns the difference between src LSN and dst LSN (gap), along with some * estimation on how much seconds they are apart from each other. To measure * that time, we "latch" an LSN on the src and then wait until dst crosses that * latched LSN. Once it does, we remember the actual astronomical time it took * to cross, and then latch the src LSN again (towards the next estimation * cycle). When the caller decides that the time is small enough, it stops * polling; and if the time is large (e.g. more than 20 seconds), it continues * to call getSlotInfo() over and over again until that time drops below the * needed 20 seconds threshold. */ export async function getSlotInfo( { dsn, slotName, }: { dsn: string; slotName: string; }, prevSlotInfo: SlotInfo | undefined, ): Promise<SlotInfo> { const client = await createConnectedClient(dsn); try { const srcLsn = await client.currentWalInsertLsn(); const dstLsn = await client.confirmedFlushLsn(slotName); const gap = subtractLsn(srcLsn, dstLsn)!; if (!prevSlotInfo) { prevSlotInfo = { srcLsn, dstLsn, gap, gapTillLatch: gap, lagSec: null, // means "unknown" latched: { srcLsn, at: performance.now(), }, }; } const gapTillLatch = subtractLsn(prevSlotInfo.latched.srcLsn, dstLsn)!; return gapTillLatch <= 0 ? { srcLsn, dstLsn, gap, gapTillLatch, lagSec: Math.round( (performance.now() - prevSlotInfo.latched.at) / 1000, ), latched: { srcLsn, at: performance.now(), }, } : { srcLsn, dstLsn, gap, gapTillLatch, lagSec: prevSlotInfo.lagSec, latched: prevSlotInfo.latched, }; } finally { await client.end().catch(() => {}); } }