Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat: initiator_username joined to workspace_build queries #2137

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion coderd/autobuild/executor/lifecycle_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ func (e *Executor) runOnce(t time.Time) Stats {

// TODO(cian): this function duplicates most of api.postWorkspaceBuilds. Refactor.
// See: https://github.com/coder/coder/issues/1401
func build(ctx context.Context, store database.Store, workspace database.Workspace, trans database.WorkspaceTransition, priorHistory database.WorkspaceBuild, priorJob database.ProvisionerJob) error {
func build(ctx context.Context, store database.Store, workspace database.Workspace, trans database.WorkspaceTransition, priorHistory database.WorkspaceBuildWithInitiator, priorJob database.ProvisionerJob) error {
template, err := store.GetTemplateByID(ctx, workspace.TemplateID)
if err != nil {
return xerrors.Errorf("get workspace template: %w", err)
Expand Down
66 changes: 45 additions & 21 deletions coderd/database/databasefake/databasefake.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,63 +476,63 @@ func (q *fakeQuerier) GetWorkspaceOwnerCountsByTemplateIDs(_ context.Context, te
return res, nil
}

func (q *fakeQuerier) GetWorkspaceBuildByID(_ context.Context, id uuid.UUID) (database.WorkspaceBuild, error) {
func (q *fakeQuerier) GetWorkspaceBuildByID(_ context.Context, id uuid.UUID) (database.WorkspaceBuildWithInitiator, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()

for _, history := range q.workspaceBuilds {
if history.ID.String() == id.String() {
return history, nil
return q.workspaceBuildWithInitiator(history), nil
}
}
return database.WorkspaceBuild{}, sql.ErrNoRows
return database.WorkspaceBuildWithInitiator{}, sql.ErrNoRows
}

func (q *fakeQuerier) GetWorkspaceBuildByJobID(_ context.Context, jobID uuid.UUID) (database.WorkspaceBuild, error) {
func (q *fakeQuerier) GetWorkspaceBuildByJobID(_ context.Context, jobID uuid.UUID) (database.WorkspaceBuildWithInitiator, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()

for _, build := range q.workspaceBuilds {
if build.JobID.String() == jobID.String() {
return build, nil
return q.workspaceBuildWithInitiator(build), nil
}
}
return database.WorkspaceBuild{}, sql.ErrNoRows
return database.WorkspaceBuildWithInitiator{}, sql.ErrNoRows
}

func (q *fakeQuerier) GetLatestWorkspaceBuildByWorkspaceID(_ context.Context, workspaceID uuid.UUID) (database.WorkspaceBuild, error) {
func (q *fakeQuerier) GetLatestWorkspaceBuildByWorkspaceID(_ context.Context, workspaceID uuid.UUID) (database.WorkspaceBuildWithInitiator, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()

var row database.WorkspaceBuild
var row database.WorkspaceBuildWithInitiator
var buildNum int32
for _, workspaceBuild := range q.workspaceBuilds {
if workspaceBuild.WorkspaceID.String() == workspaceID.String() && workspaceBuild.BuildNumber > buildNum {
row = workspaceBuild
row = q.workspaceBuildWithInitiator(workspaceBuild)
buildNum = workspaceBuild.BuildNumber
}
}
if buildNum == 0 {
return database.WorkspaceBuild{}, sql.ErrNoRows
return database.WorkspaceBuildWithInitiator{}, sql.ErrNoRows
}
return row, nil
}

func (q *fakeQuerier) GetLatestWorkspaceBuildsByWorkspaceIDs(_ context.Context, ids []uuid.UUID) ([]database.WorkspaceBuild, error) {
func (q *fakeQuerier) GetLatestWorkspaceBuildsByWorkspaceIDs(_ context.Context, ids []uuid.UUID) ([]database.WorkspaceBuildWithInitiator, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()

builds := make(map[uuid.UUID]database.WorkspaceBuild)
builds := make(map[uuid.UUID]database.WorkspaceBuildWithInitiator)
buildNumbers := make(map[uuid.UUID]int32)
for _, workspaceBuild := range q.workspaceBuilds {
for _, id := range ids {
if id.String() == workspaceBuild.WorkspaceID.String() && workspaceBuild.BuildNumber > buildNumbers[id] {
builds[id] = workspaceBuild
builds[id] = q.workspaceBuildWithInitiator(workspaceBuild)
buildNumbers[id] = workspaceBuild.BuildNumber
}
}
}
var returnBuilds []database.WorkspaceBuild
var returnBuilds []database.WorkspaceBuildWithInitiator
for i, n := range buildNumbers {
if n > 0 {
b := builds[i]
Expand All @@ -546,19 +546,19 @@ func (q *fakeQuerier) GetLatestWorkspaceBuildsByWorkspaceIDs(_ context.Context,
}

func (q *fakeQuerier) GetWorkspaceBuildByWorkspaceID(_ context.Context,
params database.GetWorkspaceBuildByWorkspaceIDParams) ([]database.WorkspaceBuild, error) {
params database.GetWorkspaceBuildByWorkspaceIDParams) ([]database.WorkspaceBuildWithInitiator, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()

history := make([]database.WorkspaceBuild, 0)
history := make([]database.WorkspaceBuildWithInitiator, 0)
for _, workspaceBuild := range q.workspaceBuilds {
if workspaceBuild.WorkspaceID.String() == params.WorkspaceID.String() {
history = append(history, workspaceBuild)
history = append(history, q.workspaceBuildWithInitiator(workspaceBuild))
}
}

// Order by build_number
slices.SortFunc(history, func(a, b database.WorkspaceBuild) bool {
slices.SortFunc(history, func(a, b database.WorkspaceBuildWithInitiator) bool {
// use greater than since we want descending order
return a.BuildNumber > b.BuildNumber
})
Expand Down Expand Up @@ -600,7 +600,7 @@ func (q *fakeQuerier) GetWorkspaceBuildByWorkspaceID(_ context.Context,
return history, nil
}

func (q *fakeQuerier) GetWorkspaceBuildByWorkspaceIDAndName(_ context.Context, arg database.GetWorkspaceBuildByWorkspaceIDAndNameParams) (database.WorkspaceBuild, error) {
func (q *fakeQuerier) GetWorkspaceBuildByWorkspaceIDAndName(_ context.Context, arg database.GetWorkspaceBuildByWorkspaceIDAndNameParams) (database.WorkspaceBuildWithInitiator, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()

Expand All @@ -611,9 +611,33 @@ func (q *fakeQuerier) GetWorkspaceBuildByWorkspaceIDAndName(_ context.Context, a
if !strings.EqualFold(workspaceBuild.Name, arg.Name) {
continue
}
return workspaceBuild, nil

return q.workspaceBuildWithInitiator(workspaceBuild), nil
}
return database.WorkspaceBuildWithInitiator{}, sql.ErrNoRows
}

func (q *fakeQuerier) workspaceBuildWithInitiator(build database.WorkspaceBuild) database.WorkspaceBuildWithInitiator {
username := "unknown"
usr, err := q.GetUserByID(context.Background(), build.InitiatorID)
if err == nil {
username = usr.Username
}
return database.WorkspaceBuildWithInitiator{
ID: build.ID,
CreatedAt: build.CreatedAt,
UpdatedAt: build.UpdatedAt,
WorkspaceID: build.WorkspaceID,
TemplateVersionID: build.TemplateVersionID,
Name: build.Name,
BuildNumber: build.BuildNumber,
Transition: build.Transition,
InitiatorID: build.InitiatorID,
ProvisionerState: build.ProvisionerState,
JobID: build.JobID,
Deadline: build.Deadline,
InitiatorUsername: username,
}
return database.WorkspaceBuild{}, sql.ErrNoRows
}

func (q *fakeQuerier) GetWorkspacesByOrganizationIDs(_ context.Context, req database.GetWorkspacesByOrganizationIDsParams) ([]database.Workspace, error) {
Expand Down
17 changes: 17 additions & 0 deletions coderd/database/dump.sql

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP VIEW IF EXISTS workspace_build_with_initiator;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-- This view adds the initiator name to the query for UI purposes.
-- Showing the initiator user ID is not very friendly.
CREATE VIEW workspace_build_with_initiator AS
-- If the user is nil, just use 'unknown' for now.
SELECT workspace_builds.*, coalesce(users.username, 'unknown') AS initiator_username
FROM workspace_builds
LEFT JOIN users ON workspace_builds.initiator_id = users.id;
Comment on lines +1 to +7
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this require adding a migration every time we want to change the query?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kylecarbs yes. Another migration will drop the old view and make a new one.

If we change the columns, it will be required too as the dump.sql expands *. I just realized that 🤔

Copy link
Member Author

@Emyrk Emyrk Jun 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless we implement something else to "migrate" views.

A view is a saved query on the database. The alternative is to use temporary views which only last for a single "session". So this alternative thing to "migrate" views could be a set of temporary views we initiate when we open a SQL connection. (maybe, brainstorming here, I think that would work) With connection pooling this might not work.

16 changes: 16 additions & 0 deletions coderd/database/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions coderd/database/querier.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading