Skip to content

Commit e4e0311

Browse files
committed
address more PR comments
1 parent 5876edd commit e4e0311

File tree

2 files changed

+32
-9
lines changed

2 files changed

+32
-9
lines changed

coderd/workspaceusage/tracker.go

+25-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package workspaceusage
22

33
import (
4+
"bytes"
45
"context"
6+
"flag"
57
"os"
68
"sort"
7-
"strings"
89
"sync"
910
"time"
1011

@@ -84,16 +85,22 @@ func WithFlushInterval(d time.Duration) Option {
8485

8586
// WithFlushChannel allows passing a channel that receives
8687
// the number of marked workspaces every time Tracker flushes.
87-
// For testing only.
88+
// For testing only and will panic if used outside of tests.
8889
func WithFlushChannel(c chan int) Option {
90+
if flag.Lookup("test.v") == nil {
91+
panic("developer error: WithFlushChannel is not to be used outside of tests.")
92+
}
8993
return func(h *Tracker) {
9094
h.flushCh = c
9195
}
9296
}
9397

9498
// WithTickChannel allows passing a channel to replace a ticker.
95-
// For testing only.
99+
// For testing only and will panic if used outside of tests.
96100
func WithTickChannel(c chan time.Time) Option {
101+
if flag.Lookup("test.v") == nil {
102+
panic("developer error: WithTickChannel is not to be used outside of tests.")
103+
}
97104
return func(h *Tracker) {
98105
h.tickCh = c
99106
h.stopTick = func() {}
@@ -125,11 +132,6 @@ func (wut *Tracker) flush(now time.Time) {
125132
return
126133
}
127134

128-
// For ease of testing, sort the IDs lexically
129-
sort.Slice(ids, func(i, j int) bool {
130-
// For some unfathomable reason, byte arrays are not comparable?
131-
return strings.Compare(ids[i].String(), ids[j].String()) < 0
132-
})
133135
// Set a short-ish timeout for this. We don't want to hang forever.
134136
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
135137
defer cancel()
@@ -147,7 +149,15 @@ func (wut *Tracker) flush(now time.Time) {
147149
wut.log.Info(ctx, "updated workspaces last_used_at", slog.F("count", count), slog.F("now", now))
148150
}
149151

152+
// Loop periodically flushes every tick.
153+
// If Loop is called after Close, it will panic. Don't do this.
150154
func (wut *Tracker) Loop() {
155+
// Calling Loop after Close() is an error.
156+
select {
157+
case <-wut.doneCh:
158+
panic("developer error: Loop called after Close")
159+
default:
160+
}
151161
defer func() {
152162
wut.log.Debug(context.Background(), "workspace usage tracker loop exited")
153163
}()
@@ -165,7 +175,8 @@ func (wut *Tracker) Loop() {
165175
}
166176
}
167177

168-
// Close stops Tracker and performs a final flush.
178+
// Close stops Tracker and returns once Loop has exited.
179+
// After calling Close(), Loop must not be called.
169180
func (wut *Tracker) Close() {
170181
wut.stopOnce.Do(func() {
171182
wut.stopCh <- struct{}{}
@@ -202,6 +213,11 @@ func (s *uuidSet) UniqueAndClear() []uuid.UUID {
202213
for k := range s.m {
203214
l = append(l, k)
204215
}
216+
// For ease of testing, sort the IDs lexically
217+
sort.Slice(l, func(i, j int) bool {
218+
// For some unfathomable reason, byte arrays are not comparable?
219+
return bytes.Compare(l[i][:], l[j][:]) < 0
220+
})
205221
s.m = make(map[uuid.UUID]struct{})
206222
return l
207223
}

coderd/workspaceusage/tracker_test.go

+7
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ func TestTracker(t *testing.T) {
9292

9393
wg.Wait()
9494
require.Equal(t, 11, count, "expected one flush with eleven ids")
95+
96+
// 4. Closing multiple times should not be a problem.
97+
wut.Close()
98+
wut.Close()
99+
100+
// 5. Running Loop() again should panic.
101+
require.Panics(t, wut.Loop)
95102
}
96103

97104
func TestMain(m *testing.M) {

0 commit comments

Comments
 (0)