Database Convex

Come CodeCourier usa Convex come database reattivo in tempo reale per tutto lo stato dell’applicazione, inclusi la progettazione dello schema, le query, le mutation e le sottoscrizioni in tempo reale.

8 min letto
convexdatabasereactive

Convex è la piattaforma backend reattiva che funge da archivio dati centrale e livello di coordinamento per CodeCourier. Ogni elemento dello stato dell’applicazione -- utenti, progetti, sandbox, workflow, run, messaggi, learning, registri di utilizzo e altro -- risiede in Convex. Ciò che rende Convex unico rispetto ai database tradizionali è la sua reattività integrata: quando i dati cambiano, ogni client sottoscritto viene notificato automaticamente e si ri-renderizza con lo stato più recente. Questa pagina spiega come CodeCourier usa Convex, la progettazione dello schema e i pattern di codice per lavorare con il database.

Cosa offre Convex

  • Sottoscrizioni in tempo reale -- Le query si rieseguono automaticamente quando i loro dati sottostanti cambiano. La dashboard mostra lo stato delle sandbox, l’avanzamento dei run e i messaggi in tempo reale senza polling.
  • Mutation transazionali -- Ogni mutation viene eseguita in una transazione serializzabile. Le letture e le scritture all’interno di una mutation sono atomiche, evitando le race condition.
  • Funzioni type-safe -- Le query, le mutation e le action sono definite in TypeScript con inferenza dei tipi completa. Lo schema Convex convalida gli argomenti e i tipi di ritorno a runtime.
  • Action per gli effetti collaterali -- Le operazioni che chiamano servizi esterni (E2B, Trigger.dev) sono definite come action, che possono leggere dati e pianificare mutation ma non sono esse stesse transazionali.
  • Autenticazione integrata -- Convex convalida i JWT di Clerk e rende l’identità dell’utente autenticato disponibile a ogni funzione.
  • Funzioni pianificate -- L’API ctx.scheduler.runAfter abilita l’esecuzione differita, usata per operazioni asincrone come l’invio dell’estrazione dei learning.
  • Archiviazione di file -- Convex fornisce un’archiviazione di file integrata (la tabella _storage) usata per le immagini di riferimento e i logo dei progetti.

Panoramica dello schema

Lo schema Convex è definito in convex/schema.ts e contiene oltre venti tabelle. Ecco i principali gruppi di entità:

Identità e accesso

  • users -- Account utente sincronizzati da Clerk. Indicizzati per clerkId ed email.
  • projects -- Unità organizzative di livello superiore. Indicizzate per ownerId e slug.
  • projectMembers -- Relazione molti-a-molti tra utenti e progetti con ruoli (owner, admin, member) e stato dell’invito.
  • projectSettings -- Configurazione per progetto inclusi i prompt di sistema, CLAUDE.md, le variabili d’ambiente, le skill e i comandi selezionati e le chiavi di deploy.
  • userSettings -- Preferenze per utente come l’ultimo progetto attivo.

Chiavi API

  • apiKeys -- Chiavi API di provider a livello utente (E2B, Anthropic, OpenRouter, OpenAI, GitHub). Archiviazione criptata con visualizzazione degli ultimi quattro caratteri.
  • projectProviderKeys -- Chiavi API di provider a livello progetto che sovrascrivono le chiavi a livello utente.
  • projectApiKeys -- Chiavi API REST di CodeCourier per l’accesso programmatico. Con hash SHA-256, revocabili, con monitoraggio dell’utilizzo.

Esecuzione

  • sandboxes -- Istanze di sandbox E2B con stato, configurazione e tracciamento del ciclo di vita.
  • sandboxMessages -- Messaggi di conversazione tra utenti e agenti IA all’interno delle sandbox.
  • workflows -- Blueprint di workflow che definiscono il tipo di pipeline, i passaggi e la configurazione predefinita.
  • runs -- Istanze di esecuzione di workflow con stato, avanzamento e tracciamento della PR.
  • runSteps -- Singoli passaggi di esecuzione all’interno dei run (designer, checker, optimizer, ecc.).
  • workChains -- Catene di esecuzione sequenziale delle issue.

Conoscenza IA

  • personas -- Personalità di agente IA con istruzioni personalizzate, skill e preferenze di modello.
  • skills / skillFiles -- Definizioni di skill e i loro contenuti di file.
  • commands -- Definizioni di comandi riutilizzabili.
  • scripts -- Definizioni di script per l’esecuzione nelle sandbox.
  • learnings -- Conoscenza estratta dalle sessioni di sandbox.
  • learningVersions -- Snapshot di learning compilati per l’iniezione nelle sessioni future.

Issue

  • issueSessions -- Record delle sessioni di issue discovery.
  • issues -- Singole issue scoperte durante le sessioni o create manualmente.

Analytics e utilizzo

  • usageCostRates -- Tariffe di costo per diversi servizi (Claude Code, E2B, Trigger.dev, Convex, ecc.) con tipi di tariffa e livelli di modello configurabili.
  • usageRecords -- Dati di utilizzo dettagliati per progetto, servizio e data, con campi di tracciamento enterprise opzionali per i conteggi dei token, gli ID dei modelli e l’attribuzione dei passaggi.
  • projectCounters -- Contatori denormalizzati per l’accesso rapido ai numeri di sandbox, run, workflow e membri.
  • dailyStats -- Statistiche giornaliere aggregate dell’attività del progetto.
  • notifications -- Record delle notifiche utente per i completamenti dei run, gli eventi di PR e l’attività del team.

Query in tempo reale

La dashboard di CodeCourier sfrutta ampiamente le sottoscrizioni di query in tempo reale di Convex. Quando visualizzi una conversazione di sandbox, la query sandboxMessages.listBySandbox si sottoscrive a tutti i messaggi di quella sandbox. Quando arriva un nuovo messaggio dall’agente IA (scritto da un task Trigger.dev tramite l’endpoint di callback), la query si riesegue automaticamente e la UI si aggiorna istantaneamente -- niente polling, niente configurazione WebSocket, niente invalidazione manuale.

Query chiave usate nella dashboard:

  • sandboxes.listPaginated -- Alimenta la vista elenco delle sandbox con paginazione basata su cursore.
  • runs.listPaginated -- Alimenta la vista elenco dei run.
  • workflows.listForProject -- Carica tutti i workflow del progetto corrente.
  • sandboxMessages.listBySandbox -- Trasmette la conversazione in tempo reale.
  • runSteps.listByRun -- Mostra l’avanzamento passo per passo durante l’esecuzione del workflow.
  • usage.getProjectUsageSummary -- Dati della dashboard di utilizzo in tempo reale.

Mutation

Le mutation in Convex sono scritture transazionali. CodeCourier usa le mutation per tutti i cambiamenti di stato avviati dall’utente:

  • Creazione, aggiornamento ed eliminazione di workflow
  • Rinominare sandbox e run
  • Gestione dei membri e degli inviti del progetto
  • Generazione e revoca delle chiavi API
  • Aggiornamento delle impostazioni del progetto
  • Registrazione dell’utilizzo e upsert delle tariffe di costo

Le mutation interne (con prefisso internal) sono usate dai callback Trigger.dev e dalle funzioni pianificate. Non sono accessibili dal frontend.

Indici

Lo schema definisce indici estesi per interrogazioni efficienti. Ogni tabella ha almeno un indice oltre all’indice predefinito _id. I pattern di indice chiave includono:

  • by_user / by_project -- Filtrare i record per proprietà.
  • by_deleted -- Filtrare in modo efficiente i record eliminati in soft delete.
  • by_status -- Filtrare per stato del ciclo di vita.
  • by_project_date -- Query di serie temporali per l’analytics.
  • by_key -- Ricerca della chiave API per hash.

Lavorare con Convex in CodeCourier

Query frontend

La dashboard usa il hook useQuery del client React di Convex:

const sandboxes = useQuery(api.sandboxes.listPaginated, {
  paginationOpts: { numItems: 20 }
});

Le query restituiscono undefined durante il caricamento e si aggiornano automaticamente quando i dati sottostanti cambiano.

Mutation frontend

Le mutation vengono chiamate tramite il hook useMutation:

const rename = useMutation(api.sandboxes.renameSandbox);
await rename({ id: sandboxId, name: "New Name" });

Action frontend

Le action che attivano operazioni esterne usano useAction:

const launch = useAction(api.sandboxActions.launchSandboxes);
await launch({ config, prompt, projectId });