drizzle-team / drizzle-team/drizzle-orm
[BUG]: withReplicas sends reads to a replica inside an Effect transaction
- Dominant language
- TypeScript
- Stars
- 35.8k
- Forks
- 1.6k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 4
Description
### Report hasn't been filed before.
- [x] I have verified that the bug I'm about to report hasn't been filed before.
### What version of `drizzle-orm` are you using?
1.0.0-rc.5-ab785fc
### What version of `drizzle-kit` are you using?
1.0.0-rc.5-ab785fc
### Other packages
Not maintained by Drizzle: @effect/sql-pg@4.0.0-rc.112, effect@4.0.0-rc.112
### Describe the Bug
With the Effect driver, transactions are context-based: everything executed through the same `PgClient` inside `db.transaction` joins it. `withReplicas` ignores that and keeps routing `select` / `with` / `$count` / `query` to a replica, so reads inside a transaction go to another client, outside the transaction.
```ts
const db = withReplicas(primary, [replica]) // two PgClient pools on the same server
yield* db.transaction(() =>
Effect.gen(function* () {
yield* db.insert(items).values({ value: 'pending' })
return yield* db.select().from(items).where(eq(items.value, 'pending'))
})
)
// -> [] : the select ran on the replica connection, the insert is not committed yet
```
Asserting `current_setting('application_name')` in the select shows the replica pool. The promise driver doesn't have this problem since reads inside a transaction go through `tx` (`db.transaction((tx => {})`). With the Effect driver the whole point is that nested code keep using `db` and joins the ambient transaction, which works for writes but not for reads.
Expected: reads routed to the primary while it has a transaction open. The transaction is in the fiber context (`primary.$client.transactionService`), so `withReplicas` could check it at execution time.
Kinda related, accidentally one of my old issues: #4185
Contributor guide
Research direction
Start by reproducing the example with withReplicas, db.transaction, and the Effect driver, then trace withReplicas alongside primary.$client.transactionService. Verify the behavior using the reported current_setting('application_name') check: reads such as select, with, $count, and query should use the primary while the transaction is open.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- postgresql, typescript
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100