From b51060d9e7bfea0e729c839505920f36d3ffec3d Mon Sep 17 00:00:00 2001 From: Ajax Davis Date: Thu, 4 Dec 2025 16:16:30 +1000 Subject: [PATCH] feat: trigger health checks automatically when tools are synced MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add non-blocking health check calls to both sync endpoints: - /api/sync/changes: Triggers health checks after tool upsert from changes feed - /api/sync/keyword: Triggers health checks after tool upsert from keyword search Health checks run asynchronously with 'sync' trigger source, ensuring: - New/updated tools are validated immediately after sync - Sync operations don't wait for health check completion - Errors are logged but don't fail the sync This completes Phase 2 of the health check system implementation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- apps/web/src/app/api/sync/changes/route.ts | 15 +++++++++++---- apps/web/src/app/api/sync/keyword/route.ts | 15 +++++++++++---- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/apps/web/src/app/api/sync/changes/route.ts b/apps/web/src/app/api/sync/changes/route.ts index f5952bf..5c6ee50 100644 --- a/apps/web/src/app/api/sync/changes/route.ts +++ b/apps/web/src/app/api/sync/changes/route.ts @@ -3,6 +3,7 @@ import { fetchChanges, fetchLatestPackageWithMetadata } from '@tpmjs/npm-client' import { validateTpmjsField } from '@tpmjs/types/tpmjs'; import { type NextRequest, NextResponse } from 'next/server'; import { env } from '~/env'; +import { performHealthCheck } from '~/lib/health-check/health-check-service'; export const runtime = 'nodejs'; export const dynamic = 'force-dynamic'; @@ -131,7 +132,7 @@ export async function POST(request: NextRequest) { // Upsert each tool in the tools array for (const toolDef of validation.tools) { - await prisma.tool.upsert({ + const upsertedTool = await prisma.tool.upsert({ where: { packageId_exportName: { packageId: packageRecord.id, @@ -160,6 +161,14 @@ export async function POST(request: NextRequest) { aiAgent: toolDef.aiAgent ? (toolDef.aiAgent as any) : undefined, }, }); + + // Trigger immediate health check (non-blocking) + performHealthCheck(upsertedTool.id, 'sync').catch((err) => { + console.error( + `Health check failed for ${pkg.name}/${toolDef.exportName} (${upsertedTool.id}):`, + err + ); + }); } // Delete orphaned tools (tools removed from package.json) @@ -174,9 +183,7 @@ export async function POST(request: NextRequest) { id: { in: orphanedTools.map((t) => t.id) }, }, }); - console.log( - `Deleted ${orphanedTools.length} orphaned tools from package: ${pkg.name}` - ); + console.log(`Deleted ${orphanedTools.length} orphaned tools from package: ${pkg.name}`); } processed++; diff --git a/apps/web/src/app/api/sync/keyword/route.ts b/apps/web/src/app/api/sync/keyword/route.ts index 0305235..e276396 100644 --- a/apps/web/src/app/api/sync/keyword/route.ts +++ b/apps/web/src/app/api/sync/keyword/route.ts @@ -3,6 +3,7 @@ import { fetchLatestPackageWithMetadata, searchByKeyword } from '@tpmjs/npm-clie import { validateTpmjsField } from '@tpmjs/types/tpmjs'; import { type NextRequest, NextResponse } from 'next/server'; import { env } from '~/env'; +import { performHealthCheck } from '~/lib/health-check/health-check-service'; export const runtime = 'nodejs'; export const dynamic = 'force-dynamic'; @@ -145,7 +146,7 @@ export async function POST(request: NextRequest) { // Upsert each tool in the tools array for (const toolDef of validation.tools) { - await prisma.tool.upsert({ + const upsertedTool = await prisma.tool.upsert({ where: { packageId_exportName: { packageId: packageRecord.id, @@ -174,6 +175,14 @@ export async function POST(request: NextRequest) { aiAgent: toolDef.aiAgent ? (toolDef.aiAgent as any) : undefined, }, }); + + // Trigger immediate health check (non-blocking) + performHealthCheck(upsertedTool.id, 'sync').catch((err) => { + console.error( + `Health check failed for ${pkg.name}/${toolDef.exportName} (${upsertedTool.id}):`, + err + ); + }); } // Delete orphaned tools (tools removed from package.json) @@ -188,9 +197,7 @@ export async function POST(request: NextRequest) { id: { in: orphanedTools.map((t) => t.id) }, }, }); - console.log( - `Deleted ${orphanedTools.length} orphaned tools from package: ${pkg.name}` - ); + console.log(`Deleted ${orphanedTools.length} orphaned tools from package: ${pkg.name}`); } processed++;