Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit45354cc

Browse files
committed
Allow partial app status updates
Since we will be sending status updates without messages on an interval,we need to prevent duplicates and preserve the previous message.Also, I think this makes the endpoint more in alignment with PATCHsemantics.
1 parentd6d329d commit45354cc

File tree

9 files changed

+173
-1
lines changed

9 files changed

+173
-1
lines changed

‎coderd/database/dbauthz/dbauthz.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,6 +1991,13 @@ func (q *querier) GetLatestCryptoKeyByFeature(ctx context.Context, feature datab
19911991
returnq.db.GetLatestCryptoKeyByFeature(ctx,feature)
19921992
}
19931993

1994+
func (q*querier)GetLatestWorkspaceAppStatusByAppID(ctx context.Context,appID uuid.UUID) (database.WorkspaceAppStatus,error) {
1995+
iferr:=q.authorizeContext(ctx,policy.ActionRead,rbac.ResourceSystem);err!=nil {
1996+
return database.WorkspaceAppStatus{},err
1997+
}
1998+
returnq.db.GetLatestWorkspaceAppStatusByAppID(ctx,appID)
1999+
}
2000+
19942001
func (q*querier)GetLatestWorkspaceAppStatusesByWorkspaceIDs(ctx context.Context,ids []uuid.UUID) ([]database.WorkspaceAppStatus,error) {
19952002
iferr:=q.authorizeContext(ctx,policy.ActionRead,rbac.ResourceSystem);err!=nil {
19962003
returnnil,err

‎coderd/database/dbmem/dbmem.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3777,6 +3777,22 @@ func (q *FakeQuerier) GetLatestCryptoKeyByFeature(_ context.Context, feature dat
37773777
returnlatestKey,nil
37783778
}
37793779

3780+
func (q*FakeQuerier)GetLatestWorkspaceAppStatusByAppID(ctx context.Context,appID uuid.UUID) (database.WorkspaceAppStatus,error) {
3781+
q.mutex.RLock()
3782+
deferq.mutex.RUnlock()
3783+
3784+
varcurrent*database.WorkspaceAppStatus=nil
3785+
for_,appStatus:=rangeq.workspaceAppStatuses {
3786+
ifappStatus.AppID==appID&& (current==nil||appStatus.CreatedAt.After(current.CreatedAt)) {
3787+
current=&appStatus
3788+
}
3789+
}
3790+
ifcurrent==nil {
3791+
return database.WorkspaceAppStatus{},sql.ErrNoRows
3792+
}
3793+
return*current,nil
3794+
}
3795+
37803796
func (q*FakeQuerier)GetLatestWorkspaceAppStatusesByWorkspaceIDs(_ context.Context,ids []uuid.UUID) ([]database.WorkspaceAppStatus,error) {
37813797
q.mutex.RLock()
37823798
deferq.mutex.RUnlock()

‎coderd/database/dbmetrics/querymetrics.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/dbmock/dbmock.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/querier.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/queries.sql.go

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/queries/workspaceapps.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,7 @@ SELECT DISTINCT ON (workspace_id)
5858
FROM workspace_app_statuses
5959
WHERE workspace_id= ANY(@ids :: uuid[])
6060
ORDER BY workspace_id, created_atDESC;
61+
62+
-- name: GetLatestWorkspaceAppStatusByAppID :one
63+
SELECT*FROM workspace_app_statusesWHERE app_id= $1
64+
ORDER BY created_atDESCLIMIT1;

‎coderd/workspaceagents.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,14 +380,40 @@ func (api *API) patchWorkspaceAgentAppStatus(rw http.ResponseWriter, r *http.Req
380380
return
381381
}
382382

383+
// nolint:gocritic // This is a system restricted operation.
384+
status,err:=api.Database.GetLatestWorkspaceAppStatusByAppID(dbauthz.AsSystemRestricted(ctx),app.ID)
385+
iferr!=nil&&!errors.Is(err,sql.ErrNoRows) {
386+
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
387+
Message:"Internal error fetching workspace app statuses.",
388+
Detail:err.Error(),
389+
})
390+
return
391+
}
392+
// Preserve the existing message, which allows partial updates where we change
393+
// the status but keep the message.
394+
ifreq.Message=="" {
395+
req.Message=status.Message
396+
// Only preserve the URI if there was no message. If there is a message and
397+
// a blank URI, we assume the intent is to remove the URI, not preserve it.
398+
ifreq.URI=="" {
399+
req.URI=status.Uri.String
400+
}
401+
}
402+
// Skip duplicate status updates.
403+
newState:=database.WorkspaceAppStatusState(req.State)
404+
ifstatus.State==newState&&status.Message==req.Message&&status.Uri.String==req.URI {
405+
httpapi.Write(ctx,rw,http.StatusOK,nil)
406+
return
407+
}
408+
383409
// nolint:gocritic // This is a system restricted operation.
384410
_,err=api.Database.InsertWorkspaceAppStatus(dbauthz.AsSystemRestricted(ctx), database.InsertWorkspaceAppStatusParams{
385411
ID:uuid.New(),
386412
CreatedAt:dbtime.Now(),
387413
WorkspaceID:workspace.ID,
388414
AgentID:workspaceAgent.ID,
389415
AppID:app.ID,
390-
State:database.WorkspaceAppStatusState(req.State),
416+
State:newState,
391417
Message:req.Message,
392418
Uri: sql.NullString{
393419
String:req.URI,

‎coderd/workspaceagents_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,81 @@ func TestWorkspaceAgentAppStatus(t *testing.T) {
387387
require.False(t,agent.Apps[0].Statuses[0].NeedsUserAttention)
388388
})
389389

390+
t.Run("Patch",func(t*testing.T) {
391+
t.Parallel()
392+
ctx:=testutil.Context(t,testutil.WaitShort)
393+
394+
ws:=dbfake.WorkspaceBuild(t,db, database.WorkspaceTable{
395+
OrganizationID:user.OrganizationID,
396+
OwnerID:user2.ID,
397+
}).WithAgent(func(a []*proto.Agent) []*proto.Agent {
398+
a[0].Apps= []*proto.App{
399+
{
400+
Slug:"vscode",
401+
},
402+
}
403+
returna
404+
}).Do()
405+
406+
agentClient:=agentsdk.New(client.URL)
407+
agentClient.SetSessionToken(ws.AgentToken)
408+
409+
err:=agentClient.PatchAppStatus(ctx, agentsdk.PatchAppStatus{
410+
AppSlug:"vscode",
411+
Message:"testing",
412+
URI:"https://example.com",
413+
State:codersdk.WorkspaceAppStatusStateComplete,
414+
})
415+
require.NoError(t,err)
416+
417+
// Duplicate should be a no-op.
418+
err=agentClient.PatchAppStatus(ctx, agentsdk.PatchAppStatus{
419+
AppSlug:"vscode",
420+
Message:"testing",
421+
URI:"https://example.com",
422+
State:codersdk.WorkspaceAppStatusStateComplete,
423+
})
424+
require.NoError(t,err)
425+
426+
// If no message, both the old message and URI are preserved, and this ends
427+
// up being a duplicate as well.
428+
err=agentClient.PatchAppStatus(ctx, agentsdk.PatchAppStatus{
429+
AppSlug:"vscode",
430+
State:codersdk.WorkspaceAppStatusStateComplete,
431+
})
432+
require.NoError(t,err)
433+
434+
// Same, but the status updated so it will not be a duplicate.
435+
err=agentClient.PatchAppStatus(ctx, agentsdk.PatchAppStatus{
436+
AppSlug:"vscode",
437+
State:codersdk.WorkspaceAppStatusStateWorking,
438+
})
439+
require.NoError(t,err)
440+
441+
// Message update, so nothing is preserved.
442+
err=agentClient.PatchAppStatus(ctx, agentsdk.PatchAppStatus{
443+
AppSlug:"vscode",
444+
Message:"updated",
445+
State:codersdk.WorkspaceAppStatusStateWorking,
446+
})
447+
require.NoError(t,err)
448+
449+
workspace,err:=client.Workspace(ctx,ws.Workspace.ID)
450+
require.NoError(t,err)
451+
agent,err:=client.WorkspaceAgent(ctx,workspace.LatestBuild.Resources[0].Agents[0].ID)
452+
require.NoError(t,err)
453+
require.Len(t,agent.Apps[0].Statuses,3)
454+
require.Equal(t,agent.Apps[0].Statuses[0].State,codersdk.WorkspaceAppStatusStateComplete)
455+
require.Equal(t,agent.Apps[0].Statuses[0].Message,"testing")
456+
require.Equal(t,agent.Apps[0].Statuses[0].URI,"https://example.com")
457+
require.Equal(t,agent.Apps[0].Statuses[1].State,codersdk.WorkspaceAppStatusStateWorking)
458+
require.Equal(t,agent.Apps[0].Statuses[1].Message,"testing")
459+
require.Equal(t,agent.Apps[0].Statuses[1].URI,"https://example.com")
460+
require.Equal(t,agent.Apps[0].Statuses[2].State,codersdk.WorkspaceAppStatusStateWorking)
461+
require.Equal(t,agent.Apps[0].Statuses[2].Message,"updated")
462+
require.Equal(t,agent.Apps[0].Statuses[2].URI,"")
463+
})
464+
390465
t.Run("FailUnknownApp",func(t*testing.T) {
391466
t.Parallel()
392467
ctx:=testutil.Context(t,testutil.WaitShort)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp