Skip to content

feat: introduce ConnectionProvider for thread-scoped DB manager lifecycle#106

Draft
lanarimarco wants to merge 6 commits intodevelopfrom
feat/reload-as-connection-provider
Draft

feat: introduce ConnectionProvider for thread-scoped DB manager lifecycle#106
lanarimarco wants to merge 6 commits intodevelopfrom
feat/reload-as-connection-provider

Conversation

@lanarimarco
Copy link
Copy Markdown
Collaborator

@lanarimarco lanarimarco commented May 5, 2026

Goal

Allow any class on the same thread to obtain the same javax.sql.DataSource (and therefore the same java.sql.Connection) within a logical unit of work, without passing the connection explicitly through the call stack.

  • reload creates and owns connections — via HikariCP pool (production) or DriverManager (tests)
  • Configuration (JDBC URI, credentials, driver, pool sizing) is owned entirely by the caller — reload never reads YAML or external config
  • The entry point is ConnectionProvider.withScope(() -> {}) — a thread-scoped scope; no connection name is required at call time
  • Inside withScope(), any class retrieves the appropriate manager or DataSource by file name via ConnectionProvider.currentManager(fileName) / requireDataSource(fileName)
  • DBFileFactory transparently participates in the active scope — jariko and Java service code share the same Connection on the same thread with no changes to jariko itself
  • Outside any scope (jariko standalone, LSP, debug), currentManagerOrNull() returns null and DBFileFactory falls back to its own manager — no behavioural regression

Summary

  • Adds ConnectionProvider singleton (base module) with thread-local withScope() lifecycle management for DBMManager instances
  • Adds PoolConfig data class for connection pool tuning and poolConfig field on ConnectionConfig
  • Moves findConnectionConfigFor + ConnectionConfigComparator from DBFileFactory into the base module (ConnectionConfigResolver.kt)
  • DBFileFactory now delegates to ConnectionProvider.currentManagerOrNull() when a scope is active, falling back to its own manager pool — guarantees connection sharing with Java service code on the same thread
  • SQL module: adds SQLConnectionPool, SQLPooledDBMManager, ThreadScopedDataSource, ConnectionProviderSqlExtensions, DBMManagerSqlExtensions, and HikariCP dependency

Three-layer design

Layer Module Responsibility
General scope management reload:base ConnectionProvider — works for any DBMManager
Convenience wiring reload:manager Extension that auto-creates managers via reflection
SQL-specific handle reload:sql ThreadScopedDataSource + type-discovery extensions + HikariCP pool
(future) JT400-specific reload:jt400 toAS400Connection(): AS400?
(future) NoSQL-specific reload:nosql toMongoDatabase(): MongoDatabase?

Test plan

  • ConnectionProviderTest — unit tests for scope lifecycle, manager reuse, and null-safe fallback
  • DBFileFactoryConnectionSharingTest — verifies DBFileFactory reuses the scoped manager when withScope() is active
  • SQLConnectionPoolTest — pool acquire/release behaviour
  • SQLPooledDBMManagerTest — pooled manager integration
  • ConnectionProviderSqlExtensionsTest — SQL-specific provider wiring

…ecycle

Adds a thread-local ConnectionProvider singleton that manages DBMManager
instances per thread using withScope() for automatic lifecycle management.

- base: add ConnectionProvider, PoolConfig, and move ConnectionConfigResolver
  (findConnectionConfigFor + ConnectionConfigComparator) out of DBFileFactory
- base: add poolConfig field to ConnectionConfig (@jvmoverloads constructor)
- manager: DBFileFactory now delegates to ConnectionProvider.currentManagerOrNull()
  when a scope is active, falling back to its own manager pool
- manager: add ConnectionProviderExtensions to wire manager-module factory
- sql: add SQLConnectionPool, SQLPooledDBMManager, ThreadScopedDataSource,
  ConnectionProviderSqlExtensions, DBMManagerSqlExtensions, and HikariCP dep
@lanarimarco lanarimarco changed the base branch from master to develop May 5, 2026 10:13
…eprecation shim

- ThreadScopedDataSource now returns a NonCloseableConnection so callers following the standard JDBC close-every-connection idiom cannot accidentally terminate the shared scope connection
- Update test assertion to unwrap the delegate before comparing identity
- Add deprecated findConnectionConfigFor shim in manager package pointing to the new location in com.smeup.dbnative
`ConnectionConfig.poolConfig` is now nullable (default null). `configureWithPool`
skips pooling for configs without an explicit `PoolConfig` and falls back to a plain
`SQLDBMManager`, so callers can mix pooled and non-pooled connections in one config.
`SQLConnectionPool` guards against a null poolConfig with a clear `requireNotNull`.
Some JDBC drivers (e.g. AS400) do not implement `Connection.isValid()`, causing
HikariCP health checks to fail. The new optional `connectionTestQuery` field is
forwarded to `HikariConfig.setConnectionTestQuery()` when set, enabling a fallback
SQL query for connection validation.
Log pool creation/shutdown, connection open/close with lifetime, and
pooled borrow/return with acquire timing; add ConnectionLoggingTest.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant