mansart-pool est un pool de connexions JDBC implémenté en pur Java 25, sans dépendance externe, avec ` Semaphore + ConcurrentLinkedDeque` lock-free et un housekeeper sur virtual thread. Il est totalement découplé du reste de Mansart : son seul contrat est javax.sql.DataSource.
Mission
-
Fournir un
DataSourceperformant, simple, configurable. -
Être natif virtual threads — aucune contention
synchronizedsur le chemin chaud. -
Rester optionnel — l’utilisateur peut brancher
mansart-jakarta-datasur n’importe quelDataSource(Hikari, Tomcat-JDBC, c3p0).
Positionnement dans le workspace
mansart-pool est un peer indépendant des autres modules Mansart. Il ne dépend ni de mansart-data-api, ni de mansart-transactions. À l’inverse, mansart-jakarta-data et mansart-transactions peuvent l’utiliser, mais n’en dépendent pas en compile.
Modules
| Sous-module | Rôle |
|---|---|
|
|
|
|
API publique
PoolConfig config = PoolConfig.builder()
.jdbcUrl("jdbc:postgresql://db.local:5432/shop")
.username("shop").password("...")
.minSize(4).maxSize(32)
.acquireTimeout(Duration.ofSeconds(5))
.idleTimeout(Duration.ofMinutes(10))
.maxLifetime(Duration.ofMinutes(30))
.validationMode(ValidationMode.IS_VALID)
.leakDetectionThreshold(Duration.ofSeconds(30))
.build();
DataSource ds = MansartDataSource.create(config);
PoolMetrics metrics = ((MansartDataSource) ds).metrics();
Voir Référence pour le tableau complet des propriétés.
Architecture runtime
MansartDataSource (impl DataSource)
│
├── Deque<PooledConnection> idle (ConcurrentLinkedDeque, lock-free)
├── Set<PooledConnection> inUse (ConcurrentHashMap.newKeySet)
├── Semaphore permits (taille = maxSize, fair=false)
├── ScopedValue<Connection> CURRENT (propagation transaction)
└── ScheduledTask housekeeper (virtual thread)
Acquisition (getConnection()) :
-
permits.acquire(acquireTimeout)— borne dure. -
idle.poll()— LIFO chaud. -
Si valid (
isValidouvalidationQuery) →inUse.add; sinon →realClose+ créer nouvelle. -
Retour :
PooledConnectionProxyqui intercepteclose().
Restitution (Connection.close() sur le proxy) :
-
pc.reset()— rollback si dirty,autoCommit=true, isolation par défaut. -
inUse.remove(pc). -
Si
aliveAndYoung()→idle.offerFirst(pc); sinon →realClose. -
permits.release().
Le proxy PooledConnectionProxy est généré au build via Class-File API JEP 484 — pas via java.lang.reflect.Proxy. Une seule classe qui implémente toutes les méthodes Connection, intercepte close(). Voir Fonctionnement interne.
Intégration ScopedValue pour transactions
La connexion enlistée par mansart-transactions est portée par ScopedValue<Connection> CURRENT au lieu d’un ThreadLocal. Avantages :
-
Propagation automatique dans
StructuredTaskScope.fork(…). -
Pas de fuite mémoire ThreadLocal sur les virtual threads à durée de vie courte.
-
Sémantique claire : la valeur n’est visible que dans la portée lexicale du
ScopedValue.where(…).
Métriques
PoolMetrics (snapshot lock-free) :
-
idleSize(),inUseSize(),totalSize(). -
acquireCount(),acquireWaitNanos()(cumul + percentiles). -
creationCount(),evictionCount(). -
leakCount().
Bridge Micrometer / Prometheus dans le backlog (MP3).
Détection de fuites
leakDetectionThreshold(Duration) enregistre, à l’acquire, une stack-trace dans le PooledConnection. Si la connexion reste empruntée plus longtemps que le seuil, le housekeeper log un WARNING avec la stack — diagnostic immédiat du chemin de code fautif. À activer en staging, désactiver en prod si l’overhead est mesuré.
Comparatif vs HikariCP
-
Threading — Mansart natif virtual threads, pas de pinning sous charge Loom. HikariCP utilise des
synchronizedqui pinent. -
Dépendances — Mansart zéro-dep. HikariCP dépend de SLF4J + javassist (en transitif via micrometer).
-
AOT — Mansart compatible GraalVM native-image et Leyden CDS sans config. HikariCP nécessite
--initialize-at-build-timepour javassist. -
API — très proches (
HikariConfig→PoolConfig). Voir Migration.
Chiffres : voir lien:https://codeberg.org/Vidocq/mansart/src/branch/main/mansart-pool/BENCH.md[mansart-pool BENCH.md] (baseline 2026-05-06 vs HikariCP).
Roadmap
-
✅ MP1 — API + skeleton.
-
⏳ MP2 — Implémentation core (
MansartDataSource, semaphore, deque, validation). -
⏳ MP3 — Métriques + leak detection.
-
⏳ MP4 — Intégration
mansart-jakarta-data(transparent côté utilisateur).
Voir lien:https://codeberg.org/Vidocq/mansart/src/branch/main/mansart-pool/PLAN.md[mansart-pool PLAN.md].