Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5a0b15d

Browse files
committed
Periodically purge old database entries
1 parent 45c0aca commit 5a0b15d

File tree

9 files changed

+124
-5
lines changed

9 files changed

+124
-5
lines changed

cli/server.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ import (
6565
"github.com/coder/coder/coderd/autobuild/executor"
6666
"github.com/coder/coder/coderd/database"
6767
"github.com/coder/coder/coderd/database/dbfake"
68+
"github.com/coder/coder/coderd/database/dbpurge"
6869
"github.com/coder/coder/coderd/database/migrations"
6970
"github.com/coder/coder/coderd/devtunnel"
7071
"github.com/coder/coder/coderd/gitauth"
@@ -993,6 +994,10 @@ flags, and YAML configuration. The precedence is as follows:
993994
shutdownConnsCtx, shutdownConns := context.WithCancel(ctx)
994995
defer shutdownConns()
995996

997+
// Ensures that old database entries are cleaned up over time!
998+
purger := dbpurge.New(ctx, logger, options.Database)
999+
defer purger.Close()
1000+
9961001
// Wrap the server in middleware that redirects to the access URL if
9971002
// the request is not to a local IP.
9981003
var handler http.Handler = coderAPI.RootHandler

coderd/database/dbauthz/system.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,13 @@ func (q *querier) DeleteOldWorkspaceAgentStats(ctx context.Context) error {
280280
return q.db.DeleteOldWorkspaceAgentStats(ctx)
281281
}
282282

283+
func (q *querier) DeleteOldWorkspaceAgentStartupLogs(ctx context.Context) error {
284+
if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceSystem); err != nil {
285+
return err
286+
}
287+
return q.db.DeleteOldWorkspaceAgentStartupLogs(ctx)
288+
}
289+
283290
func (q *querier) GetDeploymentWorkspaceAgentStats(ctx context.Context, createdAfter time.Time) (database.GetDeploymentWorkspaceAgentStatsRow, error) {
284291
return q.db.GetDeploymentWorkspaceAgentStats(ctx, createdAfter)
285292
}

coderd/database/dbfake/databasefake.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4387,6 +4387,11 @@ func (q *fakeQuerier) DeleteLicense(_ context.Context, id int32) (int32, error)
43874387
return 0, sql.ErrNoRows
43884388
}
43894389

4390+
func (*fakeQuerier) DeleteOldWorkspaceAgentStartupLogs(_ context.Context) error {
4391+
// noop
4392+
return nil
4393+
}
4394+
43904395
func (q *fakeQuerier) GetUserLinkByLinkedID(_ context.Context, id string) (database.UserLink, error) {
43914396
q.mutex.RLock()
43924397
defer q.mutex.RUnlock()

coderd/database/dbpurge/dbpurge.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package dbpurge
2+
3+
import (
4+
"context"
5+
"errors"
6+
"io"
7+
"time"
8+
9+
"golang.org/x/sync/errgroup"
10+
11+
"cdr.dev/slog"
12+
"github.com/coder/coder/coderd/database"
13+
)
14+
15+
// New creates a new periodically purging database instance.
16+
// It is the caller's responsibility to call Close on the returned instance.
17+
//
18+
// This is for cleaning up old, unused resources from the database that take up space.
19+
func New(ctx context.Context, logger slog.Logger, db database.Store) io.Closer {
20+
closed := make(chan struct{})
21+
ctx, cancelFunc := context.WithCancel(ctx)
22+
go func() {
23+
defer close(closed)
24+
ticker := time.NewTicker(24 * time.Hour)
25+
defer ticker.Stop()
26+
for {
27+
select {
28+
case <-ctx.Done():
29+
return
30+
case <-ticker.C:
31+
}
32+
33+
var eg errgroup.Group
34+
eg.Go(func() error {
35+
return db.DeleteOldWorkspaceAgentStartupLogs(ctx)
36+
})
37+
eg.Go(func() error {
38+
return db.DeleteOldWorkspaceAgentStats(ctx)
39+
})
40+
err := eg.Wait()
41+
if err != nil {
42+
if errors.Is(err, context.Canceled) {
43+
return
44+
}
45+
logger.Error(ctx, "failed to purge old database entries", slog.Error(err))
46+
}
47+
}
48+
}()
49+
return &instance{
50+
cancel: cancelFunc,
51+
closed: closed,
52+
}
53+
}
54+
55+
type instance struct {
56+
cancel context.CancelFunc
57+
closed chan struct{}
58+
}
59+
60+
func (i *instance) Close() error {
61+
i.cancel()
62+
<-i.closed
63+
return nil
64+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package dbpurge_test
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"go.uber.org/goleak"
8+
9+
"github.com/stretchr/testify/require"
10+
11+
"cdr.dev/slog/sloggers/slogtest"
12+
"github.com/coder/coder/coderd/database/dbfake"
13+
"github.com/coder/coder/coderd/database/dbpurge"
14+
)
15+
16+
func TestMain(m *testing.M) {
17+
goleak.VerifyTestMain(m)
18+
}
19+
20+
// Ensures no goroutines leak.
21+
func TestPurge(t *testing.T) {
22+
t.Parallel()
23+
purger := dbpurge.New(context.Background(), slogtest.Make(t, nil), dbfake.New())
24+
err := purger.Close()
25+
require.NoError(t, err)
26+
}

coderd/database/querier.go

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

coderd/database/queries.sql.go

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

coderd/database/queries/workspaceagents.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ INSERT INTO
128128

129129
-- If an agent hasn't connected in the last 7 days, we purge it's logs.
130130
-- Logs can take up a lot of space, so it's important we clean up frequently.
131+
-- name: DeleteOldWorkspaceAgentStartupLogs :exec
131132
DELETE FROM workspace_agent_startup_logs WHERE agent_id IN
132133
(SELECT id FROM workspace_agents WHERE last_connected_at IS NOT NULL
133134
AND last_connected_at < NOW() - INTERVAL '7 day');

coderd/metricscache/metricscache.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99

1010
"golang.org/x/exp/maps"
1111
"golang.org/x/exp/slices"
12-
"golang.org/x/xerrors"
1312

1413
"github.com/google/uuid"
1514

@@ -168,10 +167,6 @@ func countUniqueUsers(rows []database.GetTemplateDAUsRow) int {
168167
func (c *Cache) refreshTemplateDAUs(ctx context.Context) error {
169168
//nolint:gocritic // This is a system service.
170169
ctx = dbauthz.AsSystemRestricted(ctx)
171-
err := c.database.DeleteOldWorkspaceAgentStats(ctx)
172-
if err != nil {
173-
return xerrors.Errorf("delete old stats: %w", err)
174-
}
175170

176171
templates, err := c.database.GetTemplates(ctx)
177172
if err != nil {

0 commit comments

Comments
 (0)