// 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, }) } }, })