export const HERMES_RUN_REF_MAX_ENTRIES = 10_000 export type HermesSortableRunRef = { id: string run_at: string | null } export type BoundedHermesRunRefs = { refs: T[] saturated: boolean } export class HermesRunRefRetainer { private readonly retained: T[] = [] private readonly pending: T[] = [] private readonly maxEntries: number private seen = 0 constructor(maxEntries = HERMES_RUN_REF_MAX_ENTRIES) { this.maxEntries = Number.isFinite(maxEntries) ? Math.max(0, Math.min(HERMES_RUN_REF_MAX_ENTRIES, Math.floor(maxEntries))) : HERMES_RUN_REF_MAX_ENTRIES } add(ref: T): void { this.seen += 1 if (this.maxEntries === 0) { return } this.pending.push(ref) if (this.pending.length >= this.maxEntries) { this.flush() } } finish(): BoundedHermesRunRefs { this.flush() return { refs: this.retained.slice(), saturated: this.seen > this.maxEntries } } private flush(): void { if (this.pending.length === 0) { return } for (const ref of this.pending) { this.retained.push(ref) } this.pending.length = 0 this.retained.sort(compareHermesRunRefsNewestFirst) if (this.retained.length > this.maxEntries) { this.retained.length = this.maxEntries } } } export function compareHermesRunRefsNewestFirst( left: HermesSortableRunRef, right: HermesSortableRunRef ): number { const leftTime = left.run_at ? Date.parse(left.run_at) : Number.NaN const rightTime = right.run_at ? Date.parse(right.run_at) : Number.NaN if (Number.isFinite(leftTime) && Number.isFinite(rightTime)) { return rightTime - leftTime } return right.id.localeCompare(left.id) }