From ff77ca772d4e22348fba786cf55f1eb2d62c2c02 Mon Sep 17 00:00:00 2001 From: Independent Security Research Date: Sun, 8 Mar 2026 21:38:30 +0000 Subject: [PATCH] feat: add database schema for request shaper --- .../drizzle/migrations/0016_hard_vulcan.sql | 11 +++++++++++ packages/backend/drizzle/schema/index.ts | 3 +++ .../backend/drizzle/schema/postgres/index.ts | 2 ++ .../schema/postgres/provider-rate-limits.ts | 17 +++++++++++++++++ .../backend/drizzle/schema/sqlite/index.ts | 2 ++ .../schema/sqlite/provider-rate-limits.ts | 18 ++++++++++++++++++ 6 files changed, 53 insertions(+) create mode 100644 packages/backend/drizzle/migrations/0016_hard_vulcan.sql create mode 100644 packages/backend/drizzle/schema/postgres/provider-rate-limits.ts create mode 100644 packages/backend/drizzle/schema/sqlite/provider-rate-limits.ts diff --git a/packages/backend/drizzle/migrations/0016_hard_vulcan.sql b/packages/backend/drizzle/migrations/0016_hard_vulcan.sql new file mode 100644 index 00000000..8a769474 --- /dev/null +++ b/packages/backend/drizzle/migrations/0016_hard_vulcan.sql @@ -0,0 +1,11 @@ +CREATE TABLE `provider_rate_limits` ( + `provider` text NOT NULL, + `model` text NOT NULL, + `current_budget` integer NOT NULL, + `last_refill_at` integer NOT NULL, + `queue_depth` integer DEFAULT 0 NOT NULL, + `created_at` integer NOT NULL, + PRIMARY KEY(`provider`, `model`) +); +--> statement-breakpoint +CREATE INDEX `idx_rate_limits_last_refill` ON `provider_rate_limits` (`last_refill_at`); \ No newline at end of file diff --git a/packages/backend/drizzle/schema/index.ts b/packages/backend/drizzle/schema/index.ts index b5754bf6..c39127bc 100644 --- a/packages/backend/drizzle/schema/index.ts +++ b/packages/backend/drizzle/schema/index.ts @@ -8,6 +8,7 @@ export * from './sqlite/quota-snapshots'; export * from './sqlite/responses'; export * from './sqlite/mcp'; export * from './sqlite/quota-state'; +export * from './sqlite/provider-rate-limits'; export { requestUsageRelations, debugLogsRelations, @@ -31,3 +32,5 @@ export { mcpDebugLogs as pgMcpDebugLogs, } from './postgres/mcp'; export { quotaState as pgQuotaState } from './postgres/quota-state'; + +export { providerRateLimits as pgProviderRateLimits } from './postgres/provider-rate-limits'; \ No newline at end of file diff --git a/packages/backend/drizzle/schema/postgres/index.ts b/packages/backend/drizzle/schema/postgres/index.ts index 917e84b3..e6bfb274 100644 --- a/packages/backend/drizzle/schema/postgres/index.ts +++ b/packages/backend/drizzle/schema/postgres/index.ts @@ -7,3 +7,5 @@ export * from './quota-snapshots'; export * from './responses'; export * from './mcp'; export * from './quota-state'; + +export * from './provider-rate-limits'; \ No newline at end of file diff --git a/packages/backend/drizzle/schema/postgres/provider-rate-limits.ts b/packages/backend/drizzle/schema/postgres/provider-rate-limits.ts new file mode 100644 index 00000000..64afc29e --- /dev/null +++ b/packages/backend/drizzle/schema/postgres/provider-rate-limits.ts @@ -0,0 +1,17 @@ +import { pgTable, text, bigint, primaryKey, index } from 'drizzle-orm/pg-core'; + +export const providerRateLimits = pgTable( + 'provider_rate_limits', + { + provider: text('provider').notNull(), + model: text('model').notNull(), + currentBudget: bigint('current_budget', { mode: 'number' }).notNull(), + lastRefillAt: bigint('last_refill_at', { mode: 'number' }).notNull(), + queueDepth: bigint('queue_depth', { mode: 'number' }).notNull().default(0), + createdAt: bigint('created_at', { mode: 'number' }).notNull(), + }, + (table) => ({ + pk: primaryKey({ columns: [table.provider, table.model] }), + lastRefillIdx: index('idx_rate_limits_last_refill').on(table.lastRefillAt), + }) +); diff --git a/packages/backend/drizzle/schema/sqlite/index.ts b/packages/backend/drizzle/schema/sqlite/index.ts index d80772ca..4ba4e8ac 100644 --- a/packages/backend/drizzle/schema/sqlite/index.ts +++ b/packages/backend/drizzle/schema/sqlite/index.ts @@ -8,3 +8,5 @@ export * from './quota-snapshots'; export * from './responses'; export * from './mcp'; export * from './quota-state'; + +export * from './provider-rate-limits'; \ No newline at end of file diff --git a/packages/backend/drizzle/schema/sqlite/provider-rate-limits.ts b/packages/backend/drizzle/schema/sqlite/provider-rate-limits.ts new file mode 100644 index 00000000..81892a68 --- /dev/null +++ b/packages/backend/drizzle/schema/sqlite/provider-rate-limits.ts @@ -0,0 +1,18 @@ +import { sqliteTable, integer, text, primaryKey, index } from 'drizzle-orm/sqlite-core'; +import { sql } from 'drizzle-orm'; + +export const providerRateLimits = sqliteTable( + 'provider_rate_limits', + { + provider: text('provider').notNull(), + model: text('model').notNull(), + currentBudget: integer('current_budget').notNull(), + lastRefillAt: integer('last_refill_at').notNull(), + queueDepth: integer('queue_depth').notNull().default(0), + createdAt: integer('created_at').notNull(), + }, + (table) => ({ + pk: primaryKey({ columns: [table.provider, table.model] }), + lastRefillIdx: index('idx_rate_limits_last_refill').on(table.lastRefillAt), + }) +);