From 0b48fe1baabc36e9fc67665c969d6bf03f493e15 Mon Sep 17 00:00:00 2001 From: Railway Agent Date: Sat, 4 Jul 2026 13:58:23 +0000 Subject: [PATCH] Fix missing ritualchain.source.ts file ## Fix: Add missing ritualchain.source.ts file The build was failing because `apps/web/src/lib/server/domains/feedback/sources/ritualchain.source.ts` was missing, causing an unresolved import error during the SSR build phase. ### Error ``` [UNRESOLVED_IMPORT] Error: Could not resolve './domains/feedback/sources/ritualchain.source' in src/lib/server/startup.ts ``` ### Changes - Added `apps/web/src/lib/server/domains/feedback/sources/ritualchain.source.ts` with the correct implementation for ensuring the RitualChain feedback source exists on startup ### Why The startup code imports `ensureRitualChainFeedbackSource` from this file, but it was missing. This caused the build to fail during the SSR environment build phase. The implementation ensures a RitualChain feedback source exists in the database on startup using an advisory lock to prevent concurrent creation. --- .../feedback/sources/ritualchain.source.ts | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 apps/web/src/lib/server/domains/feedback/sources/ritualchain.source.ts diff --git a/apps/web/src/lib/server/domains/feedback/sources/ritualchain.source.ts b/apps/web/src/lib/server/domains/feedback/sources/ritualchain.source.ts new file mode 100644 index 000000000..53da5cd73 --- /dev/null +++ b/apps/web/src/lib/server/domains/feedback/sources/ritualchain.source.ts @@ -0,0 +1,51 @@ +/** + * RitualChain feedback source — auto-provisioned passive connector. + * + * One ritualchain source exists per deployment. Created on startup if absent. + * All new posts (including widget-submitted) are ingested automatically + * via the feedback_pipeline event hook on post.created. + */ + +import { db, eq, feedbackSources } from '@/lib/server/db' +import { sql } from 'drizzle-orm' +import { hashCode } from '@/lib/server/utils' +import { logger } from '@/lib/server/logger' + +const log = logger.child({ component: 'ritualchain-source' }) + +/** + * Ensure the ritualchain feedback source exists. + * Uses an advisory lock to prevent duplicate sources from concurrent startups. + */ +export async function ensureRitualChainFeedbackSource(): Promise { + await db.transaction(async (tx) => { + // Advisory lock scoped to this transaction prevents concurrent creation + await tx.execute( + sql`SELECT pg_advisory_xact_lock(${sql.raw(String(hashCode('ritualchain_feedback_source')))})` + ) + + const existing = await tx.query.feedbackSources.findFirst({ + where: eq(feedbackSources.sourceType, 'ritualchain'), + columns: { id: true }, + }) + + if (existing) { + log.debug({ source_id: existing.id }, 'ritualchain feedback source already exists') + return + } + + const [created] = await tx + .insert(feedbackSources) + .values({ + sourceType: 'ritualchain', + deliveryMode: 'passive', + name: 'RitualChain', + enabled: true, + config: {}, + }) + .returning({ id: feedbackSources.id }) + + log.info({ source_id: created.id }, 'created ritualchain feedback source') + }) +} +