Frank 3 месяцев назад
Родитель
Сommit
005e64e7d8

+ 9 - 0
infra/console.ts

@@ -293,3 +293,12 @@ new sst.cloudflare.x.SolidStart("Console", {
     },
   },
 })
+
+////////////////
+// HELPERS
+////////////////
+
+export const stat = new sst.cloudflare.Worker("Stat", {
+  handler: "packages/console/function/src/stat.ts",
+  link: [database],
+})

+ 1 - 0
packages/console/core/sst-env.d.ts

@@ -298,6 +298,7 @@ declare module "sst" {
     "EnterpriseStorage": cloudflare.R2Bucket
     "GatewayKv": cloudflare.KVNamespace
     "LogProcessor": cloudflare.Service
+    "Stat": cloudflare.Service
     "ZenData": cloudflare.R2Bucket
     "ZenDataNew": cloudflare.R2Bucket
   }

+ 39 - 0
packages/console/function/src/stat.ts

@@ -0,0 +1,39 @@
+import { WorkerEntrypoint } from "cloudflare:workers"
+import { and, Database, inArray } from "@opencode-ai/console-core/drizzle/index.js"
+import { ModelTpsRateLimitTable } from "@opencode-ai/console-core/schema/ip.sql.js"
+
+type Result = Record<string, { qualify: number; unqualify: number }>
+
+export default class Stat extends WorkerEntrypoint {
+  async fetch() {
+    return new Response("Not Found", { status: 404 })
+  }
+
+  async getStats(ids: string[]): Promise<Result> {
+    if (ids.length === 0) return {}
+
+    const toInterval = (date: Date) =>
+      parseInt(
+        date
+          .toISOString()
+          .replace(/[^0-9]/g, "")
+          .substring(0, 12),
+      )
+    const now = Date.now()
+    const intervals = Array.from({ length: 5 }, (_, i) => toInterval(new Date(now - i * 60 * 1000)))
+
+    const rows = await Database.use((tx) =>
+      tx
+        .select()
+        .from(ModelTpsRateLimitTable)
+        .where(and(inArray(ModelTpsRateLimitTable.id, ids), inArray(ModelTpsRateLimitTable.interval, intervals))),
+    )
+
+    const result: Result = Object.fromEntries(ids.map((id) => [id, { qualify: 0, unqualify: 0 }]))
+    for (const row of rows) {
+      result[row.id].qualify += row.qualify
+      result[row.id].unqualify += row.unqualify
+    }
+    return result
+  }
+}

+ 1 - 0
packages/console/function/sst-env.d.ts

@@ -298,6 +298,7 @@ declare module "sst" {
     "EnterpriseStorage": cloudflare.R2Bucket
     "GatewayKv": cloudflare.KVNamespace
     "LogProcessor": cloudflare.Service
+    "Stat": cloudflare.Service
     "ZenData": cloudflare.R2Bucket
     "ZenDataNew": cloudflare.R2Bucket
   }

+ 1 - 0
packages/console/resource/sst-env.d.ts

@@ -298,6 +298,7 @@ declare module "sst" {
     "EnterpriseStorage": cloudflare.R2Bucket
     "GatewayKv": cloudflare.KVNamespace
     "LogProcessor": cloudflare.Service
+    "Stat": cloudflare.Service
     "ZenData": cloudflare.R2Bucket
     "ZenDataNew": cloudflare.R2Bucket
   }

+ 1 - 0
packages/enterprise/sst-env.d.ts

@@ -298,6 +298,7 @@ declare module "sst" {
     "EnterpriseStorage": cloudflare.R2Bucket
     "GatewayKv": cloudflare.KVNamespace
     "LogProcessor": cloudflare.Service
+    "Stat": cloudflare.Service
     "ZenData": cloudflare.R2Bucket
     "ZenDataNew": cloudflare.R2Bucket
   }

+ 1 - 0
packages/function/sst-env.d.ts

@@ -298,6 +298,7 @@ declare module "sst" {
     "EnterpriseStorage": cloudflare.R2Bucket
     "GatewayKv": cloudflare.KVNamespace
     "LogProcessor": cloudflare.Service
+    "Stat": cloudflare.Service
     "ZenData": cloudflare.R2Bucket
     "ZenDataNew": cloudflare.R2Bucket
   }

+ 3 - 0
sst-env.d.ts

@@ -153,6 +153,9 @@ declare module "sst" {
       "type": "sst.sst.Linkable"
       "value": string
     }
+    "Stat": {
+      "type": "sst.cloudflare.Worker"
+    }
     "Teams": {
       "type": "sst.cloudflare.SolidStart"
       "url": string

+ 5 - 1
sst.config.ts

@@ -19,10 +19,14 @@ export default $config({
   },
   async run() {
     await import("./infra/app.js")
-    await import("./infra/console.js")
+    const { stat } = await import("./infra/console.js")
     await import("./infra/enterprise.js")
     if ($app.stage === "production" || $app.stage === "vimtor") {
       await import("./infra/monitoring.js")
     }
+
+    return {
+      STAT_WORKER_NAME: stat.nodes.worker.scriptName,
+    }
   },
 })