mirror of
https://github.com/coder/coder.git
synced 2025-07-06 15:41:45 +00:00
fix(coderd): workspaceapps: update last_used_at when workspace app reports stats (#11603)
- Adds a new query BatchUpdateLastUsedAt - Adds calls to BatchUpdateLastUsedAt in app stats handler upon flush - Passes a stats flush channel to apptest setup scaffolding and updates unit tests to assert modifications to LastUsedAt.
This commit is contained in:
@ -695,6 +695,15 @@ func (q *querier) ArchiveUnusedTemplateVersions(ctx context.Context, arg databas
|
||||
return q.db.ArchiveUnusedTemplateVersions(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) BatchUpdateWorkspaceLastUsedAt(ctx context.Context, arg database.BatchUpdateWorkspaceLastUsedAtParams) error {
|
||||
// Could be any workspace and checking auth to each workspace is overkill for the purpose
|
||||
// of this function.
|
||||
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceWorkspace.All()); err != nil {
|
||||
return err
|
||||
}
|
||||
return q.db.BatchUpdateWorkspaceLastUsedAt(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) CleanTailnetCoordinators(ctx context.Context) error {
|
||||
if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil {
|
||||
return err
|
||||
|
@ -1549,6 +1549,13 @@ func (s *MethodTestSuite) TestWorkspace() {
|
||||
ID: ws.ID,
|
||||
}).Asserts(ws, rbac.ActionUpdate).Returns()
|
||||
}))
|
||||
s.Run("BatchUpdateWorkspaceLastUsedAt", s.Subtest(func(db database.Store, check *expects) {
|
||||
ws1 := dbgen.Workspace(s.T(), db, database.Workspace{})
|
||||
ws2 := dbgen.Workspace(s.T(), db, database.Workspace{})
|
||||
check.Args(database.BatchUpdateWorkspaceLastUsedAtParams{
|
||||
IDs: []uuid.UUID{ws1.ID, ws2.ID},
|
||||
}).Asserts(rbac.ResourceWorkspace.All(), rbac.ActionUpdate).Returns()
|
||||
}))
|
||||
s.Run("UpdateWorkspaceTTL", s.Subtest(func(db database.Store, check *expects) {
|
||||
ws := dbgen.Workspace(s.T(), db, database.Workspace{})
|
||||
check.Args(database.UpdateWorkspaceTTLParams{
|
||||
|
@ -963,6 +963,31 @@ func (q *FakeQuerier) ArchiveUnusedTemplateVersions(_ context.Context, arg datab
|
||||
return archived, nil
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) BatchUpdateWorkspaceLastUsedAt(_ context.Context, arg database.BatchUpdateWorkspaceLastUsedAtParams) error {
|
||||
err := validateDatabaseType(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
// temporary map to avoid O(q.workspaces*arg.workspaceIds)
|
||||
m := make(map[uuid.UUID]struct{})
|
||||
for _, id := range arg.IDs {
|
||||
m[id] = struct{}{}
|
||||
}
|
||||
n := 0
|
||||
for i := 0; i < len(q.workspaces); i++ {
|
||||
if _, found := m[q.workspaces[i].ID]; !found {
|
||||
continue
|
||||
}
|
||||
q.workspaces[i].LastUsedAt = arg.LastUsedAt
|
||||
n++
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*FakeQuerier) CleanTailnetCoordinators(_ context.Context) error {
|
||||
return ErrUnimplemented
|
||||
}
|
||||
|
@ -114,6 +114,13 @@ func (m metricsStore) ArchiveUnusedTemplateVersions(ctx context.Context, arg dat
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m metricsStore) BatchUpdateWorkspaceLastUsedAt(ctx context.Context, arg database.BatchUpdateWorkspaceLastUsedAtParams) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.BatchUpdateWorkspaceLastUsedAt(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("BatchUpdateWorkspaceLastUsedAt").Observe(time.Since(start).Seconds())
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m metricsStore) CleanTailnetCoordinators(ctx context.Context) error {
|
||||
start := time.Now()
|
||||
err := m.s.CleanTailnetCoordinators(ctx)
|
||||
|
@ -117,6 +117,20 @@ func (mr *MockStoreMockRecorder) ArchiveUnusedTemplateVersions(arg0, arg1 any) *
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ArchiveUnusedTemplateVersions", reflect.TypeOf((*MockStore)(nil).ArchiveUnusedTemplateVersions), arg0, arg1)
|
||||
}
|
||||
|
||||
// BatchUpdateWorkspaceLastUsedAt mocks base method.
|
||||
func (m *MockStore) BatchUpdateWorkspaceLastUsedAt(arg0 context.Context, arg1 database.BatchUpdateWorkspaceLastUsedAtParams) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "BatchUpdateWorkspaceLastUsedAt", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// BatchUpdateWorkspaceLastUsedAt indicates an expected call of BatchUpdateWorkspaceLastUsedAt.
|
||||
func (mr *MockStoreMockRecorder) BatchUpdateWorkspaceLastUsedAt(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BatchUpdateWorkspaceLastUsedAt", reflect.TypeOf((*MockStore)(nil).BatchUpdateWorkspaceLastUsedAt), arg0, arg1)
|
||||
}
|
||||
|
||||
// CleanTailnetCoordinators mocks base method.
|
||||
func (m *MockStore) CleanTailnetCoordinators(arg0 context.Context) error {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -42,6 +42,7 @@ type sqlcQuerier interface {
|
||||
// Only unused template versions will be archived, which are any versions not
|
||||
// referenced by the latest build of a workspace.
|
||||
ArchiveUnusedTemplateVersions(ctx context.Context, arg ArchiveUnusedTemplateVersionsParams) ([]uuid.UUID, error)
|
||||
BatchUpdateWorkspaceLastUsedAt(ctx context.Context, arg BatchUpdateWorkspaceLastUsedAtParams) error
|
||||
CleanTailnetCoordinators(ctx context.Context) error
|
||||
CleanTailnetLostPeers(ctx context.Context) error
|
||||
CleanTailnetTunnels(ctx context.Context) error
|
||||
|
@ -10813,6 +10813,25 @@ func (q *sqlQuerier) InsertWorkspaceResourceMetadata(ctx context.Context, arg In
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const batchUpdateWorkspaceLastUsedAt = `-- name: BatchUpdateWorkspaceLastUsedAt :exec
|
||||
UPDATE
|
||||
workspaces
|
||||
SET
|
||||
last_used_at = $1
|
||||
WHERE
|
||||
id = ANY($2 :: uuid[])
|
||||
`
|
||||
|
||||
type BatchUpdateWorkspaceLastUsedAtParams struct {
|
||||
LastUsedAt time.Time `db:"last_used_at" json:"last_used_at"`
|
||||
IDs []uuid.UUID `db:"ids" json:"ids"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) BatchUpdateWorkspaceLastUsedAt(ctx context.Context, arg BatchUpdateWorkspaceLastUsedAtParams) error {
|
||||
_, err := q.db.ExecContext(ctx, batchUpdateWorkspaceLastUsedAt, arg.LastUsedAt, pq.Array(arg.IDs))
|
||||
return err
|
||||
}
|
||||
|
||||
const getDeploymentWorkspaceStats = `-- name: GetDeploymentWorkspaceStats :one
|
||||
WITH workspaces_with_jobs AS (
|
||||
SELECT
|
||||
|
@ -357,6 +357,14 @@ SET
|
||||
WHERE
|
||||
id = $1;
|
||||
|
||||
-- name: BatchUpdateWorkspaceLastUsedAt :exec
|
||||
UPDATE
|
||||
workspaces
|
||||
SET
|
||||
last_used_at = @last_used_at
|
||||
WHERE
|
||||
id = ANY(@ids :: uuid[]);
|
||||
|
||||
-- name: GetDeploymentWorkspaceStats :one
|
||||
WITH workspaces_with_jobs AS (
|
||||
SELECT
|
||||
|
Reference in New Issue
Block a user