This commit is contained in:
Pierre
2026-02-07 12:50:34 +01:00
parent bad6ddace2
commit 725d22c98f
4 changed files with 15 additions and 116 deletions
@@ -38,7 +38,6 @@ export class UnifiedAPIServer {
private getDuplicateResult: (() => DuplicateResult | null) | null = null; private getDuplicateResult: (() => DuplicateResult | null) | null = null;
private kvClient: IKVClient | null = null; private kvClient: IKVClient | null = null;
private kvManager: KVManager | null = null; private kvManager: KVManager | null = null;
private triggerScanCallback: (() => Promise<void>) | null = null;
private getQueueStatus: (() => any) | null = null; private getQueueStatus: (() => any) | null = null;
private fastQueueConcurrency: number | undefined = undefined; private fastQueueConcurrency: number | undefined = undefined;
private backgroundQueueConcurrency: number | undefined = undefined; private backgroundQueueConcurrency: number | undefined = undefined;
@@ -59,7 +58,6 @@ export class UnifiedAPIServer {
unifiedStateManager?: UnifiedProcessingStateManager, unifiedStateManager?: UnifiedProcessingStateManager,
getDuplicateResult?: () => DuplicateResult | null, getDuplicateResult?: () => DuplicateResult | null,
kvClient?: IKVClient, kvClient?: IKVClient,
triggerScanCallback?: () => Promise<void>,
backgroundQueueConcurrency?: number, backgroundQueueConcurrency?: number,
fastQueueConcurrency?: number, fastQueueConcurrency?: number,
getQueueStatus?: () => any, getQueueStatus?: () => any,
@@ -72,7 +70,6 @@ export class UnifiedAPIServer {
this.getDuplicateResult = getDuplicateResult || null; this.getDuplicateResult = getDuplicateResult || null;
this.kvClient = kvClient || null; this.kvClient = kvClient || null;
this.kvManager = kvManager || null; this.kvManager = kvManager || null;
this.triggerScanCallback = triggerScanCallback || null;
this.getQueueStatus = getQueueStatus || null; this.getQueueStatus = getQueueStatus || null;
this.backgroundQueueConcurrency = backgroundQueueConcurrency; this.backgroundQueueConcurrency = backgroundQueueConcurrency;
this.fastQueueConcurrency = fastQueueConcurrency; this.fastQueueConcurrency = fastQueueConcurrency;
@@ -724,12 +721,6 @@ export class UnifiedAPIServer {
// Add file back to discovered state for reprocessing // Add file back to discovered state for reprocessing
this.unifiedStateManager!.addDiscovered(filePath); this.unifiedStateManager!.addDiscovered(filePath);
// Trigger scan callback if available to pick up the file
if (this.triggerScanCallback) {
// Don't await - just trigger async
this.triggerScanCallback().catch(err => console.warn('[API] Scan trigger failed during retry:', getErrorMessage(err)));
}
return { status: 'ok', message: `File ${filePath} queued for retry` }; return { status: 'ok', message: `File ${filePath} queued for retry` };
} catch (error: any) { } catch (error: any) {
return reply.status(500).send({ error: error.message }); return reply.status(500).send({ error: error.message });
@@ -747,11 +738,6 @@ export class UnifiedAPIServer {
queued++; queued++;
} }
// Trigger scan callback if available
if (this.triggerScanCallback) {
this.triggerScanCallback().catch(err => console.warn('[API] Scan trigger failed during retry-all:', getErrorMessage(err)));
}
return { status: 'ok', message: `${queued} files queued for retry` }; return { status: 'ok', message: `${queued} files queued for retry` };
}); });
@@ -883,40 +869,12 @@ export class UnifiedAPIServer {
} }
/** /**
* Setup Scan Trigger API routes * Setup Metadata Clear API routes
* NOTE: /api/scan/trigger has been removed - use meta-core's endpoint instead
*/ */
private setupScanRoutes(): void { private setupScanRoutes(): void {
// Trigger manual scan // Clear all metadata
this.app.post('/api/scan/trigger', async (request, reply) => { // NOTE: To trigger a rescan after clearing, call meta-core's /api/scan/trigger endpoint
if (!this.triggerScanCallback) {
return reply.status(503).send({
status: 'error',
message: 'Scan trigger not available'
});
}
try {
console.log('Manual scan triggered via API');
// Don't await - trigger and return immediately
this.triggerScanCallback().catch(error => {
console.error('Error during triggered scan:', error);
});
return {
status: 'ok',
message: 'Scan triggered successfully'
};
} catch (error: any) {
console.error('Error triggering scan:', error);
return reply.status(500).send({
status: 'error',
message: 'Failed to trigger scan',
details: error.message
});
}
});
// Clear all metadata and trigger rescan
this.app.post('/api/metadata/clear', async (request, reply) => { this.app.post('/api/metadata/clear', async (request, reply) => {
if (!this.kvClient) { if (!this.kvClient) {
return reply.status(503).send({ return reply.status(503).send({
@@ -950,19 +908,10 @@ export class UnifiedAPIServer {
console.log(`Cleared ${deletedCount} file metadata entries`); console.log(`Cleared ${deletedCount} file metadata entries`);
// Trigger rescan if callback is available
if (this.triggerScanCallback) {
console.log('Triggering rescan after metadata clear');
this.triggerScanCallback().catch(error => {
console.error('Error during post-clear rescan:', error);
});
}
return { return {
status: 'ok', status: 'ok',
message: `Cleared ${deletedCount} files`, message: `Cleared ${deletedCount} files. To rescan, call meta-core's /api/scan/trigger endpoint.`,
deletedCount, deletedCount
rescanTriggered: !!this.triggerScanCallback
}; };
} catch (error: any) { } catch (error: any) {
console.error('Error clearing metadata:', error); console.error('Error clearing metadata:', error);
@@ -1964,7 +1913,6 @@ export class UnifiedAPIServer {
if (this.unifiedStateManager) { if (this.unifiedStateManager) {
console.log(` - Unified Processing API (4 states): http://${this.config.host}:${this.config.port}/api/processing/status`); console.log(` - Unified Processing API (4 states): http://${this.config.host}:${this.config.port}/api/processing/status`);
} }
console.log(` - Scan API: http://${this.config.host}:${this.config.port}/api/scan/trigger (POST)`);
} catch (error) { } catch (error) {
console.error('Error starting Unified API Server:', error); console.error('Error starting Unified API Server:', error);
throw error; throw error;
+2 -15
View File
@@ -270,7 +270,6 @@ describe('UnifiedAPIServer', function() {
mockStateManager as any, mockStateManager as any,
() => duplicateResult, () => duplicateResult,
mockKV as any, mockKV as any,
async () => { /* scan trigger */ },
4, // backgroundQueueConcurrency 4, // backgroundQueueConcurrency
16, // fastQueueConcurrency 16, // fastQueueConcurrency
() => ({ fast: { pending: 0, running: 0 }, background: { pending: 0, running: 0 } }) () => ({ fast: { pending: 0, running: 0 }, background: { pending: 0, running: 0 } })
@@ -463,20 +462,8 @@ describe('UnifiedAPIServer', function() {
}); });
}); });
// ========================================================================= // NOTE: /api/scan/trigger has been removed from meta-sort (Architecture V3)
// Scan API // Scan is now handled by meta-core. Tests for scan trigger are in core.bats.
// =========================================================================
describe('Scan API (/api/scan)', function() {
it('POST /api/scan/trigger triggers a scan', async function() {
const response = await app.inject({
method: 'POST',
url: '/api/scan/trigger'
});
expect([200, 202, 204]).to.include(response.statusCode);
});
});
// ========================================================================= // =========================================================================
// FUSE API (Virtual Filesystem) // FUSE API (Virtual Filesystem)
@@ -98,24 +98,8 @@ export class EventSubscriber {
console.log('[EventSubscriber] Stopped'); console.log('[EventSubscriber] Stopped');
} }
/** // NOTE: triggerScan() has been removed - meta-core handles scanning automatically
* Trigger a manual scan on meta-core // To trigger a scan manually, call meta-core's /api/scan/trigger endpoint directly
*/
async triggerScan(): Promise<void> {
try {
const response = await fetch(`${this.options.metaCoreUrl}/api/scan/trigger`, {
method: 'POST'
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
console.log('[EventSubscriber] Scan triggered on meta-core');
} catch (error) {
console.error('[EventSubscriber] Failed to trigger scan:', error);
}
}
/** /**
* Get watcher status from meta-core * Get watcher status from meta-core
@@ -171,13 +155,7 @@ export class EventSubscriber {
this.eventSource.onopen = () => { this.eventSource.onopen = () => {
console.log('[EventSubscriber] Connected to meta-core SSE'); console.log('[EventSubscriber] Connected to meta-core SSE');
this.reconnectAttempts = 0; this.reconnectAttempts = 0;
// NOTE: Initial scan is handled automatically by meta-core (Architecture V3)
// Request initial scan if configured
if (this.options.requestInitialScan) {
this.triggerScan().catch(err => {
console.error('[EventSubscriber] Failed to trigger initial scan:', err);
});
}
}; };
this.eventSource.onerror = (error) => { this.eventSource.onerror = (error) => {
+4 -18
View File
@@ -79,22 +79,8 @@ const getDuplicateResult = () => fileProcessor.getDuplicateResult();
// API Server will be initialized after KV is ready (deferred to async init) // API Server will be initialized after KV is ready (deferred to async init)
let apiServer: UnifiedAPIServer | null = null; let apiServer: UnifiedAPIServer | null = null;
// Manual scan trigger (called from API) - delegates to meta-core via EventSubscriber // NOTE: Scan trigger has been moved to meta-core (Architecture V3)
const triggerScan = async () => { // Use meta-core's /api/scan/trigger endpoint directly
console.log('[Scan] Triggering manual scan...');
// Reset pipeline counters and state before fresh scan
// Also publishes reset event to meta-fuse
await pipeline.reset();
// Trigger scan on meta-core (which will send events back via SSE)
if (eventSubscriber) {
await eventSubscriber.triggerScan();
console.log('[Scan] Scan triggered on meta-core');
} else {
console.warn('[Scan] EventSubscriber not available, cannot trigger scan');
}
};
// Global error handlers - prevent crashes from unforeseen errors // Global error handlers - prevent crashes from unforeseen errors
process.on('uncaughtException', (error: Error) => { process.on('uncaughtException', (error: Error) => {
@@ -178,7 +164,7 @@ process.on('SIGINT', async () => {
port: config.FUSE_API_PORT, port: config.FUSE_API_PORT,
host: config.FUSE_API_HOST, host: config.FUSE_API_HOST,
enableCors: true, enableCors: true,
}, unifiedStateManager, getDuplicateResult, kvClient || undefined, triggerScan, backgroundQueueConcurrency, fastQueueConcurrency, () => fileProcessor.getQueueStatus(), kvManager || undefined, getPluginManagerInstance, () => fileProcessor.getTaskScheduler()); }, unifiedStateManager, getDuplicateResult, kvClient || undefined, backgroundQueueConcurrency, fastQueueConcurrency, () => fileProcessor.getQueueStatus(), kvManager || undefined, getPluginManagerInstance, () => fileProcessor.getTaskScheduler());
await apiServer.start(); await apiServer.start();
console.log('Unified API Server started successfully'); console.log('Unified API Server started successfully');
@@ -269,7 +255,7 @@ process.on('SIGINT', async () => {
console.error('[Startup] Make sure meta-core is running and kv-leader.info exists.'); console.error('[Startup] Make sure meta-core is running and kv-leader.info exists.');
process.exit(1); process.exit(1);
} }
const metaCoreUrl = leaderInfo.baseUrl; const metaCoreUrl = leaderInfo.apiUrl;
console.log(`[Startup] Connecting to meta-core at ${metaCoreUrl}...`); console.log(`[Startup] Connecting to meta-core at ${metaCoreUrl}...`);
eventSubscriber = new EventSubscriber({ eventSubscriber = new EventSubscriber({
metaCoreUrl: metaCoreUrl, metaCoreUrl: metaCoreUrl,