Files
template-app/convex/usage.ts
T

48 lines
1.4 KiB
TypeScript

// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
// External usage delivery runs as an action, never from a Convex mutation. The stable SDK
// idempotency key makes scheduler retries safe if the ingest accepted a request but its response
// was lost.
"use node"
import { UsageClient } from "@conusai-sdk/usage"
import { makeFunctionReference } from "convex/server"
import { v } from "convex/values"
import { internalAction } from "./_generated/server"
const requiredEnv = (name: string): string => {
const value = process.env[name]?.trim()
if (!value) throw new Error(`Convex deployment is missing ${name}`)
return value
}
export const deliver = internalAction({
args: {
attempt: v.number(),
event: v.any(),
orgSlug: v.string(),
},
handler: async (ctx, { attempt, event, orgSlug }) => {
const usage = new UsageClient({
baseUrl: requiredEnv("CONUSAI_API_URL"),
apiPrefix: "",
apiKey: requiredEnv("CONUSAI_API_TOKEN"),
orgSlug,
maxRetries: 0,
flushIntervalMs: 0,
})
usage.track(event)
try {
await usage.flush()
} catch (error) {
if (attempt >= 7) throw error
const delayMs = Math.min(300_000, 1_000 * 2 ** attempt)
await ctx.scheduler.runAfter(delayMs, makeFunctionReference<"action">("usage:deliver"), {
attempt: attempt + 1,
event,
orgSlug,
})
}
},
})