Skip to content

Commit b47d076

Browse files
authored
feat: add deleting_at column to workspaces (#8333)
1 parent 0c73164 commit b47d076

22 files changed

+372
-161
lines changed

coderd/autobuild/lifecycle_executor.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ func (e *Executor) runOnce(t time.Time) Stats {
178178
// Lock the workspace if it has breached the template's
179179
// threshold for inactivity.
180180
if reason == database.BuildReasonAutolock {
181-
err = tx.UpdateWorkspaceLockedAt(e.ctx, database.UpdateWorkspaceLockedAtParams{
181+
err = tx.UpdateWorkspaceLockedDeletingAt(e.ctx, database.UpdateWorkspaceLockedDeletingAtParams{
182182
ID: ws.ID,
183183
LockedAt: sql.NullTime{
184184
Time: database.Now(),
@@ -347,11 +347,11 @@ func isEligibleForLockedStop(ws database.Workspace, templateSchedule schedule.Te
347347

348348
func isEligibleForDelete(ws database.Workspace, templateSchedule schedule.TemplateScheduleOptions, currentTick time.Time) bool {
349349
// Only attempt to delete locked workspaces.
350-
return ws.LockedAt.Valid &&
350+
return ws.LockedAt.Valid && ws.DeletingAt.Valid &&
351351
// Locked workspaces should only be deleted if a locked_ttl is specified.
352352
templateSchedule.LockedTTL > 0 &&
353353
// The workspace must breach the locked_ttl.
354-
currentTick.Sub(ws.LockedAt.Time) > templateSchedule.LockedTTL
354+
currentTick.After(ws.DeletingAt.Time)
355355
}
356356

357357
// isEligibleForFailedStop returns true if the workspace is eligible to be stopped

coderd/database/dbauthz/dbauthz.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,11 +2488,11 @@ func (q *querier) UpdateWorkspaceLastUsedAt(ctx context.Context, arg database.Up
24882488
return update(q.log, q.auth, fetch, q.db.UpdateWorkspaceLastUsedAt)(ctx, arg)
24892489
}
24902490

2491-
func (q *querier) UpdateWorkspaceLockedAt(ctx context.Context, arg database.UpdateWorkspaceLockedAtParams) error {
2492-
fetch := func(ctx context.Context, arg database.UpdateWorkspaceLockedAtParams) (database.Workspace, error) {
2491+
func (q *querier) UpdateWorkspaceLockedDeletingAt(ctx context.Context, arg database.UpdateWorkspaceLockedDeletingAtParams) error {
2492+
fetch := func(ctx context.Context, arg database.UpdateWorkspaceLockedDeletingAtParams) (database.Workspace, error) {
24932493
return q.db.GetWorkspaceByID(ctx, arg.ID)
24942494
}
2495-
return update(q.log, q.auth, fetch, q.db.UpdateWorkspaceLockedAt)(ctx, arg)
2495+
return update(q.log, q.auth, fetch, q.db.UpdateWorkspaceLockedDeletingAt)(ctx, arg)
24962496
}
24972497

24982498
func (q *querier) UpdateWorkspaceProxy(ctx context.Context, arg database.UpdateWorkspaceProxyParams) (database.WorkspaceProxy, error) {
@@ -2516,6 +2516,14 @@ func (q *querier) UpdateWorkspaceTTL(ctx context.Context, arg database.UpdateWor
25162516
return update(q.log, q.auth, fetch, q.db.UpdateWorkspaceTTL)(ctx, arg)
25172517
}
25182518

2519+
func (q *querier) UpdateWorkspacesDeletingAtByTemplateID(ctx context.Context, arg database.UpdateWorkspacesDeletingAtByTemplateIDParams) error {
2520+
fetch := func(ctx context.Context, arg database.UpdateWorkspacesDeletingAtByTemplateIDParams) (database.Template, error) {
2521+
return q.db.GetTemplateByID(ctx, arg.TemplateID)
2522+
}
2523+
2524+
return fetchAndExec(q.log, q.auth, rbac.ActionUpdate, fetch, q.db.UpdateWorkspacesDeletingAtByTemplateID)(ctx, arg)
2525+
}
2526+
25192527
func (q *querier) UpsertAppSecurityKey(ctx context.Context, data string) error {
25202528
// No authz checks as this is done during startup
25212529
return q.db.UpsertAppSecurityKey(ctx, data)

coderd/database/dbfake/dbfake.go

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,8 @@ func (q *FakeQuerier) convertToWorkspaceRowsNoLock(ctx context.Context, workspac
339339
AutostartSchedule: w.AutostartSchedule,
340340
Ttl: w.Ttl,
341341
LastUsedAt: w.LastUsedAt,
342+
LockedAt: w.LockedAt,
343+
DeletingAt: w.DeletingAt,
342344
Count: count,
343345
}
344346

@@ -4851,24 +4853,42 @@ func (q *FakeQuerier) UpdateWorkspaceLastUsedAt(_ context.Context, arg database.
48514853
return sql.ErrNoRows
48524854
}
48534855

4854-
func (q *FakeQuerier) UpdateWorkspaceLockedAt(_ context.Context, arg database.UpdateWorkspaceLockedAtParams) error {
4856+
func (q *FakeQuerier) UpdateWorkspaceLockedDeletingAt(_ context.Context, arg database.UpdateWorkspaceLockedDeletingAtParams) error {
48554857
if err := validateDatabaseType(arg); err != nil {
48564858
return err
48574859
}
4858-
48594860
q.mutex.Lock()
48604861
defer q.mutex.Unlock()
4861-
48624862
for index, workspace := range q.workspaces {
48634863
if workspace.ID != arg.ID {
48644864
continue
48654865
}
48664866
workspace.LockedAt = arg.LockedAt
4867-
workspace.LastUsedAt = database.Now()
4867+
if workspace.LockedAt.Time.IsZero() {
4868+
workspace.LastUsedAt = database.Now()
4869+
workspace.DeletingAt = sql.NullTime{}
4870+
}
4871+
if !workspace.LockedAt.Time.IsZero() {
4872+
var template database.TemplateTable
4873+
for _, t := range q.templates {
4874+
if t.ID == workspace.TemplateID {
4875+
template = t
4876+
break
4877+
}
4878+
}
4879+
if template.ID == uuid.Nil {
4880+
return xerrors.Errorf("unable to find workspace template")
4881+
}
4882+
if template.LockedTTL > 0 {
4883+
workspace.DeletingAt = sql.NullTime{
4884+
Valid: true,
4885+
Time: workspace.LockedAt.Time.Add(time.Duration(template.LockedTTL)),
4886+
}
4887+
}
4888+
}
48684889
q.workspaces[index] = workspace
48694890
return nil
48704891
}
4871-
48724892
return sql.ErrNoRows
48734893
}
48744894

@@ -4932,6 +4952,32 @@ func (q *FakeQuerier) UpdateWorkspaceTTL(_ context.Context, arg database.UpdateW
49324952
return sql.ErrNoRows
49334953
}
49344954

4955+
func (q *FakeQuerier) UpdateWorkspacesDeletingAtByTemplateID(_ context.Context, arg database.UpdateWorkspacesDeletingAtByTemplateIDParams) error {
4956+
q.mutex.Lock()
4957+
defer q.mutex.Unlock()
4958+
4959+
err := validateDatabaseType(arg)
4960+
if err != nil {
4961+
return err
4962+
}
4963+
4964+
for i, ws := range q.workspaces {
4965+
if ws.LockedAt.Time.IsZero() {
4966+
continue
4967+
}
4968+
deletingAt := sql.NullTime{
4969+
Valid: arg.LockedTtlMs > 0,
4970+
}
4971+
if arg.LockedTtlMs > 0 {
4972+
deletingAt.Time = ws.LockedAt.Time.Add(time.Duration(arg.LockedTtlMs) * time.Millisecond)
4973+
}
4974+
ws.DeletingAt = deletingAt
4975+
q.workspaces[i] = ws
4976+
}
4977+
4978+
return nil
4979+
}
4980+
49354981
func (q *FakeQuerier) UpsertAppSecurityKey(_ context.Context, data string) error {
49364982
q.mutex.Lock()
49374983
defer q.mutex.Unlock()

coderd/database/dbmetrics/dbmetrics.go

Lines changed: 10 additions & 3 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: 20 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dump.sql

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE workspaces DROP COLUMN deleting_at;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE workspaces ADD COLUMN deleting_at timestamptz NULL;

coderd/database/modelmethods.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,8 @@ func ConvertWorkspaceRows(rows []GetWorkspacesRow) []Workspace {
354354
AutostartSchedule: r.AutostartSchedule,
355355
Ttl: r.Ttl,
356356
LastUsedAt: r.LastUsedAt,
357+
LockedAt: r.LockedAt,
358+
DeletingAt: r.DeletingAt,
357359
}
358360
}
359361

coderd/database/modelqueries.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ func (q *sqlQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg GetWorkspa
240240
&i.Ttl,
241241
&i.LastUsedAt,
242242
&i.LockedAt,
243+
&i.DeletingAt,
243244
&i.TemplateName,
244245
&i.TemplateVersionID,
245246
&i.TemplateVersionName,

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