Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit87dc247

Browse files
feat: fail CI whenpubsub.Publish calls are found in db transactions (#17903)
Publishing inside a db transaction can lead to database connectionstarvation/contention since it requires its own connection.This ruleguard rule (one-shotted by Claude Sonnet 3.7 and finalized by@Emyrk) will detect two of the following 3 instances:```gotype Nested struct {ps pubsub.Pubsub}func TestFail(t *testing.T) {t.Parallel()db, ps := dbtestutil.NewDB(t)nested := &Nested{ps: ps,}// will catch this_ = db.InTx(func(_ database.Store) error {_, _ = fmt.Printf("")_ = ps.Publish("", []byte{})return nil}, nil)// will catch this_ = db.InTx(func(_ database.Store) error {_ = nested.ps.Publish("", []byte{})return nil}, nil)// will NOT catch this_ = db.InTx(func(_ database.Store) error {blah(ps)return nil}, nil)}func blah(ps pubsub.Pubsub) {ps.Publish("", []byte{})}```The ruleguard doesn't recursively introspect function calls so only thefirst two cases will be guarded against, but it's better than nothing.<img width="1444" alt="image"src="https://github.com/user-attachments/assets/8ffa0d88-16a0-41a9-9521-21211910dec9"/>---------Signed-off-by: Danny Kopping <dannykopping@gmail.com>Co-authored-by: Steven Masley <stevenmasley@gmail.com>
1 parent4412f19 commit87dc247

File tree

1 file changed

+36
-0
lines changed

1 file changed

+36
-0
lines changed

‎scripts/rules.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,42 @@ func databaseImport(m dsl.Matcher) {
134134
Where(m.File().PkgPath.Matches("github.com/coder/coder/v2/codersdk"))
135135
}
136136

137+
// publishInTransaction detects calls to Publish inside database transactions
138+
// which can lead to connection starvation.
139+
//
140+
//nolint:unused,deadcode,varnamelen
141+
funcpublishInTransaction(m dsl.Matcher) {
142+
m.Import("github.com/coder/coder/v2/coderd/database/pubsub")
143+
144+
// Match direct calls to the Publish method of a pubsub instance inside InTx
145+
m.Match(`
146+
$_.InTx(func($x) error {
147+
$*_
148+
$_ = $ps.Publish($evt, $msg)
149+
$*_
150+
}, $*_)
151+
`,
152+
// Alternative with short variable declaration
153+
`
154+
$_.InTx(func($x) error {
155+
$*_
156+
$_ := $ps.Publish($evt, $msg)
157+
$*_
158+
}, $*_)
159+
`,
160+
// Without catching error return
161+
`
162+
$_.InTx(func($x) error {
163+
$*_
164+
$ps.Publish($evt, $msg)
165+
$*_
166+
}, $*_)
167+
`).
168+
Where(m["ps"].Type.Is("pubsub.Pubsub")).
169+
At(m["ps"]).
170+
Report("Avoid calling pubsub.Publish() inside database transactions as this may lead to connection deadlocks. Move the Publish() call outside the transaction.")
171+
}
172+
137173
// doNotCallTFailNowInsideGoroutine enforces not calling t.FailNow or
138174
// functions that may themselves call t.FailNow in goroutines outside
139175
// the main test goroutine. See testing.go:834 for why.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp