| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| import { and, desc, eq } from "drizzle-orm"; |
| import { |
| db, |
| networkEvolutionEvents, |
| type NetworkEvolutionEventRow, |
| } from "@workspace/db"; |
| import { newId } from "../ids"; |
|
|
| export type EvolutionEventKind = |
| | "cadence_trigger" |
| | "regression_trigger" |
| | "coverage_trigger" |
| | "shadow_started" |
| | "shadow_budget_skipped" |
| | "shadow_budget_threshold" |
| | "shadow_runner_error" |
| | "shadow_reviewer_fallback" |
| | "shadow_no_active_cost" |
| | "auto_promote_skipped" |
| | "promote" |
| | "rollback" |
| | "regression_suite_failed" |
| |
| |
| |
| |
| |
| | "builder_proposed" |
| | "builder_no_candidate" |
| | "builder_error" |
| |
| |
| |
| | "strategy_changed" |
| |
| |
| |
| |
| |
| |
| |
| | "external_truth_backfilled" |
| | "external_truth_trigger"; |
|
|
| export interface RecordEventInput { |
| networkId: string; |
| kind: EvolutionEventKind; |
| variantId?: string | null; |
| payload?: Record<string, unknown>; |
| relatedEventId?: string | null; |
| promotionId?: string | null; |
| } |
|
|
| export async function recordEvent( |
| input: RecordEventInput, |
| ): Promise<NetworkEvolutionEventRow> { |
| const id = newId("nevt"); |
| await db.insert(networkEvolutionEvents).values({ |
| id, |
| networkId: input.networkId, |
| kind: input.kind, |
| variantId: input.variantId ?? null, |
| payload: (input.payload ?? {}) as Record<string, unknown>, |
| relatedEventId: input.relatedEventId ?? null, |
| promotionId: input.promotionId ?? null, |
| }); |
| return ( |
| await db |
| .select() |
| .from(networkEvolutionEvents) |
| .where(eq(networkEvolutionEvents.id, id)) |
| .limit(1) |
| )[0]!; |
| } |
|
|
| export interface ListEventsOptions { |
| networkId?: string; |
| kind?: EvolutionEventKind; |
| limit?: number; |
| } |
|
|
| export async function listEvents( |
| opts: ListEventsOptions = {}, |
| ): Promise<NetworkEvolutionEventRow[]> { |
| const conds = []; |
| if (opts.networkId) { |
| conds.push(eq(networkEvolutionEvents.networkId, opts.networkId)); |
| } |
| if (opts.kind) { |
| conds.push(eq(networkEvolutionEvents.kind, opts.kind)); |
| } |
| const where = conds.length ? and(...conds) : undefined; |
| const q = db |
| .select() |
| .from(networkEvolutionEvents) |
| .orderBy(desc(networkEvolutionEvents.createdAt)) |
| .limit(Math.min(opts.limit ?? 200, 1000)); |
| return where ? q.where(where) : q; |
| } |
|
|