Repository navigation
fix(orm): respect the log option of clients derived with $setOptions - #2902
kuldeepsinh19 wants to merge 2 commits into
Conversation
Derived clients reused the base client's ZenStackDriver, which patches pooled connections for logging only if the base client's log enables it and always logs with the base client's Log, so `$setOptions` couldn't enable, change or disable logging. ZenStackDriver now keeps its pool-level state (underlying driver, lifecycle, sqlite mutex, transaction bookkeeping) in a shared object. `withLog()` creates a driver over the same state with its own Log. The acquiring driver's log is recorded per connection, and patched connections look it up on each query. A derived client whose `log` differs from its base uses `withLog()` for its executor and `$qbRaw`. Fixes zenstackhq#2355
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
A pool can hand a released connection to a queued acquisition during release (pg-pool resolves the waiting request right away), and queries run on it before that acquisition records its own log, such as a dialect's onReserveConnection hook, were logged with the previous holder's log. Drop the recorded log before releasing the connection. Reported by CodeRabbit in review.
Summary
Fixes #2355.
A client derived with
$setOptions(like every derived client) reuses the base client'sZenStackDriver. That driver adds logging by patching each pooled connection the first time it's acquired, only if the base client'slogenables it, and always logs with the base client'sLog. So$setOptions({ ...db.$options, log })could not turn logging on, switch to another logger, or turn it off.Changes
zenstack-driver.tswithLog(log)returns a driver over the same state with its ownLog, so derived clients keep sharing one connection pool.client-impl.ts: a derived client whoselogoption differs from its base (identity check) useswithLog(new Log(options.log ?? []))for its executor and its$qbRawKysely instance.$use,$setAuth,$transactionand similar keep the samelogreference, so they keep the base driver as before.Known limitation: calling
$setOptionswith a differentlogon a client inside an interactive transaction still logs that transaction's queries with the logger that started it, because those queries run on the connection the transaction already holds.Overlap with #2899: both PRs change the connection provider argument in the derived-client branch of
client-impl.ts. Whichever lands second can combine them asbaseClient.isTransaction ? (baseClient.transactionConnection ?? baseClient.$qb.getExecutor()) : new DefaultConnectionProvider(driver), with the executor takingdriver.Validation
New
tests/regression/test/issue-2355.test.tscovers:$setOptions$qbRawerrorlogkeeping the base loggerWithout the change, 7 of the 8 tests fail in 3 of 3 runs; with it, all 8 pass in 3 of 3 runs.
tests/e2eORM suites that create derived clients and use the driver (client-api/transaction,raw-query,slicing,omit,error-handling,plugin-infra/*): 183 passed before and after.packages/ormunit tests: 7 passed before and after.@zenstackhq/ormlint and build (tsc+ tsdown),tscfortests/regressionand prettier on the changed files pass.Ran on SQLite only (Node 24, pnpm 10.33.0, in a container). The PostgreSQL and MySQL legs of the CI matrix were not run locally.
Review notes
createTestClientare cleared before assertions.$qbRawand for concurrent base and derived queries.withLogreuses the shared state instead of building a throwaway one.releaseConnectionreturns. That acquisition can run queries on it (for example a dialect'sonReserveConnectionhook) while the previous holder's log is still recorded for the connection. This is fixed in 07264a9: the recorded log is now cleared before the connection is released. After that commit:packages/ormunit tests pass (7 of 7);This change was written with help from an AI coding assistant (Claude Code).
Summary by CodeRabbit