Skip to content

Pipeline-ul de notificare

De la o cerere notify la un status persistent.

  1. Cerere — POST /api/v1/notify/{id} (mașină, mTLS) sau POST /api/admin/notify (consola UI). {id} = trackingId ales de client.
  2. Rezolvare șablon — după (sistem, templateKey, limba); conținutul per canal e randat cu {{variabile}} din cerere.
  3. Persistare — NotificationDispatchService creează o Notificare + câte o Livrare (status QUEUED) per canal cerut + un eveniment CREATED.
  4. Publicare — pentru fiecare livrare se publică un NotificationJob pe coada notify.{canal}.{tier}. Job-ul poartă conținutul deja randat (stateless).
  5. Consum — workerii @RabbitListener (service/delivery) preiau job-ul și cheamă ChannelSender-ul canalului.
  6. Livrare — la succes → Livrare.status=SENT + providerMessageId; la eșec → retry [10,30,60,120,300]s, apoi FAILED + .dlq. Fiecare tranziție scrie un EvenimentNotificare (QUEUED/SENT/FAILED).
  7. Agregare — statusul Notificare se recalculează din livrări (SENT/FAILED/PARTIAL/QUEUED).
  8. Interogare — GET /api/v1/notify/{id} (mașină) sau ecranul Status notificare (UI) → status agregat + cronologia evenimentelor.
POST /api/v1/notify/TRK-2026-0001
Content-Type: application/json
{
"template": "invoice-ready",
"language": "ro",
"variables": { "invoiceNumber": "F-123", "name": "Ion" },
"channels": [
{ "channel": "email", "tier": "important", "recipient": "ion@example.md" },
{ "channel": "telegram", "tier": "priority", "recipient": "@ion" }
]
}
  • 6 cozi notify.{canal}.{tier} + 6 .dlq (NotifyQueues).
  • Retry [10,30,60,120,300]s × 5; apoi dead-letter.
  • Concurență: priority = 4, important = 2 (DeliveryProperties, env-overridable).
  • Consola cozilor (admin): /api/admin/rabbit/queues — inspectează adâncimi, previzualizează mesaje, replay din DLQ, purge (vezi API-Reference).

Câmpurile per canal din Template.continut sunt liber-formatate și randate cu {{variabila}}. Exemplu:

{
"email": { "subject": "Factura {{invoiceNumber}}", "body": "Salut {{name}}" },
"push": { "title": "Factură gata", "body": "{{invoiceNumber}} gata" },
"telegram": { "text": "Factura {{invoiceNumber}} este gata" }
}

Poarta reală la trimitere este prezența conținutului pe canal în șablon (nu allowedChannels, care e informativ).

La markSent(...), pe lângă tranziția livrării, se declanșează (best-effort, @Async, nu blochează):

  • GLog — fan-out de audit către serviciul centralizat gStack.
  • MNotify — redirecționare mTLS către platforma guvernamentală (vezi MNotify-Forwarding).

Ambele scriu propriile evenimente și nu propagă excepții în pipeline-ul de livrare.