RAG: ночная пакетная индексация эмбеддингов, очередь embedding_queue, MCP get_organization_context, снижение OLLAMA_KEEP_ALIVE

This commit is contained in:
2026-07-08 15:57:25 +03:00
parent 1e9131753d
commit 70dfe07fa6
11 changed files with 440 additions and 83 deletions

View File

@@ -1117,6 +1117,60 @@ async function runStartupDataPatches() {
}, 30_000);
log('Billing worker started (24h interval)');
// Embedding queue worker — process deferred RAG embeddings nightly at 23:00 MSK
function getMsUntilMskHour(targetHour: number): number {
const now = new Date();
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'Europe/Moscow',
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
hour12: false,
});
const parts = formatter.formatToParts(now);
const getPart = (type: string) => parseInt(parts.find(p => p.type === type)?.value ?? '0', 10);
const year = getPart('year');
const month = getPart('month') - 1;
const day = getPart('day');
const hour = getPart('hour');
const minute = getPart('minute');
const second = getPart('second');
const mskNow = new Date(year, month, day, hour, minute, second).getTime();
let mskTarget = new Date(year, month, day, targetHour, 0, 0).getTime();
if (mskTarget <= mskNow) {
mskTarget += 24 * 60 * 60 * 1000;
}
return mskTarget - mskNow;
}
async function runEmbeddingQueueWorker() {
try {
const { processEmbeddingQueue } = await import('./services/embedding.service');
const pending = await storage.getPendingEmbeddingQueue(10_000);
if (pending.length === 0) {
log('[RAG Queue] No pending embeddings');
return;
}
log(`[RAG Queue] Processing ${pending.length} pending embedding items`);
const result = await processEmbeddingQueue(storage, pending);
const ids = pending.map(i => i.id);
await storage.markEmbeddingQueueProcessed(ids);
log(`[RAG Queue] Done: attempted=${result.attempted}, succeeded=${result.succeeded}, failed=${result.failed}`);
} catch (err) {
log(`[RAG Queue] Worker error: ${err instanceof Error ? err.message : String(err)}`);
}
}
const msUntil23Msk = getMsUntilMskHour(23);
setTimeout(() => {
runEmbeddingQueueWorker();
setInterval(runEmbeddingQueueWorker, 24 * 60 * 60 * 1000);
}, msUntil23Msk);
log(`Embedding queue worker scheduled at 23:00 MSK (in ${Math.round(msUntil23Msk / 1000 / 60)} minutes)`);
// ALWAYS serve the app on the port specified in the environment variable PORT
// Other ports are firewalled. Default to 5000 if not specified.
// this serves both the API and the client.