File tree 1 file changed +32
-0
lines changed
1 file changed +32
-0
lines changed Original file line number Diff line number Diff line change @@ -134,6 +134,38 @@ func databaseImport(m dsl.Matcher) {
134
134
Where (m .File ().PkgPath .Matches ("github.com/coder/coder/v2/codersdk" ))
135
135
}
136
136
137
+ // publishInTransaction detects calls to Publish inside database transactions
138
+ // which can lead to connection deadlocks or other unexpected behavior.
139
+ //
140
+ //nolint:unused,deadcode,varnamelen
141
+ func publishInTransaction (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
+ $db.InTx(func($tx $dbType) $retType {
147
+ $*_
148
+ $ps.Publish($*args)
149
+ $*_
150
+ }, $*txopts)
151
+ ` ).
152
+ Where (m ["ps" ].Type .Implements ("pubsub.Pubsub" ) ||
153
+ m ["ps" ].Text .Matches (`\w+\.pubsub` ) ||
154
+ m ["ps" ].Text .Matches (`pubsub\.\w+` )).
155
+ Report ("Avoid calling Publish inside database transactions as this may lead to connection deadlocks. Move the Publish call outside the transaction." )
156
+
157
+ // Also catch publish calls on nested fields like c.pubsub.Publish()
158
+ m .Match (`
159
+ $db.InTx(func($tx $dbType) $retType {
160
+ $*_
161
+ $ps.$field.Publish($*args)
162
+ $*_
163
+ }, $*txopts)
164
+ ` ).
165
+ Where (m ["field" ].Text == "pubsub" ).
166
+ Report ("Avoid calling Publish inside database transactions as this may lead to connection deadlocks. Move the Publish call outside the transaction." )
167
+ }
168
+
137
169
// doNotCallTFailNowInsideGoroutine enforces not calling t.FailNow or
138
170
// functions that may themselves call t.FailNow in goroutines outside
139
171
// the main test goroutine. See testing.go:834 for why.
You can’t perform that action at this time.
0 commit comments