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
|
|
@ -108,6 +108,29 @@ MODE=full OWNED_CHANNELS=fcm
|
|||
3. Nada se pierde: los docs pendientes siguen en `notifications` con
|
||||
`notified`/`emailNotified` sin marcar.
|
||||
|
||||
## Fase 1b — matcher geoespacial (rollout)
|
||||
|
||||
El matcher **genera** los docs `notifications` (fuego → subs 2dsphere) que hoy
|
||||
crea node-red. Config: `MATCHER_MODE` (`off`/`shadow`/`full`), `IRON_PASSWORD`
|
||||
(sella `sealed`; = `settings.private.ironPassword`), `MATCHER_AUDIENCE`
|
||||
(`web,mobile`). Ingesta por **polling** de `activefires` (Mongo 3.2 no tiene
|
||||
change streams). Ver `docs/legacy-matching.md`.
|
||||
|
||||
Secuencia (empezar solo con la fase 1a estable):
|
||||
|
||||
1. **`MATCHER_MODE=shadow`** ≥3 días / varios ciclos NASA reales. Escribe en
|
||||
`notifications_shadow` (no toca `notifications`, node-red sigue generando).
|
||||
2. **Comparar** con `src/matcher/compare.ts` (`compareShadow`): correr el
|
||||
comparador sobre la ventana y exigir **`shadowOnly` vacío** (0 notifs de más =
|
||||
0 spam) — cada `realOnly` (faltante) se analiza uno a uno; `contentMismatches`
|
||||
revisados.
|
||||
3. **Cutover** (con confirmación explícita): desactivar el subflow de matching en
|
||||
node-red (exportar el flow antes como respaldo; documentar qué nodos) y poner
|
||||
`MATCHER_MODE=full`. node-red deja de insertar en `notifications`; el matcher
|
||||
pasa a ser el único origen. Los workers de 1a consumen igual.
|
||||
4. **Rollback**: reimportar el flow de node-red y `MATCHER_MODE=shadow`/`off`.
|
||||
Los workers de 1a siguen consumiendo `notifications` venga de donde venga.
|
||||
|
||||
## Checklist de verificación (por paso)
|
||||
|
||||
- [ ] Tests en verde (`npm test`).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue