livrare lot 2

This commit is contained in:
EVOTECH IT SRL 2026-07-10 03:39:53 -07:00
commit 8ecc78e729
763 changed files with 164593 additions and 0 deletions

View file

@ -0,0 +1,168 @@
# Migrare RabbitMQ: `staging-dataLayer-rabbitmq` local → cluster HA `10.11.50.100`
**Autor**: refactor 2026-04-22 (după Redis migration)
**Scop**: mutarea cozilor async (cele 31 de cozi analysis.*) de pe containerul RabbitMQ local pe clusterul HA managed cu vhost dedicat `/didi`.
---
## Stare actuală (post-cutover)
- Codul RabbitMQ era **deja centralizat** în 3 fișiere:
- `src/queue/connection.ts` — manager singleton conexiune + channels
- `src/shared/queue/constants.ts``getRabbitMQConfig()` + `getRabbitMQUrl()`
- `src/scripts/init-priority-queues.ts` — script standalone
- Zero refactor pe cod aplicație. Un singur punct de schimbat.
- URL-encoding corect pentru vhost `/didi` adăugat în `getRabbitMQUrl()` (folosește `encodeURIComponent` pentru user/pass/vhost).
- `CONNECTION_RETRY_DELAY` tuned de la 5s la 2s pentru failover HA mai rapid.
- Logging îmbunătățit: arată host+vhost+user la conectare/eroare/close.
---
## Target
| Parametru | Valoare |
|---|---|
| AMQP | `10.11.50.100:16672` |
| Management UI | `http://10.11.50.100:16673` |
| Username | `didi` |
| Password | `$CLUSTER_PASSWORD` |
| Vhost dedicat | `/didi` (izolat de alte proiecte) |
| URI encoded | `amqp://didi:...@10.11.50.100:16672/%2Fdidi` |
| Cluster HA | 3 noduri rag01/02/03 + HAProxy VIP |
---
## Diferență critică față de Redis
**Nu a fost nevoie de migrare de date**. Cozile RabbitMQ sunt efemere — topologia (exchange + 31 queues) se creează automat de workeri la `assertExchange()` / `assertQueue()` pe prima conectare. Mesajele în zbor la cutover se pierd (erau 0 la momentul migrării).
---
## Pași executați la cutover
### 1. Refactor cod (minim)
- `src/queue/connection.ts`:
- Retry: 5s → 2s
- Logging: `[RabbitMQ] Connecting to HOST:PORT/VHOST (user: USER)...`
- Error messages: includ host+vhost pentru debug
- Add `blocked/unblocked` handlers (broker flow control)
- `src/shared/queue/constants.ts`:
- `getRabbitMQUrl()` folosește `encodeURIComponent()` pentru user/pass/vhost
- Fix critical: vhost `/didi` acum devine `%2Fdidi` în URL (fără asta, amqplib parsa ca vhost `didi` fără slash)
### 2. docker-compose (agent-v3)
`x-worker-env` schimbate din hardcoded la fallbacks:
```yaml
RABBITMQ_HOST: ${RABBITMQ_HOST:-staging-dataLayer-rabbitmq}
RABBITMQ_PORT: ${RABBITMQ_PORT:-5672}
RABBITMQ_USER: ${RABBITMQ_USER:-admin}
RABBITMQ_PASS: ${RABBITMQ_PASS:-rabbitmq123}
RABBITMQ_VHOST: ${RABBITMQ_VHOST:-/}
```
### 3. `.env` agent-v3
Adăugat bloc:
```
RABBITMQ_HOST=10.11.50.100
RABBITMQ_PORT=16672
RABBITMQ_USER=didi
RABBITMQ_PASS=$CLUSTER_PASSWORD
RABBITMQ_VHOST=/didi
```
### 4. Rebuild + restart
- `docker compose build` (toate 8 imagini, cache fast)
- `docker compose up -d --force-recreate` pe agent-v3 stack
- Workerii s-au conectat în < 1s și au creat automat toate 31 cozile
### 5. Verificare
- 31/31 cozi prezente pe `/didi` cu consumerii corespunzători (claims×3, rest×2)
- 14 conexiuni active de la workeri prin HAProxy VIP
- Smoke test: analiză async plan 4 = pro, status `completed` în 3.9s, risk MOSTLY_RELIABLE (22)
---
## Script de verificare: `scripts/verify-rabbitmq-cluster.ts`
Mirror al `verify-redis-cluster.ts`. Rulează cu:
```bash
RABBITMQ_HOST=10.11.50.100 RABBITMQ_PORT=16672 \
RABBITMQ_USER=didi RABBITMQ_PASS='...' RABBITMQ_VHOST=/didi \
node_modules/.bin/ts-node --transpile-only scripts/verify-rabbitmq-cluster.ts
```
Verifică:
1. Conectivitate + auth pe vhost
2. Channel creation
3. Assert exchange `analysis` (topic, durable)
4. Write privilege (creează + șterge coadă temporară)
5. Topologie expected (31 cozi) — WARN dacă workerii nu au rulat încă
Exit codes: `0` = OK sau WARN (topology lipsă pre-cutover), `1` = FATAL.
---
## Fallback LOCAL păstrat
Containerul `staging-dataLayer-rabbitmq` e **oprit** dar **nu șters** — rollback rapid prin script.
### Switch rapid: `services/orchestration-layer/scripts/redis-switch.sh`
Scriptul acoperă ACUM ambele servicii (Redis + RabbitMQ):
```bash
# Arată status curent
./redis-switch.sh status
# Switch ambele (Redis + Rabbit) la cluster
./redis-switch.sh cluster
# Switch ambele la local
./redis-switch.sh local
# Doar unul:
./redis-switch.sh cluster redis # Redis → cluster, Rabbit neschimbat
./redis-switch.sh local rabbit # Rabbit → local, Redis neschimbat
```
Script-ul:
- Pornește containerul local dacă e oprit (`docker start` sau `docker compose up -d`)
- Rescrie blocul corespunzător în `.env` (fără să atingă celelalte)
- Restart `didi-framework` + `agent-v3` stack
### Rollback în 30s
```bash
./redis-switch.sh local rabbit # doar RabbitMQ înapoi la local
```
---
## Cleanup DEFINITIV (după 30+ zile stabil)
1. Stop + remove container local:
```bash
docker stop staging-dataLayer-rabbitmq # deja oprit
docker rm staging-dataLayer-rabbitmq
docker volume rm didi-staging-rabbitmq-data
```
2. Șterge secțiunea din `data-layer/docker-compose.yml`
3. Update `didiQueue/INDEX.md` marcat ca deprecated
4. Admin dashboard nginx — șterge `/health-check/rabbitmq` (pointa la container local)
---
## Riscuri cunoscute / TODO
1. **amqplib nu are Sentinel/discovery nativ** — la failover cluster, ioredis-style "învață" singur noul master. amqplib doar se deconectează și se reconectează la VIP (care rutează la noul master). Downtime client: 5-15s acceptabil.
2. **init-priority-queues.ts** — neinvestigat în detaliu dacă mai e rulat. Cozile se creează oricum prin workeri.
3. **Monitoring**: management UI-ul e pe `10.11.50.100:16673` — accesibil doar din LAN. Admin dashboard nu-l embedă direct; user poate deschide browser separat.