mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat(coderd): notify when workspace is marked as dormant (#13868)
This commit is contained in:
@@ -3555,12 +3555,15 @@ func (q *querier) UpdateWorkspaceTTL(ctx context.Context, arg database.UpdateWor
|
||||
return update(q.log, q.auth, fetch, q.db.UpdateWorkspaceTTL)(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) UpdateWorkspacesDormantDeletingAtByTemplateID(ctx context.Context, arg database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams) error {
|
||||
fetch := func(ctx context.Context, arg database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams) (database.Template, error) {
|
||||
return q.db.GetTemplateByID(ctx, arg.TemplateID)
|
||||
func (q *querier) UpdateWorkspacesDormantDeletingAtByTemplateID(ctx context.Context, arg database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]database.Workspace, error) {
|
||||
template, err := q.db.GetTemplateByID(ctx, arg.TemplateID)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("get template by id: %w", err)
|
||||
}
|
||||
|
||||
return fetchAndExec(q.log, q.auth, policy.ActionUpdate, fetch, q.db.UpdateWorkspacesDormantDeletingAtByTemplateID)(ctx, arg)
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, template); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return q.db.UpdateWorkspacesDormantDeletingAtByTemplateID(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) UpsertAnnouncementBanners(ctx context.Context, value string) error {
|
||||
|
||||
@@ -8700,15 +8700,16 @@ func (q *FakeQuerier) UpdateWorkspaceTTL(_ context.Context, arg database.UpdateW
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) UpdateWorkspacesDormantDeletingAtByTemplateID(_ context.Context, arg database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams) error {
|
||||
func (q *FakeQuerier) UpdateWorkspacesDormantDeletingAtByTemplateID(_ context.Context, arg database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]database.Workspace, error) {
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
err := validateDatabaseType(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
affectedRows := []database.Workspace{}
|
||||
for i, ws := range q.workspaces {
|
||||
if ws.TemplateID != arg.TemplateID {
|
||||
continue
|
||||
@@ -8733,9 +8734,10 @@ func (q *FakeQuerier) UpdateWorkspacesDormantDeletingAtByTemplateID(_ context.Co
|
||||
}
|
||||
ws.DeletingAt = deletingAt
|
||||
q.workspaces[i] = ws
|
||||
affectedRows = append(affectedRows, ws)
|
||||
}
|
||||
|
||||
return nil
|
||||
return affectedRows, nil
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) UpsertAnnouncementBanners(_ context.Context, data string) error {
|
||||
|
||||
@@ -2279,11 +2279,11 @@ func (m metricsStore) UpdateWorkspaceTTL(ctx context.Context, arg database.Updat
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m metricsStore) UpdateWorkspacesDormantDeletingAtByTemplateID(ctx context.Context, arg database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams) error {
|
||||
func (m metricsStore) UpdateWorkspacesDormantDeletingAtByTemplateID(ctx context.Context, arg database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]database.Workspace, error) {
|
||||
start := time.Now()
|
||||
r0 := m.s.UpdateWorkspacesDormantDeletingAtByTemplateID(ctx, arg)
|
||||
r0, r1 := m.s.UpdateWorkspacesDormantDeletingAtByTemplateID(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("UpdateWorkspacesDormantDeletingAtByTemplateID").Observe(time.Since(start).Seconds())
|
||||
return r0
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m metricsStore) UpsertAnnouncementBanners(ctx context.Context, value string) error {
|
||||
|
||||
@@ -4776,11 +4776,12 @@ func (mr *MockStoreMockRecorder) UpdateWorkspaceTTL(arg0, arg1 any) *gomock.Call
|
||||
}
|
||||
|
||||
// UpdateWorkspacesDormantDeletingAtByTemplateID mocks base method.
|
||||
func (m *MockStore) UpdateWorkspacesDormantDeletingAtByTemplateID(arg0 context.Context, arg1 database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams) error {
|
||||
func (m *MockStore) UpdateWorkspacesDormantDeletingAtByTemplateID(arg0 context.Context, arg1 database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]database.Workspace, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateWorkspacesDormantDeletingAtByTemplateID", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
ret0, _ := ret[0].([]database.Workspace)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// UpdateWorkspacesDormantDeletingAtByTemplateID indicates an expected call of UpdateWorkspacesDormantDeletingAtByTemplateID.
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
DELETE FROM notification_templates
|
||||
WHERE
|
||||
id = '0ea69165-ec14-4314-91f1-69566ac3c5a0';
|
||||
|
||||
DELETE FROM notification_templates
|
||||
WHERE
|
||||
id = '51ce2fdf-c9ca-4be1-8d70-628674f9bc42';
|
||||
@@ -0,0 +1,35 @@
|
||||
INSERT INTO
|
||||
notification_templates (
|
||||
id,
|
||||
name,
|
||||
title_template,
|
||||
body_template,
|
||||
"group",
|
||||
actions
|
||||
)
|
||||
VALUES (
|
||||
'0ea69165-ec14-4314-91f1-69566ac3c5a0',
|
||||
'Workspace Marked as Dormant',
|
||||
E'Workspace "{{.Labels.name}}" marked as dormant',
|
||||
E'Hi {{.UserName}}\n\n' || E'Your workspace **{{.Labels.name}}** has been marked as **dormant**.\n' || E'The specified reason was "**{{.Labels.reason}} (initiated by: {{ .Labels.initiator }}){{end}}**\n\n' || E'Dormancy refers to a workspace being unused for a defined length of time, and after it exceeds {{.Labels.dormancyHours}} hours of dormancy might be deleted.\n' || E'To activate your workspace again, simply use it as normal.',
|
||||
'Workspace Events',
|
||||
'[
|
||||
{
|
||||
"label": "View workspace",
|
||||
"url": "{{ base_url }}/@{{.UserName}}/{{.Labels.name}}"
|
||||
}
|
||||
]'::jsonb
|
||||
),
|
||||
(
|
||||
'51ce2fdf-c9ca-4be1-8d70-628674f9bc42',
|
||||
'Workspace Marked for Deletion',
|
||||
E'Workspace "{{.Labels.name}}" marked for deletion',
|
||||
E'Hi {{.UserName}}\n\n' || E'Your workspace **{{.Labels.name}}** has been marked for **deletion** after {{.Labels.dormancyHours}} hours of dormancy.\n' || E'The specified reason was "**{{.Labels.reason}}{{end}}**\n\n' || E'Dormancy refers to a workspace being unused for a defined length of time, and after it exceeds {{.Labels.dormancyHours}} hours of dormancy it will be deleted.\n' || E'To prevent your workspace from being deleted, simply use it as normal.',
|
||||
'Workspace Events',
|
||||
'[
|
||||
{
|
||||
"label": "View workspace",
|
||||
"url": "{{ base_url }}/@{{.UserName}}/{{.Labels.name}}"
|
||||
}
|
||||
]'::jsonb
|
||||
);
|
||||
@@ -448,7 +448,7 @@ type sqlcQuerier interface {
|
||||
UpdateWorkspaceProxy(ctx context.Context, arg UpdateWorkspaceProxyParams) (WorkspaceProxy, error)
|
||||
UpdateWorkspaceProxyDeleted(ctx context.Context, arg UpdateWorkspaceProxyDeletedParams) error
|
||||
UpdateWorkspaceTTL(ctx context.Context, arg UpdateWorkspaceTTLParams) error
|
||||
UpdateWorkspacesDormantDeletingAtByTemplateID(ctx context.Context, arg UpdateWorkspacesDormantDeletingAtByTemplateIDParams) error
|
||||
UpdateWorkspacesDormantDeletingAtByTemplateID(ctx context.Context, arg UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]Workspace, error)
|
||||
UpsertAnnouncementBanners(ctx context.Context, value string) error
|
||||
UpsertAppSecurityKey(ctx context.Context, value string) error
|
||||
UpsertApplicationName(ctx context.Context, value string) error
|
||||
|
||||
@@ -14082,7 +14082,7 @@ func (q *sqlQuerier) UpdateWorkspaceTTL(ctx context.Context, arg UpdateWorkspace
|
||||
return err
|
||||
}
|
||||
|
||||
const updateWorkspacesDormantDeletingAtByTemplateID = `-- name: UpdateWorkspacesDormantDeletingAtByTemplateID :exec
|
||||
const updateWorkspacesDormantDeletingAtByTemplateID = `-- name: UpdateWorkspacesDormantDeletingAtByTemplateID :many
|
||||
UPDATE workspaces
|
||||
SET
|
||||
deleting_at = CASE
|
||||
@@ -14095,6 +14095,7 @@ WHERE
|
||||
template_id = $3
|
||||
AND
|
||||
dormant_at IS NOT NULL
|
||||
RETURNING id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, dormant_at, deleting_at, automatic_updates, favorite
|
||||
`
|
||||
|
||||
type UpdateWorkspacesDormantDeletingAtByTemplateIDParams struct {
|
||||
@@ -14103,9 +14104,43 @@ type UpdateWorkspacesDormantDeletingAtByTemplateIDParams struct {
|
||||
TemplateID uuid.UUID `db:"template_id" json:"template_id"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) UpdateWorkspacesDormantDeletingAtByTemplateID(ctx context.Context, arg UpdateWorkspacesDormantDeletingAtByTemplateIDParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateWorkspacesDormantDeletingAtByTemplateID, arg.TimeTilDormantAutodeleteMs, arg.DormantAt, arg.TemplateID)
|
||||
return err
|
||||
func (q *sqlQuerier) UpdateWorkspacesDormantDeletingAtByTemplateID(ctx context.Context, arg UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]Workspace, error) {
|
||||
rows, err := q.db.QueryContext(ctx, updateWorkspacesDormantDeletingAtByTemplateID, arg.TimeTilDormantAutodeleteMs, arg.DormantAt, arg.TemplateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Workspace
|
||||
for rows.Next() {
|
||||
var i Workspace
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.OwnerID,
|
||||
&i.OrganizationID,
|
||||
&i.TemplateID,
|
||||
&i.Deleted,
|
||||
&i.Name,
|
||||
&i.AutostartSchedule,
|
||||
&i.Ttl,
|
||||
&i.LastUsedAt,
|
||||
&i.DormantAt,
|
||||
&i.DeletingAt,
|
||||
&i.AutomaticUpdates,
|
||||
&i.Favorite,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getWorkspaceAgentScriptsByAgentIDs = `-- name: GetWorkspaceAgentScriptsByAgentIDs :many
|
||||
|
||||
@@ -646,7 +646,7 @@ WHERE
|
||||
RETURNING
|
||||
workspaces.*;
|
||||
|
||||
-- name: UpdateWorkspacesDormantDeletingAtByTemplateID :exec
|
||||
-- name: UpdateWorkspacesDormantDeletingAtByTemplateID :many
|
||||
UPDATE workspaces
|
||||
SET
|
||||
deleting_at = CASE
|
||||
@@ -658,7 +658,8 @@ SET
|
||||
WHERE
|
||||
template_id = @template_id
|
||||
AND
|
||||
dormant_at IS NOT NULL;
|
||||
dormant_at IS NOT NULL
|
||||
RETURNING *;
|
||||
|
||||
-- name: UpdateTemplateWorkspacesLastUsedAt :exec
|
||||
UPDATE workspaces
|
||||
|
||||
Reference in New Issue
Block a user