Skip to content

Commit b8f215c

Browse files
committed
fix(dbpurge): use dbauthz.AsSystemRestricted and add jitter
Fixes: #7016
1 parent 00d468b commit b8f215c

File tree

2 files changed

+54
-3
lines changed

2 files changed

+54
-3
lines changed

coderd/database/dbpurge/dbpurge.go

+34-3
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,48 @@ import (
1010

1111
"cdr.dev/slog"
1212
"github.com/coder/coder/coderd/database"
13+
"github.com/coder/coder/coderd/database/dbauthz"
14+
"github.com/coder/coder/cryptorand"
1315
)
1416

17+
const (
18+
jitter = 2 * time.Hour
19+
delay = 23 * time.Hour
20+
)
21+
22+
func nextTick() (time.Duration, error) {
23+
f, err := cryptorand.Float64()
24+
if err != nil {
25+
return 0, err
26+
}
27+
28+
return delay + time.Duration(float64(jitter)*f), nil
29+
}
30+
1531
// New creates a new periodically purging database instance.
1632
// It is the caller's responsibility to call Close on the returned instance.
1733
//
1834
// This is for cleaning up old, unused resources from the database that take up space.
1935
func New(ctx context.Context, logger slog.Logger, db database.Store) io.Closer {
2036
closed := make(chan struct{})
2137
ctx, cancelFunc := context.WithCancel(ctx)
38+
//nolint:gocritic // The system purges old db records without user input.
39+
ctx = dbauthz.AsSystemRestricted(ctx)
2240
go func() {
2341
defer close(closed)
24-
ticker := time.NewTicker(24 * time.Hour)
25-
defer ticker.Stop()
42+
wait, err := nextTick()
43+
if err != nil {
44+
logger.Error(ctx, "failed to generate random delay; exiting", slog.Error(err))
45+
return
46+
}
47+
48+
timer := time.NewTimer(wait)
49+
defer timer.Stop()
2650
for {
2751
select {
2852
case <-ctx.Done():
2953
return
30-
case <-ticker.C:
54+
case <-timer.C:
3155
}
3256

3357
var eg errgroup.Group
@@ -44,6 +68,13 @@ func New(ctx context.Context, logger slog.Logger, db database.Store) io.Closer {
4468
}
4569
logger.Error(ctx, "failed to purge old database entries", slog.Error(err))
4670
}
71+
72+
wait, err := nextTick()
73+
if err != nil {
74+
logger.Error(ctx, "failed to generate random delay; exiting", slog.Error(err))
75+
return
76+
}
77+
timer.Reset(wait)
4778
}
4879
}()
4980
return &instance{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package dbpurge
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
"github.com/stretchr/testify/require"
8+
)
9+
10+
func Test_nextTick(t *testing.T) {
11+
t.Parallel()
12+
13+
tick, err := nextTick()
14+
require.NoError(t, err)
15+
16+
t.Log("tick:", tick.String())
17+
18+
assert.GreaterOrEqual(t, tick, delay)
19+
assert.LessOrEqual(t, tick, delay+jitter)
20+
}

0 commit comments

Comments
 (0)