Files
peardata/server/services/warm-flush.js
T
Raven Scott c541c27ad8
CI / test (push) Successful in 1m17s
Release rolling / release (push) Successful in 8m15s
Prune work
2026-07-30 12:38:17 -04:00

80 lines
2.1 KiB
JavaScript

/**
* Flush memory tier1 (downsampled) points into HyperDB warm storage.
*
* Called from the pipeline when the in-memory store rolls a tier1 bucket,
* or on a periodic timer as a safety net.
*
* Cardinality gate: only static catalog charts are persisted by default
* (see isWarmPersistableChart). Instance charts remain in RAM rings only.
*/
import { getDb } from '../db/index.js'
import { isWarmPersistableChart } from '../../shared/metrics.js'
import logger from '../utils/logger.js'
const log = logger.child('warm-flush')
/** @type {Array<{ chart: string, context: string, ts: number, values: object }>} */
let pending = []
let flushing = false
let skippedHighCardinality = 0
/**
* Queue a warm point for HyperDB persistence.
* @param {{ chart: string, context: string, ts: number, values: object }} point
*/
export function enqueueWarmPoint(point) {
if (!isWarmPersistableChart(point.chart)) {
skippedHighCardinality++
return
}
pending.push({
chart: point.chart,
context: point.context || point.chart,
ts: point.ts,
values: point.values,
tier: 1,
})
}
/** @returns {{ pending: number, skippedHighCardinality: number }} */
export function warmFlushStats() {
return { pending: pending.length, skippedHighCardinality }
}
/**
* Flush pending warm points to HyperDB.
*/
export async function flushWarmPending() {
const db = getDb()
if (!db || !pending.length || flushing) return { inserted: 0 }
flushing = true
const batch = pending
pending = []
try {
const res = await db.putMetricPoints(batch)
log.debug?.('Flushed warm points', res)
return res
} catch (err) {
// re-queue on failure (bounded)
pending = batch.concat(pending).slice(-5000)
log.error('Warm flush failed', { error: err.message, requeued: batch.length })
return { inserted: 0, error: err.message }
} finally {
flushing = false
}
}
/**
* Persist an anomaly/alert event to HyperDB.
* @param {object} ev
*/
export async function persistAlertEvent(ev) {
const db = getDb()
if (!db) return
try {
await db.putAlertEvent(ev)
} catch (err) {
log.warn('Failed to persist alert event', { error: err.message })
}
}