ObsiViewer/apply-phase3-patch.mjs

149 lines
4.9 KiB
JavaScript

#!/usr/bin/env node
/**
* Phase 3 Patch Application Script
* Applies final modifications to server/index.mjs
*/
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const indexFile = path.join(__dirname, 'server', 'index.mjs');
const backupFile = `${indexFile}.backup.${Date.now()}`;
console.log('\n🚀 Phase 3 Patch Application');
console.log('================================\n');
try {
// Step 1: Create backup
console.log('📦 Creating backup...');
fs.copyFileSync(indexFile, backupFile);
console.log(`✅ Backup created: ${backupFile}\n`);
// Step 2: Read the file
console.log('📖 Reading index.mjs...');
let content = fs.readFileSync(indexFile, 'utf-8');
console.log('✅ File read successfully\n');
// Step 3: Add performance endpoint setup
console.log('🔧 Adding performance endpoint setup...');
const performanceEndpointSetup = `// Phase 3: Setup performance monitoring endpoint
setupPerformanceEndpoint(app, performanceMonitor, metadataCache, meilisearchCircuitBreaker);
`;
// Insert before "// Créer le répertoire de la voûte"
content = content.replace(
'// Créer le répertoire de la voûte s\'il n\'existe pas',
performanceEndpointSetup + '// Créer le répertoire de la voûte s\'il n\'existe pas'
);
console.log('✅ Performance endpoint setup added\n');
// Step 4: Update app.listen() for deferred indexing
console.log('🔧 Updating app.listen() for deferred indexing...');
const oldListen = `app.listen(PORT, '0.0.0.0', () => {
console.log(\`ObsiViewer server running on http://0.0.0.0:\${PORT}\`);
console.log(\`Vault directory: \${vaultDir}\`);
});`;
const newListen = `// Phase 3: Deferred Meilisearch indexing (non-blocking)
let indexingState = { inProgress: false, completed: false };
const scheduleIndexing = async () => {
if (indexingState.inProgress) return;
indexingState.inProgress = true;
setImmediate(async () => {
try {
console.time('[Meilisearch] Background indexing');
await fullReindex(vaultDir);
console.timeEnd('[Meilisearch] Background indexing');
indexingState.completed = true;
console.log('[Meilisearch] ✅ Background indexing completed');
} catch (error) {
console.error('[Meilisearch] ❌ Background indexing failed:', error.message);
indexingState.completed = false;
// Retry after 5 minutes
setTimeout(() => {
indexingState.inProgress = false;
scheduleIndexing();
}, 5 * 60 * 1000);
}
});
};
const server = app.listen(PORT, '0.0.0.0', () => {
console.log(\`🚀 ObsiViewer server running on http://0.0.0.0:\${PORT}\`);
console.log(\`📁 Vault directory: \${vaultDir}\`);
console.log(\`📊 Performance monitoring: http://0.0.0.0:\${PORT}/__perf\`);
// Schedule background indexing (non-blocking)
scheduleIndexing();
console.log('✅ Server ready - Meilisearch indexing in background');
});
// Graceful shutdown
process.on('SIGINT', () => {
console.log('\\n🛑 Shutting down server...');
server.close(() => {
console.log('✅ Server shutdown complete');
process.exit(0);
});
});`;
content = content.replace(oldListen, newListen);
console.log('✅ app.listen() updated with deferred indexing\n');
// Step 5: Write the modified content
console.log('💾 Writing modified index.mjs...');
fs.writeFileSync(indexFile, content, 'utf-8');
console.log('✅ File written successfully\n');
// Step 6: Verify changes
console.log('🔍 Verifying changes...');
const verifyContent = fs.readFileSync(indexFile, 'utf-8');
const checks = [
{ name: 'Performance endpoint setup', pattern: 'setupPerformanceEndpoint' },
{ name: 'Deferred indexing', pattern: 'scheduleIndexing' },
{ name: 'Graceful shutdown', pattern: "process.on('SIGINT'" },
{ name: 'Performance monitoring URL', pattern: '__perf' }
];
let allPassed = true;
for (const check of checks) {
if (verifyContent.includes(check.pattern)) {
console.log(`${check.name}`);
} else {
console.log(`${check.name}`);
allPassed = false;
}
}
console.log('');
if (allPassed) {
console.log('✅ All verification checks passed!\n');
} else {
console.log('⚠️ Some verification checks failed\n');
}
console.log('================================');
console.log('✅ Phase 3 patch applied successfully!\n');
console.log('Next steps:');
console.log('1. Test the server: npm run start');
console.log('2. Check performance: curl http://localhost:3000/__perf');
console.log('3. Monitor cache hits in the logs');
console.log('4. Verify Meilisearch indexing in background\n');
} catch (error) {
console.error('❌ Error applying patch:', error.message);
console.error('\nRolling back...');
if (fs.existsSync(backupFile)) {
fs.copyFileSync(backupFile, indexFile);
console.log('✅ Rollback complete');
}
process.exit(1);
}