feat(engine): 实现同步引擎与 engine_status 快照

apps/engine 独立进程(syncRound + 防重叠调度);上游 log/token;QPU 采样;
server 读 engine_status;时刻出参 toUnixSec;中文日志;zod-openapi 扩展顺序修复。
This commit is contained in:
2026-10-07 12:54:13 +08:00
parent 3e12db1706
commit d47cb5543c
28 changed files with 676 additions and 102 deletions
+90
View File
@@ -2,6 +2,7 @@ import type { Db } from "./index.ts";
import {
apiKeys,
auditLogs,
engineStatus,
members,
payments,
qpuHistory,
@@ -10,6 +11,7 @@ import {
users,
type ApiKeyRow,
type AuditLogRow,
type EngineStatusRow,
type MemberRow,
type PaymentRow,
type SessionRow,
@@ -148,6 +150,54 @@ export function createRepos(db: Db) {
}
return base;
},
async listActive() {
return db
.select({
id: apiKeys.id,
key_hash: apiKeys.key_hash,
key_ciphertext: apiKeys.key_ciphertext,
status: apiKeys.status,
member_id: apiKeys.member_id,
token_name: apiKeys.token_name,
})
.from(apiKeys)
.where(eq(apiKeys.status, "active"))
.orderBy(asc(apiKeys.id));
},
async insertLog(values: {
api_key_id: number;
dedupe_key: string;
billing_source: string | null;
subscription_id: number | null;
user_id: number;
created_at: Date;
type: number;
content: string;
username: string;
token_name: string;
model_name: string;
quota: number;
prompt_tokens: number;
completion_tokens: number;
use_time: number;
is_stream: boolean;
channel: number;
channel_name: string;
token_id: number;
group_name: string;
ip: string;
request_id: string;
upstream_request_id: string | null;
other: unknown;
}): Promise<boolean> {
const before = await db
.select({ n: count() })
.from(usageLogs)
.where(eq(usageLogs.dedupe_key, values.dedupe_key));
if ((before[0]?.n ?? 0) > 0) return false;
await db.insert(usageLogs).values(values).onConflictDoNothing();
return true;
},
async findById(id: number): Promise<ApiKeyRow | null> {
const rows = await db
.select()
@@ -293,6 +343,43 @@ export function createRepos(db: Db) {
},
},
engine: {
async upsertSnapshot(values: {
running: boolean;
sync_interval_ms: number;
last_round: unknown;
}): Promise<EngineStatusRow> {
const [row] = await db
.insert(engineStatus)
.values({
id: 1,
running: values.running,
sync_interval_ms: values.sync_interval_ms,
last_round: values.last_round,
updated_at: new Date(),
})
.onConflictDoUpdate({
target: engineStatus.id,
set: {
running: values.running,
sync_interval_ms: values.sync_interval_ms,
last_round: values.last_round,
updated_at: new Date(),
},
})
.returning();
return row!;
},
async getSnapshot(): Promise<EngineStatusRow | null> {
const rows = await db
.select()
.from(engineStatus)
.where(eq(engineStatus.id, 1))
.limit(1);
return rows[0] ?? null;
},
},
payments: {
async listAll(): Promise<PaymentRow[]> {
return db.select().from(payments).orderBy(desc(payments.paid_at));
@@ -354,6 +441,9 @@ export function createRepos(db: Db) {
.limit(1);
return rows[0] ?? null;
},
async insertChange(qpu: number, effective_from: Date): Promise<void> {
await db.insert(qpuHistory).values({ qpu, effective_from });
},
},
logs: {
+14
View File
@@ -191,6 +191,19 @@ export const auditLogs = pgTable(
(t) => [index("audit_logs_created_at_idx").on(t.created_at)],
);
/** 同步引擎状态单行快照(《同步引擎设计》§5) */
export const engineStatus = pgTable("engine_status", {
id: integer("id").primaryKey().default(1),
running: boolean("running").notNull().default(false),
sync_interval_ms: bigint("sync_interval_ms", { mode: "number" })
.notNull()
.default(300_000),
last_round: jsonb("last_round"),
updated_at: timestamp("updated_at", { withTimezone: true, mode: "date" })
.notNull()
.defaultNow(),
});
export type MemberRow = typeof members.$inferSelect;
export type ApiKeyRow = typeof apiKeys.$inferSelect;
export type UsageLogRow = typeof usageLogs.$inferSelect;
@@ -199,3 +212,4 @@ export type QpuHistoryRow = typeof qpuHistory.$inferSelect;
export type UserRow = typeof users.$inferSelect;
export type SessionRow = typeof sessions.$inferSelect;
export type AuditLogRow = typeof auditLogs.$inferSelect;
export type EngineStatusRow = typeof engineStatus.$inferSelect;