Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

push-manager

Service Quarkus chargé de l'envoi des notifications push (Firebase Cloud Messaging) de l'ENT.

Il consomme une file de notifications en PostgreSQL, résout les tokens FCM des destinataires dans Neo4j, envoie via l'API FCM HTTP v1, journalise un rapport par token et purge les tokens devenus invalides.

  • Java 25 / Quarkus 3.36, threads virtuels
  • Port HTTP par défaut : 8101
  • Artefact : io.edifice:push-manager

Fonctionnement

Un scheduler (SendNotificationScheduler) tourne toutes les 10 s, sans exécution concurrente (ConcurrentExecution.SKIP), sur thread virtuel. Le traitement est découpé en trois phases aux transactions distinctes : aucune transaction n'est tenue pendant un appel réseau.

flowchart TD
    A["TX1 — claimNextBatch()<br/>SELECT ... FOR UPDATE SKIP LOCKED (≤ 10 000)<br/>attempts += 1, attemptAt = now → COMMIT"] --> B
    B["Envois hors transaction<br/>1 thread virtuel par notif, 32 envois FCM concurrents max<br/>Neo4j : lecture des fcmTokens · FCM HTTP v1 : 1 requête par token"] --> C
    C["TX2 — persistOutcome() par tranches de 500<br/>1 rapport par token + statut final (SUCCESS / ERROR / reste PENDING)"] --> D
    D["Purge hors transaction<br/>suppression des tokens obsolètes dans Neo4j, par utilisateur"]
Loading

Points de conception :

  • Réservation durable : la tentative est inscrite (attempts, attemptAt) et committée avant tout envoi. Les autres instances sont ensuite exclues par la fenêtre de reprise de 5 min de nextBatch(), et non par des verrous tenus pendant les envois. Un crash en cours d'envoi ne rejoue le lot qu'après cette fenêtre, tentative décomptée.
  • Limite de tentatives : push-notif.max-attempts (défaut 5) ; à épuisement la notif bascule en ERROR.
  • Classification transitoire / définitif fondée sur le code d'erreur applicatif FCM (FcmErrorCode, lu dans error.details[]) et non sur le seul statut HTTP.
  • Purge de token uniquement sur UNREGISTERED et SENDER_ID_MISMATCH, codes qui désignent le token lui-même. Un 403 PERMISSION_DENIED (projet Firebase mal configuré) ne purge rien.
  • Livraison at-least-once : un doublon reste possible si le process meurt entre l'envoi et TX2.

Dépendances externes

Dépendance Usage
PostgreSQL schéma push_manager : file push_notifs, rapports push_notif_reports. Migrations Flyway (src/main/resources/db/migration), appliquées au démarrage.
Neo4j 3.x lecture / mise à jour de (:User)-[:PREFERS]->(:UserAppConf).fcmTokens, via l'API HTTP transactionnelle (/db/data/transaction/commit) — Bolt indisponible.
FCM HTTP v1 envoi, authentifié par un compte de service Google (OAuth2).
MongoDB collection logpushnotifs — amorce de journalisation (LogPushNotifServiceImpl), pas encore branchée sur le batch.
Zookeeper enregistrement du service pour Traefik, désactivé par défaut (REGISTER_ZOOKEEPER).

Prérequis

  1. Docker
  2. Java 25 — ./build.sh fait tourner Maven dans l'image mvn-java25-node22, donc rien à installer pour ce chemin ; pour un mvn local, vérifier que JAVA_HOME pointe bien sur un JDK 25
  3. edifice-cli — installé par ./build.sh init

Configuration

Tout est surchargeable par variables d'environnement (voir src/main/resources/application.properties).

Variable Défaut Rôle
QUARKUS_HTTP_PORT 8101 port HTTP
DB_URL / DB_USERNAME / DB_PASSWORD jdbc:postgresql://localhost:5432/ong?currentSchema=push_manager / web-education / We_1234 PostgreSQL
MIGRATE_AT_STARTUP true migrations Flyway au démarrage
NEO4J_URL http://localhost:7474 endpoint HTTP Neo4j
NEO4J_USERNAME / NEO4J_PASSWORD vides auth Neo4j (vides en local, auth désactivée)
FCM_PROJECT_ID vide projet Firebase cible
FCM_ISS vide client_email du compte de service
FCM_KEY vide clé privée PEM (acceptée sur une seule ligne, cf. FirebaseConfig.normalizePem)
FCM_SCOPE https://www.googleapis.com/auth/firebase.messaging scope OAuth2
PUSH_NOTIF_MAX_ATTEMPTS 5 tentatives avant bascule en ERROR
PLATFORM_ID / PLATFORM_NAME / PLATFORM_TIMEZONE — / local / Europe/Paris identification de la plateforme
REGISTER_ZOOKEEPER / ZOOKEEPER_HOSTS false / zookeeper1:2181 enregistrement Zookeeper
SERVICE_NAME / SERVICE_PATH_PREFIX push-manager / /push-manager identité annoncée à Traefik
MONGDB_USERNAME / MONGDB_PASSWORD vides MongoDB (noms tels quels dans la config)

Sans FCM_PROJECT_ID / FCM_ISS / FCM_KEY valides, le service démarre mais tout envoi échoue.

Développement local

Démarrer les dépendances (le compose.yaml fournit PostgreSQL, MongoDB, Adminer sur localhost:48080 et Zookeeper) :

docker compose up -d postgres mongo adminer

compose.yaml ne fournit pas Neo4j : pointer NEO4J_URL sur une instance existante.

Puis lancer le service en mode dev (rechargement à chaud) :

mvn quarkus:dev      # ou : quarkus dev

En mode dev : Swagger UI sur /q/swagger-ui.

Build & publication

./build.sh init clean install   # init (+ edifice-cli), clean, install
./build.sh test                 # tests Maven dans le conteneur de build
./build.sh publish              # publication du jar sur le Nexus ODE
./build.sh image                # image conteneur JVM (tag <version>-jvm)
./build.sh imageNative          # image native (tag <version>-native)

La CI (Jenkinsfile) enchaîne ./build.sh init, puis ./edifice install, publish et image.

Tests

Tests Java (src/test/java, 20 tests) :

JAVA_HOME=<jdk-25> mvn test     # ou ./build.sh test

Ils tournent sans dépendance à installer : Dev Services démarre un PostgreSQL jetable, FakeNeo4jServer remplace Neo4j (vrai serveur HTTP sur port aléatoire) et FakeFcmSender remplace l'envoi FCM. Le scheduler est désactivé (quarkus.scheduler.enabled=false) pour piloter pollAndSend() de façon déterministe. Couverture : migrations Flyway, client Neo4j (avec et sans auth), extraction du code d'erreur FCM, et le cycle complet du batch (succès, purge de token, reprise, épuisement des tentatives).

Tests k6 (src/test/js) : scénario d'intégration it/scenarios/health.ts et amorce de test de charge loadtest/scenarios, publiés comme paquet @edifice.io/push-manager-tests.

Endpoints

Endpoint Description
/q/health, /q/health/live, /q/health/ready SmallRye Health (dont MemoryHealthCheck en readiness, seuil heap 90 %)
/q/metrics métriques Prometheus (Micrometer)
/q/openapi, /q/swagger-ui OpenAPI ; Swagger UI en mode dev uniquement

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages