Spike/222 workspace build order (#1534)

* chore: refactor before_id/after_id to build_number

Signed-off-by: Spike Curtis <spike@coder.com>

* pagination of workspace_builds

Signed-off-by: Spike Curtis <spike@coder.com>

* Disable parallel on postgres tests

Signed-off-by: Spike Curtis <spike@coder.com>

* Fix lint

Signed-off-by: Spike Curtis <spike@coder.com>

* Fix workspace build postgres query

Signed-off-by: Spike Curtis <spike@coder.com>

* Fix JS tests

Signed-off-by: Spike Curtis <spike@coder.com>

* Fix workspace builds postgres query

Signed-off-by: Spike Curtis <spike@coder.com>
This commit is contained in:
Spike Curtis
2022-05-18 16:33:33 +00:00
committed by GitHub
parent 13571b0393
commit 9f402fa27f
24 changed files with 410 additions and 239 deletions
+67 -18
View File
@@ -441,50 +441,100 @@ func (q *fakeQuerier) GetWorkspaceBuildByJobID(_ context.Context, jobID uuid.UUI
return database.WorkspaceBuild{}, sql.ErrNoRows
}
func (q *fakeQuerier) GetWorkspaceBuildByWorkspaceIDWithoutAfter(_ context.Context, workspaceID uuid.UUID) (database.WorkspaceBuild, error) {
func (q *fakeQuerier) GetLatestWorkspaceBuildByWorkspaceID(_ context.Context, workspaceID uuid.UUID) (database.WorkspaceBuild, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()
var row database.WorkspaceBuild
var buildNum int32
for _, workspaceBuild := range q.workspaceBuilds {
if workspaceBuild.WorkspaceID.String() != workspaceID.String() {
continue
}
if !workspaceBuild.AfterID.Valid {
return workspaceBuild, nil
if workspaceBuild.WorkspaceID.String() == workspaceID.String() && workspaceBuild.BuildNumber > buildNum {
row = workspaceBuild
buildNum = workspaceBuild.BuildNumber
}
}
return database.WorkspaceBuild{}, sql.ErrNoRows
if buildNum == 0 {
return database.WorkspaceBuild{}, sql.ErrNoRows
}
return row, nil
}
func (q *fakeQuerier) GetWorkspaceBuildsByWorkspaceIDsWithoutAfter(_ context.Context, ids []uuid.UUID) ([]database.WorkspaceBuild, error) {
func (q *fakeQuerier) GetLatestWorkspaceBuildsByWorkspaceIDs(_ context.Context, ids []uuid.UUID) ([]database.WorkspaceBuild, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()
builds := make([]database.WorkspaceBuild, 0)
builds := make(map[uuid.UUID]database.WorkspaceBuild)
buildNumbers := make(map[uuid.UUID]int32)
for _, workspaceBuild := range q.workspaceBuilds {
for _, id := range ids {
if id.String() != workspaceBuild.WorkspaceID.String() {
continue
if id.String() == workspaceBuild.WorkspaceID.String() && workspaceBuild.BuildNumber > buildNumbers[id] {
builds[id] = workspaceBuild
buildNumbers[id] = workspaceBuild.BuildNumber
}
builds = append(builds, workspaceBuild)
}
}
if len(builds) == 0 {
var returnBuilds []database.WorkspaceBuild
for i, n := range buildNumbers {
if n > 0 {
b := builds[i]
returnBuilds = append(returnBuilds, b)
}
}
if len(returnBuilds) == 0 {
return nil, sql.ErrNoRows
}
return builds, nil
return returnBuilds, nil
}
func (q *fakeQuerier) GetWorkspaceBuildByWorkspaceID(_ context.Context, workspaceID uuid.UUID) ([]database.WorkspaceBuild, error) {
func (q *fakeQuerier) GetWorkspaceBuildByWorkspaceID(_ context.Context,
params database.GetWorkspaceBuildByWorkspaceIDParams) ([]database.WorkspaceBuild, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()
history := make([]database.WorkspaceBuild, 0)
for _, workspaceBuild := range q.workspaceBuilds {
if workspaceBuild.WorkspaceID.String() == workspaceID.String() {
if workspaceBuild.WorkspaceID.String() == params.WorkspaceID.String() {
history = append(history, workspaceBuild)
}
}
// Order by build_number
slices.SortFunc(history, func(a, b database.WorkspaceBuild) bool {
// use greater than since we want descending order
return a.BuildNumber > b.BuildNumber
})
if params.AfterID != uuid.Nil {
found := false
for i, v := range history {
if v.ID == params.AfterID {
// We want to return all builds after index i.
history = history[i+1:]
found = true
break
}
}
// If no builds after the time, then we return an empty list.
if !found {
return nil, sql.ErrNoRows
}
}
if params.OffsetOpt > 0 {
if int(params.OffsetOpt) > len(history)-1 {
return nil, sql.ErrNoRows
}
history = history[params.OffsetOpt:]
}
if params.LimitOpt > 0 {
if int(params.LimitOpt) > len(history) {
params.LimitOpt = int32(len(history))
}
history = history[:params.LimitOpt]
}
if len(history) == 0 {
return nil, sql.ErrNoRows
}
@@ -1429,7 +1479,7 @@ func (q *fakeQuerier) InsertWorkspaceBuild(_ context.Context, arg database.Inser
WorkspaceID: arg.WorkspaceID,
Name: arg.Name,
TemplateVersionID: arg.TemplateVersionID,
BeforeID: arg.BeforeID,
BuildNumber: arg.BuildNumber,
Transition: arg.Transition,
InitiatorID: arg.InitiatorID,
JobID: arg.JobID,
@@ -1641,7 +1691,6 @@ func (q *fakeQuerier) UpdateWorkspaceBuildByID(_ context.Context, arg database.U
continue
}
workspaceBuild.UpdatedAt = arg.UpdatedAt
workspaceBuild.AfterID = arg.AfterID
workspaceBuild.ProvisionerState = arg.ProvisionerState
q.workspaceBuilds[index] = workspaceBuild
return nil
+4 -2
View File
@@ -288,8 +288,7 @@ CREATE TABLE workspace_builds (
workspace_id uuid NOT NULL,
template_version_id uuid NOT NULL,
name character varying(64) NOT NULL,
before_id uuid,
after_id uuid,
build_number integer NOT NULL,
transition workspace_transition NOT NULL,
initiator_id uuid NOT NULL,
provisioner_state bytea,
@@ -389,6 +388,9 @@ ALTER TABLE ONLY workspace_builds
ALTER TABLE ONLY workspace_builds
ADD CONSTRAINT workspace_builds_pkey PRIMARY KEY (id);
ALTER TABLE ONLY workspace_builds
ADD CONSTRAINT workspace_builds_workspace_id_build_number_key UNIQUE (workspace_id, build_number);
ALTER TABLE ONLY workspace_builds
ADD CONSTRAINT workspace_builds_workspace_id_name_key UNIQUE (workspace_id, name);
@@ -165,8 +165,7 @@ CREATE TABLE workspace_builds (
workspace_id uuid NOT NULL REFERENCES workspaces (id) ON DELETE CASCADE,
template_version_id uuid NOT NULL REFERENCES template_versions (id) ON DELETE CASCADE,
name varchar(64) NOT NULL,
before_id uuid,
after_id uuid,
build_number integer NOT NULL,
transition workspace_transition NOT NULL,
initiator_id uuid NOT NULL,
-- State stored by the provisioner
@@ -174,5 +173,6 @@ CREATE TABLE workspace_builds (
-- Job ID of the action
job_id uuid NOT NULL UNIQUE REFERENCES provisioner_jobs (id) ON DELETE CASCADE,
PRIMARY KEY (id),
UNIQUE(workspace_id, name)
UNIQUE(workspace_id, name),
UNIQUE(workspace_id, build_number)
);
+1 -2
View File
@@ -501,8 +501,7 @@ type WorkspaceBuild struct {
WorkspaceID uuid.UUID `db:"workspace_id" json:"workspace_id"`
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
Name string `db:"name" json:"name"`
BeforeID uuid.NullUUID `db:"before_id" json:"before_id"`
AfterID uuid.NullUUID `db:"after_id" json:"after_id"`
BuildNumber int32 `db:"build_number" json:"build_number"`
Transition WorkspaceTransition `db:"transition" json:"transition"`
InitiatorID uuid.UUID `db:"initiator_id" json:"initiator_id"`
ProvisionerState []byte `db:"provisioner_state" json:"provisioner_state"`
+3 -1
View File
@@ -17,8 +17,10 @@ func TestMain(m *testing.M) {
goleak.VerifyTestMain(m)
}
// nolint:paralleltest
func TestPostgres(t *testing.T) {
t.Parallel()
// postgres.Open() seems to be creating race conditions when run in parallel.
// t.Parallel()
if testing.Short() {
t.Skip()
+6 -2
View File
@@ -22,8 +22,10 @@ func TestPubsub(t *testing.T) {
return
}
// nolint:paralleltest
t.Run("Postgres", func(t *testing.T) {
t.Parallel()
// postgres.Open() seems to be creating race conditions when run in parallel.
// t.Parallel()
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()
@@ -52,8 +54,10 @@ func TestPubsub(t *testing.T) {
assert.Equal(t, string(message), data)
})
// nolint:paralleltest
t.Run("PostgresCloseCancel", func(t *testing.T) {
t.Parallel()
// postgres.Open() seems to be creating race conditions when run in parallel.
// t.Parallel()
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()
connectionURL, closePg, err := postgres.Open()
+3 -3
View File
@@ -27,6 +27,8 @@ type querier interface {
GetAuditLogsBefore(ctx context.Context, arg GetAuditLogsBeforeParams) ([]AuditLog, error)
GetFileByHash(ctx context.Context, hash string) (File, error)
GetGitSSHKey(ctx context.Context, userID uuid.UUID) (GitSSHKey, error)
GetLatestWorkspaceBuildByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) (WorkspaceBuild, error)
GetLatestWorkspaceBuildsByWorkspaceIDs(ctx context.Context, ids []uuid.UUID) ([]WorkspaceBuild, error)
GetOrganizationByID(ctx context.Context, id uuid.UUID) (Organization, error)
GetOrganizationByName(ctx context.Context, name string) (Organization, error)
GetOrganizationIDsByMemberIDs(ctx context.Context, ids []uuid.UUID) ([]GetOrganizationIDsByMemberIDsRow, error)
@@ -61,10 +63,8 @@ type querier interface {
GetWorkspaceAgentsByResourceIDs(ctx context.Context, ids []uuid.UUID) ([]WorkspaceAgent, error)
GetWorkspaceBuildByID(ctx context.Context, id uuid.UUID) (WorkspaceBuild, error)
GetWorkspaceBuildByJobID(ctx context.Context, jobID uuid.UUID) (WorkspaceBuild, error)
GetWorkspaceBuildByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) ([]WorkspaceBuild, error)
GetWorkspaceBuildByWorkspaceID(ctx context.Context, arg GetWorkspaceBuildByWorkspaceIDParams) ([]WorkspaceBuild, error)
GetWorkspaceBuildByWorkspaceIDAndName(ctx context.Context, arg GetWorkspaceBuildByWorkspaceIDAndNameParams) (WorkspaceBuild, error)
GetWorkspaceBuildByWorkspaceIDWithoutAfter(ctx context.Context, workspaceID uuid.UUID) (WorkspaceBuild, error)
GetWorkspaceBuildsByWorkspaceIDsWithoutAfter(ctx context.Context, ids []uuid.UUID) ([]WorkspaceBuild, error)
GetWorkspaceByID(ctx context.Context, id uuid.UUID) (Workspace, error)
GetWorkspaceByOwnerIDAndName(ctx context.Context, arg GetWorkspaceByOwnerIDAndNameParams) (Workspace, error)
GetWorkspaceOwnerCountsByTemplateIDs(ctx context.Context, ids []uuid.UUID) ([]GetWorkspaceOwnerCountsByTemplateIDsRow, error)
+141 -111
View File
@@ -2749,9 +2749,93 @@ func (q *sqlQuerier) UpdateWorkspaceAgentConnectionByID(ctx context.Context, arg
return err
}
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
FROM
workspace_builds
WHERE
workspace_id = $1
ORDER BY
build_number desc
LIMIT
1
`
func (q *sqlQuerier) GetLatestWorkspaceBuildByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) (WorkspaceBuild, error) {
row := q.db.QueryRowContext(ctx, getLatestWorkspaceBuildByWorkspaceID, workspaceID)
var i WorkspaceBuild
err := row.Scan(
&i.ID,
&i.CreatedAt,
&i.UpdatedAt,
&i.WorkspaceID,
&i.TemplateVersionID,
&i.Name,
&i.BuildNumber,
&i.Transition,
&i.InitiatorID,
&i.ProvisionerState,
&i.JobID,
)
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
FROM (
SELECT
workspace_id, MAX(build_number) as max_build_number
FROM
workspace_builds
WHERE
workspace_id = ANY($1 :: uuid [ ])
GROUP BY
workspace_id
) m
JOIN
workspace_builds wb
ON m.workspace_id = wb.workspace_id AND m.max_build_number = wb.build_number
`
func (q *sqlQuerier) GetLatestWorkspaceBuildsByWorkspaceIDs(ctx context.Context, ids []uuid.UUID) ([]WorkspaceBuild, error) {
rows, err := q.db.QueryContext(ctx, getLatestWorkspaceBuildsByWorkspaceIDs, pq.Array(ids))
if err != nil {
return nil, err
}
defer rows.Close()
var items []WorkspaceBuild
for rows.Next() {
var i WorkspaceBuild
if err := rows.Scan(
&i.ID,
&i.CreatedAt,
&i.UpdatedAt,
&i.WorkspaceID,
&i.TemplateVersionID,
&i.Name,
&i.BuildNumber,
&i.Transition,
&i.InitiatorID,
&i.ProvisionerState,
&i.JobID,
); 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 getWorkspaceBuildByID = `-- name: GetWorkspaceBuildByID :one
SELECT
id, created_at, updated_at, workspace_id, template_version_id, name, before_id, after_id, 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
FROM
workspace_builds
WHERE
@@ -2770,8 +2854,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByID(ctx context.Context, id uuid.UUID) (W
&i.WorkspaceID,
&i.TemplateVersionID,
&i.Name,
&i.BeforeID,
&i.AfterID,
&i.BuildNumber,
&i.Transition,
&i.InitiatorID,
&i.ProvisionerState,
@@ -2782,7 +2865,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByID(ctx context.Context, id uuid.UUID) (W
const getWorkspaceBuildByJobID = `-- name: GetWorkspaceBuildByJobID :one
SELECT
id, created_at, updated_at, workspace_id, template_version_id, name, before_id, after_id, 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
FROM
workspace_builds
WHERE
@@ -2801,8 +2884,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByJobID(ctx context.Context, jobID uuid.UU
&i.WorkspaceID,
&i.TemplateVersionID,
&i.Name,
&i.BeforeID,
&i.AfterID,
&i.BuildNumber,
&i.Transition,
&i.InitiatorID,
&i.ProvisionerState,
@@ -2813,15 +2895,51 @@ func (q *sqlQuerier) GetWorkspaceBuildByJobID(ctx context.Context, jobID uuid.UU
const getWorkspaceBuildByWorkspaceID = `-- name: GetWorkspaceBuildByWorkspaceID :many
SELECT
id, created_at, updated_at, workspace_id, template_version_id, name, before_id, after_id, 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
FROM
workspace_builds
WHERE
workspace_id = $1
workspace_builds.workspace_id = $1
AND CASE
-- This allows using the last element on a page as effectively a cursor.
-- This is an important option for scripts that need to paginate without
-- duplicating or missing data.
WHEN $2 :: uuid != '00000000-00000000-00000000-00000000' THEN (
-- The pagination cursor is the last ID of the previous page.
-- The query is ordered by the build_number field, so select all
-- rows after the cursor.
build_number > (
SELECT
build_number
FROM
workspace_builds
WHERE
id = $2
)
)
ELSE true
END
ORDER BY
build_number desc OFFSET $3
LIMIT
-- A null limit means "no limit", so -1 means return all
NULLIF($4 :: int, -1)
`
func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) ([]WorkspaceBuild, error) {
rows, err := q.db.QueryContext(ctx, getWorkspaceBuildByWorkspaceID, workspaceID)
type GetWorkspaceBuildByWorkspaceIDParams struct {
WorkspaceID uuid.UUID `db:"workspace_id" json:"workspace_id"`
AfterID uuid.UUID `db:"after_id" json:"after_id"`
OffsetOpt int32 `db:"offset_opt" json:"offset_opt"`
LimitOpt int32 `db:"limit_opt" json:"limit_opt"`
}
func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceID(ctx context.Context, arg GetWorkspaceBuildByWorkspaceIDParams) ([]WorkspaceBuild, error) {
rows, err := q.db.QueryContext(ctx, getWorkspaceBuildByWorkspaceID,
arg.WorkspaceID,
arg.AfterID,
arg.OffsetOpt,
arg.LimitOpt,
)
if err != nil {
return nil, err
}
@@ -2836,8 +2954,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceID(ctx context.Context, workspa
&i.WorkspaceID,
&i.TemplateVersionID,
&i.Name,
&i.BeforeID,
&i.AfterID,
&i.BuildNumber,
&i.Transition,
&i.InitiatorID,
&i.ProvisionerState,
@@ -2858,7 +2975,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceID(ctx context.Context, workspa
const getWorkspaceBuildByWorkspaceIDAndName = `-- name: GetWorkspaceBuildByWorkspaceIDAndName :one
SELECT
id, created_at, updated_at, workspace_id, template_version_id, name, before_id, after_id, 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
FROM
workspace_builds
WHERE
@@ -2881,8 +2998,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceIDAndName(ctx context.Context,
&i.WorkspaceID,
&i.TemplateVersionID,
&i.Name,
&i.BeforeID,
&i.AfterID,
&i.BuildNumber,
&i.Transition,
&i.InitiatorID,
&i.ProvisionerState,
@@ -2891,84 +3007,6 @@ func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceIDAndName(ctx context.Context,
return i, err
}
const getWorkspaceBuildByWorkspaceIDWithoutAfter = `-- name: GetWorkspaceBuildByWorkspaceIDWithoutAfter :one
SELECT
id, created_at, updated_at, workspace_id, template_version_id, name, before_id, after_id, transition, initiator_id, provisioner_state, job_id
FROM
workspace_builds
WHERE
workspace_id = $1
AND after_id IS NULL
LIMIT
1
`
func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceIDWithoutAfter(ctx context.Context, workspaceID uuid.UUID) (WorkspaceBuild, error) {
row := q.db.QueryRowContext(ctx, getWorkspaceBuildByWorkspaceIDWithoutAfter, workspaceID)
var i WorkspaceBuild
err := row.Scan(
&i.ID,
&i.CreatedAt,
&i.UpdatedAt,
&i.WorkspaceID,
&i.TemplateVersionID,
&i.Name,
&i.BeforeID,
&i.AfterID,
&i.Transition,
&i.InitiatorID,
&i.ProvisionerState,
&i.JobID,
)
return i, err
}
const getWorkspaceBuildsByWorkspaceIDsWithoutAfter = `-- name: GetWorkspaceBuildsByWorkspaceIDsWithoutAfter :many
SELECT
id, created_at, updated_at, workspace_id, template_version_id, name, before_id, after_id, transition, initiator_id, provisioner_state, job_id
FROM
workspace_builds
WHERE
workspace_id = ANY($1 :: uuid [ ])
AND after_id IS NULL
`
func (q *sqlQuerier) GetWorkspaceBuildsByWorkspaceIDsWithoutAfter(ctx context.Context, ids []uuid.UUID) ([]WorkspaceBuild, error) {
rows, err := q.db.QueryContext(ctx, getWorkspaceBuildsByWorkspaceIDsWithoutAfter, pq.Array(ids))
if err != nil {
return nil, err
}
defer rows.Close()
var items []WorkspaceBuild
for rows.Next() {
var i WorkspaceBuild
if err := rows.Scan(
&i.ID,
&i.CreatedAt,
&i.UpdatedAt,
&i.WorkspaceID,
&i.TemplateVersionID,
&i.Name,
&i.BeforeID,
&i.AfterID,
&i.Transition,
&i.InitiatorID,
&i.ProvisionerState,
&i.JobID,
); 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 insertWorkspaceBuild = `-- name: InsertWorkspaceBuild :one
INSERT INTO
workspace_builds (
@@ -2977,7 +3015,7 @@ INSERT INTO
updated_at,
workspace_id,
template_version_id,
before_id,
"build_number",
"name",
transition,
initiator_id,
@@ -2985,7 +3023,7 @@ INSERT INTO
provisioner_state
)
VALUES
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING id, created_at, updated_at, workspace_id, template_version_id, name, before_id, after_id, transition, initiator_id, provisioner_state, job_id
($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
`
type InsertWorkspaceBuildParams struct {
@@ -2994,7 +3032,7 @@ type InsertWorkspaceBuildParams struct {
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
WorkspaceID uuid.UUID `db:"workspace_id" json:"workspace_id"`
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
BeforeID uuid.NullUUID `db:"before_id" json:"before_id"`
BuildNumber int32 `db:"build_number" json:"build_number"`
Name string `db:"name" json:"name"`
Transition WorkspaceTransition `db:"transition" json:"transition"`
InitiatorID uuid.UUID `db:"initiator_id" json:"initiator_id"`
@@ -3009,7 +3047,7 @@ func (q *sqlQuerier) InsertWorkspaceBuild(ctx context.Context, arg InsertWorkspa
arg.UpdatedAt,
arg.WorkspaceID,
arg.TemplateVersionID,
arg.BeforeID,
arg.BuildNumber,
arg.Name,
arg.Transition,
arg.InitiatorID,
@@ -3024,8 +3062,7 @@ func (q *sqlQuerier) InsertWorkspaceBuild(ctx context.Context, arg InsertWorkspa
&i.WorkspaceID,
&i.TemplateVersionID,
&i.Name,
&i.BeforeID,
&i.AfterID,
&i.BuildNumber,
&i.Transition,
&i.InitiatorID,
&i.ProvisionerState,
@@ -3039,26 +3076,19 @@ UPDATE
workspace_builds
SET
updated_at = $2,
after_id = $3,
provisioner_state = $4
provisioner_state = $3
WHERE
id = $1
`
type UpdateWorkspaceBuildByIDParams struct {
ID uuid.UUID `db:"id" json:"id"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
AfterID uuid.NullUUID `db:"after_id" json:"after_id"`
ProvisionerState []byte `db:"provisioner_state" json:"provisioner_state"`
ID uuid.UUID `db:"id" json:"id"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
ProvisionerState []byte `db:"provisioner_state" json:"provisioner_state"`
}
func (q *sqlQuerier) UpdateWorkspaceBuildByID(ctx context.Context, arg UpdateWorkspaceBuildByIDParams) error {
_, err := q.db.ExecContext(ctx, updateWorkspaceBuildByID,
arg.ID,
arg.UpdatedAt,
arg.AfterID,
arg.ProvisionerState,
)
_, err := q.db.ExecContext(ctx, updateWorkspaceBuildByID, arg.ID, arg.UpdatedAt, arg.ProvisionerState)
return err
}
+46 -14
View File
@@ -33,27 +33,60 @@ SELECT
FROM
workspace_builds
WHERE
workspace_id = $1;
workspace_builds.workspace_id = $1
AND CASE
-- This allows using the last element on a page as effectively a cursor.
-- This is an important option for scripts that need to paginate without
-- duplicating or missing data.
WHEN @after_id :: uuid != '00000000-00000000-00000000-00000000' THEN (
-- The pagination cursor is the last ID of the previous page.
-- The query is ordered by the build_number field, so select all
-- rows after the cursor.
build_number > (
SELECT
build_number
FROM
workspace_builds
WHERE
id = @after_id
)
)
ELSE true
END
ORDER BY
build_number desc OFFSET @offset_opt
LIMIT
-- A null limit means "no limit", so -1 means return all
NULLIF(@limit_opt :: int, -1);
-- name: GetWorkspaceBuildByWorkspaceIDWithoutAfter :one
-- name: GetLatestWorkspaceBuildByWorkspaceID :one
SELECT
*
FROM
workspace_builds
WHERE
workspace_id = $1
AND after_id IS NULL
ORDER BY
build_number desc
LIMIT
1;
-- name: GetWorkspaceBuildsByWorkspaceIDsWithoutAfter :many
SELECT
*
FROM
workspace_builds
WHERE
workspace_id = ANY(@ids :: uuid [ ])
AND after_id IS NULL;
-- name: GetLatestWorkspaceBuildsByWorkspaceIDs :many
SELECT wb.*
FROM (
SELECT
workspace_id, MAX(build_number) as max_build_number
FROM
workspace_builds
WHERE
workspace_id = ANY(@ids :: uuid [ ])
GROUP BY
workspace_id
) m
JOIN
workspace_builds wb
ON m.workspace_id = wb.workspace_id AND m.max_build_number = wb.build_number;
-- name: InsertWorkspaceBuild :one
INSERT INTO
@@ -63,7 +96,7 @@ INSERT INTO
updated_at,
workspace_id,
template_version_id,
before_id,
"build_number",
"name",
transition,
initiator_id,
@@ -78,7 +111,6 @@ UPDATE
workspace_builds
SET
updated_at = $2,
after_id = $3,
provisioner_state = $4
provisioner_state = $3
WHERE
id = $1;