Skip to content

Commit c1d6e9f

Browse files
authored
Merge pull request #64 from rh-aiservices-bu/orphaned-key-fix
fix(test): handle orphaned keys and improve server startup
2 parents eeedd97 + 499d111 commit c1d6e9f

File tree

3 files changed

+56
-35
lines changed

3 files changed

+56
-35
lines changed

backend/src/lib/database-migrations.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,7 @@ export const backfillLiteLLMKeyAlias = async (dbUtils: DatabaseUtils, liteLLMSer
656656
console.log(`🔄 Backfilling litellm_key_alias for ${keysToBackfill.length} API keys...`);
657657

658658
let successCount = 0;
659+
let orphanedCount = 0;
659660
let errorCount = 0;
660661

661662
for (const key of keysToBackfill) {
@@ -671,15 +672,26 @@ export const backfillLiteLLMKeyAlias = async (dbUtils: DatabaseUtils, liteLLMSer
671672

672673
successCount++;
673674
} catch (error) {
674-
console.error(
675-
`Failed to backfill key_alias for API key ${key.id}:`,
676-
error instanceof Error ? error.message : error,
677-
);
678-
errorCount++;
675+
// Handle 404s (orphaned keys) differently - mark without verbose logging
676+
if (error instanceof Error && error.message?.includes('404')) {
677+
await dbUtils.query(`UPDATE api_keys SET litellm_key_alias = $1 WHERE id = $2`, [
678+
`orphaned_${key.id}`,
679+
key.id,
680+
]);
681+
orphanedCount++;
682+
} else {
683+
console.error(
684+
`Failed to backfill key_alias for API key ${key.id}:`,
685+
error instanceof Error ? error.message : error,
686+
);
687+
errorCount++;
688+
}
679689
}
680690
}
681691

682-
console.log(`✅ Backfilled litellm_key_alias: ${successCount} succeeded, ${errorCount} failed`);
692+
console.log(
693+
`✅ Backfilled litellm_key_alias: ${successCount} succeeded, ${orphanedCount} orphaned, ${errorCount} failed`,
694+
);
683695
} catch (error) {
684696
console.error('❌ Failed to backfill litellm_key_alias:', error);
685697
// Don't throw - this is a best-effort migration

backend/src/plugins/database.ts

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -36,38 +36,42 @@ const databasePlugin: FastifyPluginAsync = async (fastify) => {
3636
// Don't fail the startup, but log the error
3737
}
3838

39-
// Backfill litellm_key_alias for existing API keys
40-
try {
41-
const { backfillLiteLLMKeyAlias } = await import('../lib/database-migrations');
42-
const { LiteLLMService } = await import('../services/litellm.service');
43-
const liteLLMService = new LiteLLMService(fastify);
44-
await backfillLiteLLMKeyAlias(fastify.dbUtils, liteLLMService);
45-
} catch (backfillError) {
46-
fastify.log.error(backfillError as Error, 'Failed to backfill litellm_key_alias');
47-
// Don't fail the startup, but log the error
48-
}
49-
50-
// Skip initial model sync in test environment
51-
// Tests can explicitly sync models if needed for their scenarios
52-
if (process.env.NODE_ENV !== 'test') {
53-
// Sync models on startup
39+
// Start LiteLLM-dependent operations in background - don't block server startup
40+
setImmediate(async () => {
41+
// Background task 1: Backfill litellm_key_alias for existing API keys
5442
try {
55-
const { ModelSyncService } = await import('../services/model-sync.service');
56-
const modelSyncService = new ModelSyncService(fastify);
57-
const syncResult = await modelSyncService.syncModels({
58-
forceUpdate: false,
59-
markUnavailable: true,
60-
});
43+
fastify.log.info('Starting background backfill of litellm_key_alias');
44+
const { backfillLiteLLMKeyAlias } = await import('../lib/database-migrations');
45+
const { LiteLLMService } = await import('../services/litellm.service');
46+
const liteLLMService = new LiteLLMService(fastify);
47+
await backfillLiteLLMKeyAlias(fastify.dbUtils, liteLLMService);
48+
fastify.log.info('Background backfill completed successfully');
49+
} catch (backfillError) {
50+
fastify.log.error(backfillError as Error, 'Background backfill failed');
51+
}
52+
53+
// Background task 2: Sync models from LiteLLM
54+
// Skip in test environment
55+
if (process.env.NODE_ENV !== 'test') {
56+
try {
57+
fastify.log.info('Starting background model sync from LiteLLM');
58+
const { ModelSyncService } = await import('../services/model-sync.service');
59+
const modelSyncService = new ModelSyncService(fastify);
60+
const syncResult = await modelSyncService.syncModels({
61+
forceUpdate: false,
62+
markUnavailable: true,
63+
});
6164

62-
fastify.log.info({
63-
msg: 'Initial model sync completed',
64-
...syncResult,
65-
});
66-
} catch (syncError) {
67-
fastify.log.error({ error: syncError }, 'Failed to sync models on startup');
68-
// Don't fail startup - continue with cached models
65+
fastify.log.info({
66+
msg: 'Background model sync completed',
67+
...syncResult,
68+
});
69+
} catch (syncError) {
70+
fastify.log.error({ error: syncError }, 'Background model sync failed');
71+
// Continue - services will use cached models if available
72+
}
6973
}
70-
}
74+
});
7175

7276
// Initialize LiteLLM integration service for auto-sync
7377
const litellmIntegrationService = new LiteLLMIntegrationService(fastify);

frontend/src/test/mocks/handlers.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,11 @@ export const handlers = [
358358
});
359359
}),
360360

361+
// Banner endpoint (used by BannerProvider in Layout)
362+
http.get('/api/v1/banners', () => {
363+
return HttpResponse.json([]);
364+
}),
365+
361366
// Error simulation endpoints
362367
http.get('/api/v1/test-error', () => {
363368
return HttpResponse.json(

0 commit comments

Comments
 (0)