mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 16:02:32 +00:00
* refactor(cloud): share PostgreSQL schema startup between services * feat(cloud): add durable native push notification gateway * infra(push): define dedicated gateway resources and operational checks * fix(push): bound cross-host admission and simplify gateway configuration * fix(push): validate deploy configuration and preserve topic-error registrations
57 lines
1.5 KiB
TypeScript
57 lines
1.5 KiB
TypeScript
const COUNTER_NAMES = [
|
|
'ip_rate_limited',
|
|
'request_error',
|
|
'challenge_issued',
|
|
'challenge_rejected',
|
|
'session_issued',
|
|
'session_rejected',
|
|
'device_registered',
|
|
'device_rejected',
|
|
'device_deleted',
|
|
'send_queued',
|
|
'send_dead',
|
|
'send_rate_limited',
|
|
'send_error',
|
|
'delivery_sent',
|
|
'delivery_dead',
|
|
'delivery_error',
|
|
'delivery_retry'
|
|
] as const
|
|
|
|
type PushCounterName = (typeof COUNTER_NAMES)[number]
|
|
|
|
// Aggregate counters only. Nothing here may accept a token, a title, a body,
|
|
// or more than the first four characters of a host fingerprint.
|
|
export class PushObservability {
|
|
private counters = new Map<PushCounterName, number>()
|
|
private timer: NodeJS.Timeout | null = null
|
|
|
|
record(name: PushCounterName, delta = 1): void {
|
|
this.counters.set(name, (this.counters.get(name) ?? 0) + delta)
|
|
}
|
|
|
|
consume(): Record<PushCounterName, number> {
|
|
const snapshot = Object.fromEntries(
|
|
COUNTER_NAMES.map((name) => [name, this.counters.get(name) ?? 0])
|
|
) as Record<PushCounterName, number>
|
|
this.counters = new Map()
|
|
return snapshot
|
|
}
|
|
|
|
start(intervalMs = 60_000): void {
|
|
if (this.timer) return
|
|
this.timer = setInterval(() => {
|
|
const counters = this.consume()
|
|
if (Object.values(counters).every((value) => value === 0)) return
|
|
console.warn(JSON.stringify({ event: 'orca_push_counters', ...counters }))
|
|
}, intervalMs)
|
|
this.timer.unref()
|
|
}
|
|
|
|
stop(): void {
|
|
if (!this.timer) return
|
|
clearInterval(this.timer)
|
|
this.timer = null
|
|
}
|
|
}
|