Skip to content

Commit 533c6dc

Browse files
fix: remove error log when notification manager is already closed (#18264)
Closes coder/internal#677 Resolves flakes such as: ``` $ go test -race -run "TestRunStopRace" github.com/coder/coder/v2/coderd/notifications -count=10000 -parallel $(nproc) --- FAIL: TestRunStopRace (0.00s) t.go:106: 2025-06-06 02:44:39.348 [debu] notifications-manager: notification manager started t.go:106: 2025-06-06 02:44:39.348 [debu] notifications-manager: graceful stop requested t.go:106: 2025-06-06 02:44:39.348 [debu] notifications-manager: notification manager stopped t.go:115: 2025-06-06 02:44:39.348 [erro] notifications-manager: notification manager stopped with error ... error= manager already closed: github.com/coder/coder/v2/coderd/notifications.(*Manager).loop /home/coder/coder/coderd/notifications/manager.go:166 *** slogtest: log detected at level ERROR; TEST FAILURE *** --- FAIL: TestRunStopRace (0.00s) t.go:106: 2025-06-06 02:44:41.632 [debu] notifications-manager: notification manager started t.go:106: 2025-06-06 02:44:41.632 [debu] notifications-manager: graceful stop requested t.go:106: 2025-06-06 02:44:41.632 [debu] notifications-manager: notification manager stopped t.go:115: 2025-06-06 02:44:41.633 [erro] notifications-manager: notification manager stopped with error ... error= manager already closed: github.com/coder/coder/v2/coderd/notifications.(*Manager).loop /home/coder/coder/coderd/notifications/manager.go:166 *** slogtest: log detected at level ERROR; TEST FAILURE *** FAIL FAIL github.com/coder/coder/v2/coderd/notifications 6.847s FAIL ``` These error logs are caused as a result of the `Manager` `Run` start operation being asynchronous. In the flaking test case we immediately call `Stop` after `Run`. It's possible for `Stop` to be scheduled to completion before the goroutine spawned by `Run` calls `loop` and checks `closed`. If this happens, `loop` returns an error and produces the error log. We'll address this by replacing this specific error log with a warning log. ``` $ go test -run "TestRunStopRace" github.com/coder/coder/v2/coderd/notifications -count=10000 -parallel $(nproc) ok github.com/coder/coder/v2/coderd/notifications 1.294s $ go test -race github.com/coder/coder/v2/coderd/notifications -count=100 -parallel $(nproc) ok github.com/coder/coder/v2/coderd/notifications 26.525s ```
1 parent 7c2fb66 commit 533c6dc

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

coderd/notifications/manager.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ func (m *Manager) WithHandlers(reg map[database.NotificationMethod]Handler) {
135135
m.handlers = reg
136136
}
137137

138+
var ErrManagerAlreadyClosed = xerrors.New("manager already closed")
139+
138140
// Run initiates the control loop in the background, which spawns a given number of notifier goroutines.
139141
// Manager requires system-level permissions to interact with the store.
140142
// Run is only intended to be run once.
@@ -146,7 +148,11 @@ func (m *Manager) Run(ctx context.Context) {
146148
go func() {
147149
err := m.loop(ctx)
148150
if err != nil {
149-
m.log.Error(ctx, "notification manager stopped with error", slog.Error(err))
151+
if xerrors.Is(err, ErrManagerAlreadyClosed) {
152+
m.log.Warn(ctx, "notification manager stopped with error", slog.Error(err))
153+
} else {
154+
m.log.Error(ctx, "notification manager stopped with error", slog.Error(err))
155+
}
150156
}
151157
}()
152158
})
@@ -163,7 +169,7 @@ func (m *Manager) loop(ctx context.Context) error {
163169
m.mu.Lock()
164170
if m.closed {
165171
m.mu.Unlock()
166-
return xerrors.New("manager already closed")
172+
return ErrManagerAlreadyClosed
167173
}
168174

169175
var eg errgroup.Group

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy