SqlClient: a fiber forked inside a transaction keeps using its connection after the transaction ends
Maintainer thường phản hồi trong vòng 1 ngày
@effect-bot đang làm issue này rồi.
Từ ngày 6/11/2026.
Đánh giá
Issue này chưa được đánh giá.
Mô tả
What version of Effect is running?
effect 4.1.2, @effect/sql-sqlite-bun 4.1.2, Bun 1.4.2
What steps can reproduce the bug?
A fiber forked inside withTransaction outlives it. Its context still holds the TransactionConnection, so its
statements go straight to that connection, without the client's lock. Here its plain INSERT runs inside another
fiber's transaction, which then rolls back: the INSERT reported success and the row is gone.
import { SqliteClient } from "@effect/sql-sqlite-bun"
import * as Deferred from "effect/Deferred"
import * as Effect from "effect/Effect"
import * as Fiber from "effect/Fiber"
import { SqlClient } from "effect/sql"
const program = Effect.gen(function*() {
const sql = yield* SqlClient.SqlClient
yield* sql`CREATE TABLE t (who TEXT)`
const go = yield* Deferred.make<void>()
const done = yield* Deferred.make<void>()
// Forked inside a transaction, runs after it has committed.
const stale = yield* sql.withTransaction(
Effect.forkChild(Effect.gen(function*() {
yield* Deferred.await(go)
yield* sql`INSERT INTO t VALUES ('stale fiber')`
yield* Deferred.succeed(done, undefined)
}))
)
const other = yield* Effect.forkChild(Effect.ignore(sql.withTransaction(Effect.gen(function*() {
yield* sql`INSERT INTO t VALUES ('other transaction')`
yield* Deferred.succeed(go, undefined)
yield* Deferred.await(done)
return yield* Effect.fail("rollback")
}))))
yield* Fiber.join(stale)
yield* Fiber.join(other)
console.log(yield* sql`SELECT who FROM t`)
})
Effect.runPromise(program.pipe(Effect.scoped, Effect.provide(SqliteClient.layer({ filename: ":memory:" }))))
What is the expected behavior?
The stale fiber's statement fails, as a statement on a released pin does in @effect/sql-pg since #9089, or it
takes the connection through the client's lock like any other statement. Either way, [ { who: 'stale fiber' } ]
or an error, never a lost row.
What do you see instead?
[]
The INSERT succeeded and was rolled back with the other fiber's transaction. A nested withTransaction in such
a fiber does the same with a SAVEPOINT: SQLite starts a transaction for it outside the lock, and the next
withTransaction to take the lock fails with cannot start a transaction within a transaction.
Additional information
getConnection and makeWithTransaction in SqlClient.ts take the connection from the TransactionConnection
found in the context, with no check that its transaction is still open. #9084 was the same situation on sql-pg,
fixed in the driver by marking a released pin. The SQLite clients share one connection and have nothing to mark,
so the check would have to live where the connection is taken from the context, as the one afterCommit already
does ("the transaction has already ended").
We hit this in a runtime on Effect Cluster, where a handler forks long-lived fibers inside WithTransaction, and
now fork with Effect.updateContext(effect, Context.omit(sql.transactionService)).
- Ngôn ngữ chính
- TypeScript
- Star
- 16.7k
- Fork
- 808
- Merge trung bình
- 12 giờ 17 phút
- Pull request đã merge (30 ngày)
- 805
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của Effect-TS/effect
-
From Discord: Return Stream.empty for HTTP requests with an empty bodyCó thể đã có người làm @pujitha24 đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 30/100
Maintainer thường phản hồi trong vòng 1 ngày
-
sql-pg: scoped connection shutdown retains a socket when the peer withholds FINCó thể đã có người làm @effect-bot đã nhận hôm nay. Đang mở
Effect-TS/effect#10458 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Schema: a public way to derive a canonical codec, as `toCodecJson` and `toCodecStringTree` doCó thể đã có người làm @effect-bot đã nhận hôm nay. Đang mởNeeds Proposal schema
Effect-TS/effect#10457 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
McpServer.layerHttp: optional legacy GET SSE for idle list-change notificationsCó thể đã có người làm @effect-bot đã nhận 1 ngày trước. Đang mở
Effect-TS/effect#10436 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
CLI completions stop offering repeatable flags after their first useCó thể đã có người làm @effect-bot đã nhận 1 ngày trước. Đang mở
Effect-TS/effect#10427 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của Effect-TS/effect
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
microsoft/vscode-containers#655 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 77/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
dsh-tauri-desk/deepseek-harness-desktop#1477 · 1 bình luận ·
-
[docs] RELEASE.md: wrong branch name, no check that the prepare PR merged with the right subject, manual publish stepCó thể đã có người làm @albertteoh đã nhận hôm nay. Đang mởdocumentation
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
jaegertracing/jaeger-ui#4739 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Add: Shop On TV SDĐang mởcheck:passed streams:add
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 64/100
Maintainer thường phản hồi trong vòng 1 ngày