MCPcopy Index your code
hub / github.com/coder/coder / subscribeQueue

Method subscribeQueue

coderd/database/pubsub/pubsub.go:253–365  ·  view source on GitHub ↗
(event string, newQ *MsgQueue)

Source from the content-addressed store, hash-verified

251}
252
253func (p *PGPubsub) subscribeQueue(event string, newQ *MsgQueue) (cancel func(), err error) {
254 defer func() {
255 if err != nil {
256 // if we hit an error, we need to close the queue so we don't
257 // leak its goroutine.
258 newQ.Close()
259 p.subscribesTotal.WithLabelValues("false").Inc()
260 } else {
261 p.subscribesTotal.WithLabelValues("true").Inc()
262 }
263 }()
264
265 var (
266 unlistenInProgress <-chan struct{}
267 // MUST hold the p.qMu lock to manipulate this!
268 qs *queueSet
269 )
270 func() {
271 p.qMu.Lock()
272 defer p.qMu.Unlock()
273
274 var ok bool
275 if qs, ok = p.queues[event]; !ok {
276 qs = newQueueSet()
277 p.queues[event] = qs
278 }
279 qs.m[newQ] = struct{}{}
280 unlistenInProgress = qs.unlistenInProgress
281 }()
282 // NOTE there cannot be any `return` statements between here and the next +-+, otherwise the
283 // assumptions the defer makes could be violated
284 if unlistenInProgress != nil {
285 // We have to wait here because we don't want our `Listen` call to happen before the other
286 // goroutine calls `Unlisten`. That would result in this subscription not getting any
287 // events. c.f. https://github.com/coder/coder/issues/15312
288 p.logger.Debug(context.Background(), "waiting for Unlisten in progress", slog.F("event", event))
289 <-unlistenInProgress
290 p.logger.Debug(context.Background(), "unlistening complete", slog.F("event", event))
291 }
292 // +-+ (see above)
293 defer func() {
294 if err != nil {
295 p.qMu.Lock()
296 defer p.qMu.Unlock()
297 delete(qs.m, newQ)
298 if len(qs.m) == 0 {
299 // we know that newQ was in the queueSet since we last unlocked, so there cannot
300 // have been any _new_ goroutines trying to Unlisten(). Therefore, if the queueSet
301 // is now empty, it's safe to delete.
302 delete(p.queues, event)
303 }
304 }
305 }()
306
307 // The pgListener waits for the response to `LISTEN` on a mainloop that also dispatches
308 // notifies. We need to avoid holding the mutex while this happens, since holding the mutex
309 // blocks reading notifications and can deadlock the pgListener.
310 // c.f. https://github.com/coder/coder/issues/11950

Callers 2

SubscribeMethod · 0.95
SubscribeWithErrMethod · 0.95

Calls 10

newQueueSetFunction · 0.85
WithLabelValuesMethod · 0.80
CloseMethod · 0.65
ListenMethod · 0.65
UnlistenMethod · 0.65
LockMethod · 0.45
UnlockMethod · 0.45
IsMethod · 0.45
ErrorfMethod · 0.45
ErrorMethod · 0.45

Tested by

no test coverage detected