Fase 1b: cableado del matcher (ingesta polling, runner shadow/full, comparador)
- config: bloque matcher (MATCHER_MODE off/shadow/full, IRON_PASSWORD, audiencia, poll, batch) + validacion - db: colecciones subscriptions/activefires/notifications_shadow/matcher_state + ensureMatcherIndexes (2dsphere en notifications_shadow para el dedupe 500m) - matcher/context: MatchContext sobre Mongo real (candidatas geo $near 1000km + audiencia; dedupe geo $near 500m; lang del owner) - matcher/ingest: polling de activefires por createdAt>checkpoint (Mongo 3.2 sin change streams), checkpoint persistido en matcher_state - matcher/runner: loop shadow(->notifications_shadow)/full(->notifications), idempotente por dedupe+checkpoint - matcher/compare: comparador de shadow (shadowOnly=spam, realOnly=faltantes, contentMismatches) — el gate antes del cutover - index: arranca el matcher; fake-repo ampliado (upsert, sort, $gt/$lt) - docs/env/README actualizados 73 tests en verde, typecheck y build OK.
This commit is contained in:
parent
b3aeb6108f
commit
a1ed206985
13 changed files with 531 additions and 19 deletions
|
|
@ -1,7 +1,8 @@
|
|||
import { Worker } from 'bullmq';
|
||||
import { loadConfig } from './config.js';
|
||||
import { createLogger } from './logger.js';
|
||||
import { connect, ensureIndexes } from './db.js';
|
||||
import { connect, ensureIndexes, ensureMatcherIndexes } from './db.js';
|
||||
import { createMatcherRunner } from './matcher/runner.js';
|
||||
import { createQueues, redisConnection, QUEUE_NAMES } from './queue.js';
|
||||
import { createFcmClient, type FcmClient } from './fcm.js';
|
||||
import { createMailer, type Mailer } from './mailer.js';
|
||||
|
|
@ -55,9 +56,15 @@ async function main(): Promise<void> {
|
|||
const poller = createPoller(cfg, repos, queues, log);
|
||||
poller.start();
|
||||
|
||||
// Fase 1b — geospatial matcher (fire → subscriptions → notifications).
|
||||
if (cfg.matcher.mode !== 'off') await ensureMatcherIndexes(repos);
|
||||
const matcher = createMatcherRunner(cfg, repos, log);
|
||||
matcher.start();
|
||||
|
||||
const shutdown = async (signal: string): Promise<void> => {
|
||||
log.info({ signal }, 'shutting down');
|
||||
poller.stop();
|
||||
matcher.stop();
|
||||
await Promise.all(workers.map((w) => w.close()));
|
||||
await Promise.all(Object.values(queues).map((q) => q.close()));
|
||||
await repos.close();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue