// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0 // The stores of the mariadb and mongodb profiles (spec ยง5.1; profiles//README.md), built once // per web process beside the Postgres pair app.ts builds. One login, no row-level security to bind // (AT-D20 is Postgres-only): the repository predicate is the tenant wall, which the adapters' shared // contract suites prove. The queue is BullMQ on the linked Valkey, and a request only enqueues. // // `kit template:prune --profile` keeps this folder for mariadb and mongodb (and the chosen engine's // folder); postgres and convex remove it with every `kit:profile-dialect` line. import type { AppEnv } from "@app/config" import type { AnyEntityDef, JobQueue } from "@conusai-kit/data" import { createBullmqJobQueue } from "@conusai-kit/jobs-bullmq" import { Redis } from "ioredis" import type { EngineStore } from "../stores" import { mariadbStore } from "./mariadb/index" // kit:profile-mariadb import { mongodbStore } from "./mongodb/index" // kit:profile-mongodb export interface DialectStores extends EngineStore { /** The queue a request enqueues on; it connects on the first enqueue. */ queue(): JobQueue close(): Promise } /** * The BullMQ key prefix of this app: `kit-jobs-`, from the project the platform injects, so * two apps sharing one Valkey service never meet (the worker's `queueSlug` is the same function). */ export function queueSlug(env: Pick): string { const id = env.deployment.CONUSAI_PROJECT_ID.toLowerCase().replace(/[^a-z0-9-]+/g, "-") return `p-${id}`.replace(/-+$/, "") } type Collections = ReadonlyArray<{ readonly entity: string; readonly table: string }> function engineStore(env: AppEnv, entities: readonly AnyEntityDef[], collections: Collections): EngineStore | null { if (env.mariadb) return mariadbStore(env.mariadb.url, entities) // kit:profile-mariadb if (env.mongodb) return mongodbStore(env.mongodb.url, entities, collections) // kit:profile-mongodb return null } /** The stores of the mariadb or mongodb profile, or null on any other. */ export function dialectStores( env: AppEnv, entities: readonly AnyEntityDef[], collections: Collections = [], ): DialectStores | null { const store = engineStore(env, entities, collections) if (!store) return null const redisUrl = env.redis?.url if (!redisUrl) throw new Error("the mariadb and mongodb profiles need REDIS_URL for their job queue") let connection: Redis | undefined let queue: ReturnType | undefined return { ...store, queue: () => { // BullMQ needs `maxRetriesPerRequest: null` on the connection it is given. connection ??= new Redis(redisUrl, { maxRetriesPerRequest: null }) queue ??= createBullmqJobQueue({ connection, slug: queueSlug(env) }) return queue }, close: async () => { await queue?.close().catch(() => undefined) await connection?.quit().catch(() => undefined) await store.data.close() }, } }