Files
order_site/apps/backend/src/repositories/realtime-event-repo.ts
T

74 lines
1.9 KiB
TypeScript

import { query } from '../db/client.js'
export type RealtimeEventRow = {
id: number
event_type: string
entity_id: number
scopes: unknown
operation: string
data: unknown
admin_audience: boolean
worker_ids: unknown
broadcast_workers: boolean
occurred_at: string
}
export async function createRealtimeEvent(input: {
eventType: string
entityId: number
scopes: string[]
operation: string
data?: unknown
adminAudience: boolean
workerIds: number[]
broadcastWorkers: boolean
occurredAt: string
}): Promise<RealtimeEventRow> {
const result = await query<RealtimeEventRow>(
`
INSERT INTO realtime_events (
event_type, entity_id, scopes, operation, data,
admin_audience, worker_ids, broadcast_workers, occurred_at
) VALUES ($1, $2, $3::jsonb, $4, $5::jsonb, $6, $7::jsonb, $8, $9)
RETURNING *
`,
[
input.eventType,
input.entityId,
JSON.stringify(input.scopes),
input.operation,
input.data === undefined ? null : JSON.stringify(input.data),
input.adminAudience,
JSON.stringify(input.workerIds),
input.broadcastWorkers,
input.occurredAt,
],
)
const row = result.rows[0]
if (!row) throw new Error('realtime_event_create_failed')
// 事件仅用于短期断线补发;每 100 条清理一次,避免每次业务事件都额外触发 DELETE。
if (Number(row.id) % 100 === 0) {
await query(
`
DELETE FROM realtime_events
WHERE id < GREATEST(0, (SELECT COALESCE(MAX(id), 0) - 500 FROM realtime_events))
`,
)
}
return row
}
export async function listRealtimeEventsAfter(eventId: number, limit = 500) {
const result = await query<RealtimeEventRow>(
`
SELECT * FROM realtime_events
WHERE id > $1
ORDER BY id ASC
LIMIT $2
`,
[Math.max(0, Number(eventId) || 0), Math.min(500, Math.max(1, Number(limit) || 500))],
)
return result.rows
}