feat: add API/SDK support for autostop extension (#1778)

* Adds deadline column to workspace_builds, associated DB/API plumbing
* database: Upon inserting a row into workspace_builds, deadline will 
  initially be zero.
* autobuild: Executor now checks the Deadline field of the workspace_build
  for the purpose of autostop logic.
* coderd: Adds a new route /api/v2/workspaces/:workspace/extend which allows
  updating the deadline of the currently active workspace build. The new
  deadline must be after the existing deadline, and not the zero time.
* provisionerd: updates workspace_build.deadline upon successful workspace 
  build completion (equal to now plus workspace TTL, if it exists).
This commit is contained in:
Cian Johnston
2022-05-26 18:08:11 +01:00
committed by GitHub
parent c04d045279
commit 8f0a5a81f1
18 changed files with 306 additions and 34 deletions
@@ -1485,6 +1485,7 @@ func (q *fakeQuerier) InsertWorkspaceBuild(_ context.Context, arg database.Inser
InitiatorID: arg.InitiatorID,
JobID: arg.JobID,
ProvisionerState: arg.ProvisionerState,
Deadline: arg.Deadline,
}
q.workspaceBuilds = append(q.workspaceBuilds, workspaceBuild)
return workspaceBuild, nil
@@ -1693,6 +1694,7 @@ func (q *fakeQuerier) UpdateWorkspaceBuildByID(_ context.Context, arg database.U
}
workspaceBuild.UpdatedAt = arg.UpdatedAt
workspaceBuild.ProvisionerState = arg.ProvisionerState
workspaceBuild.Deadline = arg.Deadline
q.workspaceBuilds[index] = workspaceBuild
return nil
}
+2 -1
View File
@@ -291,7 +291,8 @@ CREATE TABLE workspace_builds (
transition workspace_transition NOT NULL,
initiator_id uuid NOT NULL,
provisioner_state bytea,
job_id uuid NOT NULL
job_id uuid NOT NULL,
deadline timestamp with time zone DEFAULT '0001-01-01 00:00:00+00'::timestamp with time zone NOT NULL
);
CREATE TABLE workspace_resources (
@@ -0,0 +1 @@
ALTER TABLE ONLY workspace_builds DROP COLUMN deadline;
@@ -0,0 +1 @@
ALTER TABLE ONLY workspace_builds ADD COLUMN deadline TIMESTAMPTZ NOT NULL DEFAULT TIMESTAMPTZ '0001-01-01 00:00:00+00:00';
+1
View File
@@ -505,6 +505,7 @@ type WorkspaceBuild struct {
InitiatorID uuid.UUID `db:"initiator_id" json:"initiator_id"`
ProvisionerState []byte `db:"provisioner_state" json:"provisioner_state"`
JobID uuid.UUID `db:"job_id" json:"job_id"`
Deadline time.Time `db:"deadline" json:"deadline"`
}
type WorkspaceResource struct {
+27 -10
View File
@@ -2745,7 +2745,7 @@ func (q *sqlQuerier) UpdateWorkspaceAgentConnectionByID(ctx context.Context, arg
const getLatestWorkspaceBuildByWorkspaceID = `-- name: GetLatestWorkspaceBuildByWorkspaceID :one
SELECT
id, created_at, updated_at, workspace_id, template_version_id, name, build_number, transition, initiator_id, provisioner_state, job_id
id, created_at, updated_at, workspace_id, template_version_id, name, build_number, transition, initiator_id, provisioner_state, job_id, deadline
FROM
workspace_builds
WHERE
@@ -2771,12 +2771,13 @@ func (q *sqlQuerier) GetLatestWorkspaceBuildByWorkspaceID(ctx context.Context, w
&i.InitiatorID,
&i.ProvisionerState,
&i.JobID,
&i.Deadline,
)
return i, err
}
const getLatestWorkspaceBuildsByWorkspaceIDs = `-- name: GetLatestWorkspaceBuildsByWorkspaceIDs :many
SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.name, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id
SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.name, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id, wb.deadline
FROM (
SELECT
workspace_id, MAX(build_number) as max_build_number
@@ -2813,6 +2814,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuildsByWorkspaceIDs(ctx context.Context,
&i.InitiatorID,
&i.ProvisionerState,
&i.JobID,
&i.Deadline,
); err != nil {
return nil, err
}
@@ -2829,7 +2831,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuildsByWorkspaceIDs(ctx context.Context,
const getWorkspaceBuildByID = `-- name: GetWorkspaceBuildByID :one
SELECT
id, created_at, updated_at, workspace_id, template_version_id, name, build_number, transition, initiator_id, provisioner_state, job_id
id, created_at, updated_at, workspace_id, template_version_id, name, build_number, transition, initiator_id, provisioner_state, job_id, deadline
FROM
workspace_builds
WHERE
@@ -2853,13 +2855,14 @@ func (q *sqlQuerier) GetWorkspaceBuildByID(ctx context.Context, id uuid.UUID) (W
&i.InitiatorID,
&i.ProvisionerState,
&i.JobID,
&i.Deadline,
)
return i, err
}
const getWorkspaceBuildByJobID = `-- name: GetWorkspaceBuildByJobID :one
SELECT
id, created_at, updated_at, workspace_id, template_version_id, name, build_number, transition, initiator_id, provisioner_state, job_id
id, created_at, updated_at, workspace_id, template_version_id, name, build_number, transition, initiator_id, provisioner_state, job_id, deadline
FROM
workspace_builds
WHERE
@@ -2883,13 +2886,14 @@ func (q *sqlQuerier) GetWorkspaceBuildByJobID(ctx context.Context, jobID uuid.UU
&i.InitiatorID,
&i.ProvisionerState,
&i.JobID,
&i.Deadline,
)
return i, err
}
const getWorkspaceBuildByWorkspaceID = `-- name: GetWorkspaceBuildByWorkspaceID :many
SELECT
id, created_at, updated_at, workspace_id, template_version_id, name, build_number, transition, initiator_id, provisioner_state, job_id
id, created_at, updated_at, workspace_id, template_version_id, name, build_number, transition, initiator_id, provisioner_state, job_id, deadline
FROM
workspace_builds
WHERE
@@ -2953,6 +2957,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceID(ctx context.Context, arg Get
&i.InitiatorID,
&i.ProvisionerState,
&i.JobID,
&i.Deadline,
); err != nil {
return nil, err
}
@@ -2969,7 +2974,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceID(ctx context.Context, arg Get
const getWorkspaceBuildByWorkspaceIDAndName = `-- name: GetWorkspaceBuildByWorkspaceIDAndName :one
SELECT
id, created_at, updated_at, workspace_id, template_version_id, name, build_number, transition, initiator_id, provisioner_state, job_id
id, created_at, updated_at, workspace_id, template_version_id, name, build_number, transition, initiator_id, provisioner_state, job_id, deadline
FROM
workspace_builds
WHERE
@@ -2997,6 +3002,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceIDAndName(ctx context.Context,
&i.InitiatorID,
&i.ProvisionerState,
&i.JobID,
&i.Deadline,
)
return i, err
}
@@ -3014,10 +3020,11 @@ INSERT INTO
transition,
initiator_id,
job_id,
provisioner_state
provisioner_state,
deadline
)
VALUES
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING id, created_at, updated_at, workspace_id, template_version_id, name, build_number, transition, initiator_id, provisioner_state, job_id
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) RETURNING id, created_at, updated_at, workspace_id, template_version_id, name, build_number, transition, initiator_id, provisioner_state, job_id, deadline
`
type InsertWorkspaceBuildParams struct {
@@ -3032,6 +3039,7 @@ type InsertWorkspaceBuildParams struct {
InitiatorID uuid.UUID `db:"initiator_id" json:"initiator_id"`
JobID uuid.UUID `db:"job_id" json:"job_id"`
ProvisionerState []byte `db:"provisioner_state" json:"provisioner_state"`
Deadline time.Time `db:"deadline" json:"deadline"`
}
func (q *sqlQuerier) InsertWorkspaceBuild(ctx context.Context, arg InsertWorkspaceBuildParams) (WorkspaceBuild, error) {
@@ -3047,6 +3055,7 @@ func (q *sqlQuerier) InsertWorkspaceBuild(ctx context.Context, arg InsertWorkspa
arg.InitiatorID,
arg.JobID,
arg.ProvisionerState,
arg.Deadline,
)
var i WorkspaceBuild
err := row.Scan(
@@ -3061,6 +3070,7 @@ func (q *sqlQuerier) InsertWorkspaceBuild(ctx context.Context, arg InsertWorkspa
&i.InitiatorID,
&i.ProvisionerState,
&i.JobID,
&i.Deadline,
)
return i, err
}
@@ -3070,7 +3080,8 @@ UPDATE
workspace_builds
SET
updated_at = $2,
provisioner_state = $3
provisioner_state = $3,
deadline = $4
WHERE
id = $1
`
@@ -3079,10 +3090,16 @@ type UpdateWorkspaceBuildByIDParams struct {
ID uuid.UUID `db:"id" json:"id"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
ProvisionerState []byte `db:"provisioner_state" json:"provisioner_state"`
Deadline time.Time `db:"deadline" json:"deadline"`
}
func (q *sqlQuerier) UpdateWorkspaceBuildByID(ctx context.Context, arg UpdateWorkspaceBuildByIDParams) error {
_, err := q.db.ExecContext(ctx, updateWorkspaceBuildByID, arg.ID, arg.UpdatedAt, arg.ProvisionerState)
_, err := q.db.ExecContext(ctx, updateWorkspaceBuildByID,
arg.ID,
arg.UpdatedAt,
arg.ProvisionerState,
arg.Deadline,
)
return err
}
+5 -3
View File
@@ -101,16 +101,18 @@ INSERT INTO
transition,
initiator_id,
job_id,
provisioner_state
provisioner_state,
deadline
)
VALUES
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING *;
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) RETURNING *;
-- name: UpdateWorkspaceBuildByID :exec
UPDATE
workspace_builds
SET
updated_at = $2,
provisioner_state = $3
provisioner_state = $3,
deadline = $4
WHERE
id = $1;