Skip to content

Commit a74273f

Browse files
authored
chore(coderd/database/dbpurge): replace usage of time.* with quartz (#14480)
Related to #10576 This PR introduces quartz to coderd/database/dbpurge and updates the following unit tests to make use of Quartz's functionality: - TestPurge - TestDeleteOldWorkspaceAgentLogs Additionally, updates DeleteOldWorkspaceAgentLogs to replace the hard-coded interval with a parameter passed into the query. This aids in testing and brings us a step towards allowing operators to configure the cutoff interval for workspace agent logs.
1 parent c90be9b commit a74273f

File tree

11 files changed

+120
-86
lines changed

11 files changed

+120
-86
lines changed

cli/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
985985
defer shutdownConns()
986986

987987
// Ensures that old database entries are cleaned up over time!
988-
purger := dbpurge.New(ctx, logger.Named("dbpurge"), options.Database)
988+
purger := dbpurge.New(ctx, logger.Named("dbpurge"), options.Database, quartz.NewReal())
989989
defer purger.Close()
990990

991991
// Updates workspace usage

coderd/database/dbauthz/dbauthz.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,11 +1144,11 @@ func (q *querier) DeleteOldProvisionerDaemons(ctx context.Context) error {
11441144
return q.db.DeleteOldProvisionerDaemons(ctx)
11451145
}
11461146

1147-
func (q *querier) DeleteOldWorkspaceAgentLogs(ctx context.Context) error {
1147+
func (q *querier) DeleteOldWorkspaceAgentLogs(ctx context.Context, threshold time.Time) error {
11481148
if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceSystem); err != nil {
11491149
return err
11501150
}
1151-
return q.db.DeleteOldWorkspaceAgentLogs(ctx)
1151+
return q.db.DeleteOldWorkspaceAgentLogs(ctx, threshold)
11521152
}
11531153

11541154
func (q *querier) DeleteOldWorkspaceAgentStats(ctx context.Context) error {

coderd/database/dbauthz/dbauthz_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2517,7 +2517,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
25172517
}).Asserts(rbac.ResourceSystem, policy.ActionCreate)
25182518
}))
25192519
s.Run("DeleteOldWorkspaceAgentLogs", s.Subtest(func(db database.Store, check *expects) {
2520-
check.Args().Asserts(rbac.ResourceSystem, policy.ActionDelete)
2520+
check.Args(time.Time{}).Asserts(rbac.ResourceSystem, policy.ActionDelete)
25212521
}))
25222522
s.Run("InsertWorkspaceAgentStats", s.Subtest(func(db database.Store, check *expects) {
25232523
check.Args(database.InsertWorkspaceAgentStatsParams{}).Asserts(rbac.ResourceSystem, policy.ActionCreate).Errors(errMatchAny)

coderd/database/dbmem/dbmem.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,19 +1706,15 @@ func (q *FakeQuerier) DeleteOldProvisionerDaemons(_ context.Context) error {
17061706
return nil
17071707
}
17081708

1709-
func (q *FakeQuerier) DeleteOldWorkspaceAgentLogs(_ context.Context) error {
1709+
func (q *FakeQuerier) DeleteOldWorkspaceAgentLogs(_ context.Context, threshold time.Time) error {
17101710
q.mutex.Lock()
17111711
defer q.mutex.Unlock()
17121712

1713-
now := dbtime.Now()
1714-
weekInterval := 7 * 24 * time.Hour
1715-
weekAgo := now.Add(-weekInterval)
1716-
17171713
var validLogs []database.WorkspaceAgentLog
17181714
for _, log := range q.workspaceAgentLogs {
17191715
var toBeDeleted bool
17201716
for _, agent := range q.workspaceAgents {
1721-
if agent.ID == log.AgentID && agent.LastConnectedAt.Valid && agent.LastConnectedAt.Time.Before(weekAgo) {
1717+
if agent.ID == log.AgentID && agent.LastConnectedAt.Valid && agent.LastConnectedAt.Time.Before(threshold) {
17221718
toBeDeleted = true
17231719
break
17241720
}

coderd/database/dbmetrics/dbmetrics.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbmock/dbmock.go

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbpurge/dbpurge.go

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,28 @@ import (
1111

1212
"github.com/coder/coder/v2/coderd/database"
1313
"github.com/coder/coder/v2/coderd/database/dbauthz"
14+
"github.com/coder/quartz"
1415
)
1516

1617
const (
17-
delay = 10 * time.Minute
18+
delay = 10 * time.Minute
19+
maxAgentLogAge = 7 * 24 * time.Hour
1820
)
1921

2022
// New creates a new periodically purging database instance.
2123
// It is the caller's responsibility to call Close on the returned instance.
2224
//
2325
// This is for cleaning up old, unused resources from the database that take up space.
24-
func New(ctx context.Context, logger slog.Logger, db database.Store) io.Closer {
26+
func New(ctx context.Context, logger slog.Logger, db database.Store, clk quartz.Clock) io.Closer {
2527
closed := make(chan struct{})
2628

2729
ctx, cancelFunc := context.WithCancel(ctx)
2830
//nolint:gocritic // The system purges old db records without user input.
2931
ctx = dbauthz.AsSystemRestricted(ctx)
3032

31-
// Use time.Nanosecond to force an initial tick. It will be reset to the
32-
// correct duration after executing once.
33-
ticker := time.NewTicker(time.Nanosecond)
34-
doTick := func() {
33+
ticker := clk.NewTicker(time.Nanosecond)
34+
doTick := func(start time.Time) {
3535
defer ticker.Reset(delay)
36-
37-
start := time.Now()
3836
// Start a transaction to grab advisory lock, we don't want to run
3937
// multiple purges at the same time (multiple replicas).
4038
if err := db.InTx(func(tx database.Store) error {
@@ -49,7 +47,7 @@ func New(ctx context.Context, logger slog.Logger, db database.Store) io.Closer {
4947
return nil
5048
}
5149

52-
if err := tx.DeleteOldWorkspaceAgentLogs(ctx); err != nil {
50+
if err := tx.DeleteOldWorkspaceAgentLogs(ctx, start.Add(-maxAgentLogAge)); err != nil {
5351
return xerrors.Errorf("failed to delete old workspace agent logs: %w", err)
5452
}
5553
if err := tx.DeleteOldWorkspaceAgentStats(ctx); err != nil {
@@ -62,7 +60,7 @@ func New(ctx context.Context, logger slog.Logger, db database.Store) io.Closer {
6260
return xerrors.Errorf("failed to delete old notification messages: %w", err)
6361
}
6462

65-
logger.Info(ctx, "purged old database entries", slog.F("duration", time.Since(start)))
63+
logger.Info(ctx, "purged old database entries", slog.F("duration", clk.Since(start)))
6664

6765
return nil
6866
}, nil); err != nil {
@@ -78,9 +76,9 @@ func New(ctx context.Context, logger slog.Logger, db database.Store) io.Closer {
7876
select {
7977
case <-ctx.Done():
8078
return
81-
case <-ticker.C:
79+
case tick := <-ticker.C:
8280
ticker.Stop()
83-
doTick()
81+
doTick(tick)
8482
}
8583
}
8684
}()

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