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

Commitbd139f3

Browse files
johnstcnmafredri
andauthored
fix(coderd/provisionerdserver): workaround lack of coder_ai_task resource on stop transition (#19560)
This works around the issue where a task may "disappear" on stop.Re-using the previous value of `has_ai_task` and `sidebar_app_id` on astop transition.---------Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
1 parent8083d9d commitbd139f3

File tree

2 files changed

+114
-1
lines changed

2 files changed

+114
-1
lines changed

‎coderd/provisionerdserver/provisionerdserver.go‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1995,6 +1995,37 @@ func (s *server) completeWorkspaceBuildJob(ctx context.Context, job database.Pro
19951995
sidebarAppID= uuid.NullUUID{UUID:id,Valid:true}
19961996
}
19971997

1998+
// This is a hacky workaround for the issue with tasks 'disappearing' on stop:
1999+
// reuse has_ai_task and sidebar_app_id from the previous build.
2000+
// This workaround should be removed as soon as possible.
2001+
ifworkspaceBuild.Transition==database.WorkspaceTransitionStop&&workspaceBuild.BuildNumber>1 {
2002+
ifprevBuild,err:=s.Database.GetWorkspaceBuildByWorkspaceIDAndBuildNumber(ctx, database.GetWorkspaceBuildByWorkspaceIDAndBuildNumberParams{
2003+
WorkspaceID:workspaceBuild.WorkspaceID,
2004+
BuildNumber:workspaceBuild.BuildNumber-1,
2005+
});err==nil {
2006+
hasAITask=prevBuild.HasAITask.Bool
2007+
sidebarAppID=prevBuild.AITaskSidebarAppID
2008+
warnUnknownSidebarAppID=false
2009+
s.Logger.Debug(ctx,"task workaround: reused has_ai_task and sidebar_app_id from previous build to keep track of task",
2010+
slog.F("job_id",job.ID.String()),
2011+
slog.F("build_number",prevBuild.BuildNumber),
2012+
slog.F("workspace_id",workspace.ID),
2013+
slog.F("workspace_build_id",workspaceBuild.ID),
2014+
slog.F("transition",string(workspaceBuild.Transition)),
2015+
slog.F("sidebar_app_id",sidebarAppID.UUID),
2016+
slog.F("has_ai_task",hasAITask),
2017+
)
2018+
}else {
2019+
s.Logger.Error(ctx,"task workaround: tracking via has_ai_task and sidebar_app from previous build failed",
2020+
slog.Error(err),
2021+
slog.F("job_id",job.ID.String()),
2022+
slog.F("workspace_id",workspace.ID),
2023+
slog.F("workspace_build_id",workspaceBuild.ID),
2024+
slog.F("transition",string(workspaceBuild.Transition)),
2025+
)
2026+
}
2027+
}
2028+
19982029
ifwarnUnknownSidebarAppID {
19992030
// Ref: https://github.com/coder/coder/issues/18776
20002031
// This can happen for a number of reasons:

‎coderd/provisionerdserver/provisionerdserver_test.go‎

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2842,9 +2842,12 @@ func TestCompleteJob(t *testing.T) {
28422842
// has_ai_task has a default value of nil, but once the workspace build completes it will have a value;
28432843
// it is set to "true" if the related template has any coder_ai_task resources defined, and its sidebar app ID
28442844
// will be set as well in that case.
2845+
// HACK(johnstcn): we also set it to "true" if any _previous_ workspace builds ever had it set to "true".
2846+
// This is to avoid tasks "disappearing" when you stop them.
28452847
t.Run("WorkspaceBuild",func(t*testing.T) {
28462848
typetestcasestruct {
28472849
namestring
2850+
seedFuncfunc(context.Context, testing.TB, database.Store)error// If you need to insert other resources
28482851
transition database.WorkspaceTransition
28492852
input*proto.CompletedJob_WorkspaceBuild
28502853
expectHasAiTaskbool
@@ -2944,6 +2947,17 @@ func TestCompleteJob(t *testing.T) {
29442947
expectHasAiTask:true,
29452948
expectUsageEvent:false,
29462949
},
2950+
{
2951+
name:"current build does not have ai task but previous build did",
2952+
seedFunc:seedPreviousWorkspaceStartWithAITask,
2953+
transition:database.WorkspaceTransitionStop,
2954+
input:&proto.CompletedJob_WorkspaceBuild{
2955+
AiTasks: []*sdkproto.AITask{},
2956+
Resources: []*sdkproto.Resource{},
2957+
},
2958+
expectHasAiTask:true,
2959+
expectUsageEvent:false,
2960+
},
29472961
} {
29482962
t.Run(tc.name,func(t*testing.T) {
29492963
t.Parallel()
@@ -2980,6 +2994,9 @@ func TestCompleteJob(t *testing.T) {
29802994
})
29812995

29822996
ctx:=testutil.Context(t,testutil.WaitShort)
2997+
iftc.seedFunc!=nil {
2998+
require.NoError(t,tc.seedFunc(ctx,t,db))
2999+
}
29833000

29843001
buildJobID:=uuid.New()
29853002
wsBuildID:=uuid.New()
@@ -2999,8 +3016,13 @@ func TestCompleteJob(t *testing.T) {
29993016
Tags:pd.Tags,
30003017
})
30013018
require.NoError(t,err)
3019+
varbuildNumint32
3020+
iflatestBuild,err:=db.GetLatestWorkspaceBuildByWorkspaceID(ctx,workspaceTable.ID);err==nil {
3021+
buildNum=latestBuild.BuildNumber
3022+
}
30023023
build:=dbgen.WorkspaceBuild(t,db, database.WorkspaceBuild{
30033024
ID:wsBuildID,
3025+
BuildNumber:buildNum+1,
30043026
JobID:buildJobID,
30053027
WorkspaceID:workspaceTable.ID,
30063028
TemplateVersionID:version.ID,
@@ -3038,7 +3060,7 @@ func TestCompleteJob(t *testing.T) {
30383060
require.True(t,build.HasAITask.Valid)// We ALWAYS expect a value to be set, therefore not nil, i.e. valid = true.
30393061
require.Equal(t,tc.expectHasAiTask,build.HasAITask.Bool)
30403062

3041-
iftc.expectHasAiTask {
3063+
iftc.expectHasAiTask&&build.Transition!=database.WorkspaceTransitionStop{
30423064
require.Equal(t,sidebarAppID,build.AITaskSidebarAppID.UUID.String())
30433065
}
30443066

@@ -4244,3 +4266,63 @@ func (f *fakeUsageInserter) InsertDiscreteUsageEvent(_ context.Context, _ databa
42444266
f.collectedEvents=append(f.collectedEvents,event)
42454267
returnnil
42464268
}
4269+
4270+
funcseedPreviousWorkspaceStartWithAITask(ctx context.Context,t testing.TB,db database.Store)error {
4271+
t.Helper()
4272+
// If the below looks slightly convoluted, that's because it is.
4273+
// The workspace doesn't yet have a latest build, so querying all
4274+
// workspaces will fail.
4275+
tpls,err:=db.GetTemplates(ctx)
4276+
iferr!=nil {
4277+
returnxerrors.Errorf("seedFunc: get template: %w",err)
4278+
}
4279+
iflen(tpls)!=1 {
4280+
returnxerrors.Errorf("seedFunc: expected exactly one template, got %d",len(tpls))
4281+
}
4282+
ws,err:=db.GetWorkspacesByTemplateID(ctx,tpls[0].ID)
4283+
iferr!=nil {
4284+
returnxerrors.Errorf("seedFunc: get workspaces: %w",err)
4285+
}
4286+
iflen(ws)!=1 {
4287+
returnxerrors.Errorf("seedFunc: expected exactly one workspace, got %d",len(ws))
4288+
}
4289+
w:=ws[0]
4290+
prevJob:=dbgen.ProvisionerJob(t,db,nil, database.ProvisionerJob{
4291+
OrganizationID:w.OrganizationID,
4292+
InitiatorID:w.OwnerID,
4293+
Type:database.ProvisionerJobTypeWorkspaceBuild,
4294+
})
4295+
tvs,err:=db.GetTemplateVersionsByTemplateID(ctx, database.GetTemplateVersionsByTemplateIDParams{
4296+
TemplateID:tpls[0].ID,
4297+
})
4298+
iferr!=nil {
4299+
returnxerrors.Errorf("seedFunc: get template version: %w",err)
4300+
}
4301+
iflen(tvs)!=1 {
4302+
returnxerrors.Errorf("seedFunc: expected exactly one template version, got %d",len(tvs))
4303+
}
4304+
iftpls[0].ActiveVersionID==uuid.Nil {
4305+
returnxerrors.Errorf("seedFunc: active version id is nil")
4306+
}
4307+
res:=dbgen.WorkspaceResource(t,db, database.WorkspaceResource{
4308+
JobID:prevJob.ID,
4309+
})
4310+
agt:=dbgen.WorkspaceAgent(t,db, database.WorkspaceAgent{
4311+
ResourceID:res.ID,
4312+
})
4313+
wa:=dbgen.WorkspaceApp(t,db, database.WorkspaceApp{
4314+
AgentID:agt.ID,
4315+
})
4316+
_=dbgen.WorkspaceBuild(t,db, database.WorkspaceBuild{
4317+
BuildNumber:1,
4318+
HasAITask: sql.NullBool{Valid:true,Bool:true},
4319+
AITaskSidebarAppID: uuid.NullUUID{Valid:true,UUID:wa.ID},
4320+
ID:w.ID,
4321+
InitiatorID:w.OwnerID,
4322+
JobID:prevJob.ID,
4323+
TemplateVersionID:tvs[0].ID,
4324+
Transition:database.WorkspaceTransitionStart,
4325+
WorkspaceID:w.ID,
4326+
})
4327+
returnnil
4328+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp