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

Commit3f66077

Browse files
committed
make the new tests pass with some refactoring
1 parent3fdb781 commit3f66077

File tree

7 files changed

+213
-55
lines changed

7 files changed

+213
-55
lines changed

‎coderd/autostart/lifecycle/lifecycle_executor.go

Lines changed: 57 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,12 @@ import (
99

1010
"github.com/coder/coder/coderd/autostart/schedule"
1111
"github.com/coder/coder/coderd/database"
12-
"github.com/coder/coder/codersdk"
1312

1413
"github.com/google/uuid"
1514
"github.com/moby/moby/pkg/namesgenerator"
1615
"golang.org/x/xerrors"
1716
)
1817

19-
//var ExecutorUUID = uuid.MustParse("00000000-0000-0000-0000-000000000000")
20-
2118
// Executor executes automated workspace lifecycle operations.
2219
typeExecutorstruct {
2320
ctx context.Context
@@ -26,6 +23,7 @@ type Executor struct {
2623
tick<-chan time.Time
2724
}
2825

26+
// NewExecutor returns a new instance of Executor.
2927
funcNewExecutor(ctx context.Context,db database.Store,log slog.Logger,tick<-chan time.Time)*Executor {
3028
le:=&Executor{
3129
ctx:ctx,
@@ -36,15 +34,18 @@ func NewExecutor(ctx context.Context, db database.Store, log slog.Logger, tick <
3634
returnle
3735
}
3836

39-
func (e*Executor)Run()error {
37+
// Run will cause executor to run workspace lifecycle operations on every
38+
// tick from its channel. It will stop when its context is Done, or when
39+
// its channel is closed.
40+
func (e*Executor)Run() {
4041
for {
4142
select {
4243
caset:=<-e.tick:
4344
iferr:=e.runOnce(t);err!=nil {
4445
e.log.Error(e.ctx,"error running once",slog.Error(err))
4546
}
4647
case<-e.ctx.Done():
47-
returnnil
48+
return
4849
default:
4950
}
5051
}
@@ -53,65 +54,89 @@ func (e *Executor) Run() error {
5354
func (e*Executor)runOnce(t time.Time)error {
5455
currentTick:=t.Round(time.Minute)
5556
returne.db.InTx(func(db database.Store)error {
56-
autostartWorkspaces,err:=db.GetWorkspacesAutostart(e.ctx)
57+
eligibleWorkspaces,err:=db.GetWorkspacesAutostartAutostop(e.ctx)
5758
iferr!=nil {
58-
returnxerrors.Errorf("getall workspaces: %w",err)
59+
returnxerrors.Errorf("geteligible workspaces for autostart or autostop: %w",err)
5960
}
6061

61-
for_,ws:=rangeautostartWorkspaces {
62-
sched,err:=schedule.Weekly(ws.AutostartSchedule.String)
63-
iferr!=nil {
64-
e.log.Warn(e.ctx,"workspace has invalid autostart schedule",
65-
slog.F("workspace_id",ws.ID),
66-
slog.F("autostart_schedule",ws.AutostartSchedule.String),
67-
)
68-
continue
69-
}
70-
71-
// Determine the workspace state based on its latest build. We expect it to be stopped.
62+
for_,ws:=rangeeligibleWorkspaces {
63+
// Determine the workspace state based on its latest build.
7264
latestBuild,err:=db.GetWorkspaceBuildByWorkspaceIDWithoutAfter(e.ctx,ws.ID)
7365
iferr!=nil {
7466
returnxerrors.Errorf("get latest build for workspace %q: %w",ws.ID,err)
7567
}
76-
iflatestBuild.Transition!=database.WorkspaceTransitionStop {
77-
e.log.Debug(e.ctx,"autostart: skipping workspace: wrong transition",
78-
slog.F("transition",latestBuild.Transition),
68+
69+
varvalidTransition database.WorkspaceTransition
70+
varsched*schedule.Schedule
71+
switchlatestBuild.Transition {
72+
casedatabase.WorkspaceTransitionStart:
73+
validTransition=database.WorkspaceTransitionStop
74+
sched,err=schedule.Weekly(ws.AutostopSchedule.String)
75+
iferr!=nil {
76+
e.log.Warn(e.ctx,"workspace has invalid autostop schedule, skipping",
77+
slog.F("workspace_id",ws.ID),
78+
slog.F("autostart_schedule",ws.AutostopSchedule.String),
79+
)
80+
continue
81+
}
82+
casedatabase.WorkspaceTransitionStop:
83+
validTransition=database.WorkspaceTransitionStart
84+
sched,err=schedule.Weekly(ws.AutostartSchedule.String)
85+
iferr!=nil {
86+
e.log.Warn(e.ctx,"workspace has invalid autostart schedule, skipping",
87+
slog.F("workspace_id",ws.ID),
88+
slog.F("autostart_schedule",ws.AutostartSchedule.String),
89+
)
90+
continue
91+
}
92+
default:
93+
e.log.Debug(e.ctx,"last transition not valid for autostart or autostop",
7994
slog.F("workspace_id",ws.ID),
95+
slog.F("latest_build_transition",latestBuild.Transition),
8096
)
81-
continue
8297
}
8398

8499
// Round time to the nearest minute, as this is the finest granularity cron supports.
85-
earliestAutostart:=sched.Next(latestBuild.CreatedAt).Round(time.Minute)
86-
ifearliestAutostart.After(currentTick) {
87-
e.log.Debug(e.ctx,"autostart:skipping workspace: too early",
100+
nextTransitionAt:=sched.Next(latestBuild.CreatedAt).Round(time.Minute)
101+
ifnextTransitionAt.After(currentTick) {
102+
e.log.Debug(e.ctx,"skipping workspace: too early",
88103
slog.F("workspace_id",ws.ID),
89-
slog.F("earliest_autostart",earliestAutostart),
104+
slog.F("next_transition_at",nextTransitionAt),
105+
slog.F("transition",validTransition),
90106
slog.F("current_tick",currentTick),
91107
)
92108
continue
93109
}
94110

95-
e.log.Info(e.ctx,"autostart:scheduling workspacestart",
111+
e.log.Info(e.ctx,"scheduling workspacetransition",
96112
slog.F("workspace_id",ws.ID),
113+
slog.F("transition",validTransition),
97114
)
98115

99-
iferr:=doBuild(e.ctx,db,ws,currentTick);err!=nil {
100-
e.log.Error(e.ctx,"autostart workspace",slog.F("workspace_id",ws.ID),slog.Error(err))
116+
iferr:=doBuild(e.ctx,db,ws,validTransition);err!=nil {
117+
e.log.Error(e.ctx,"transition workspace",
118+
slog.F("workspace_id",ws.ID),
119+
slog.F("transition",validTransition),
120+
slog.Error(err),
121+
)
101122
}
102123
}
103124
returnnil
104125
})
105126
}
106127

107-
//XXX:cian: this functionshouldn't really exist. Refactor.
108-
funcdoBuild(ctx context.Context,store database.Store,workspace database.Workspace,now time.Time)error {
128+
//TODO(cian): this functionduplicates most of api.postWorkspaceBuilds. Refactor.
129+
funcdoBuild(ctx context.Context,store database.Store,workspace database.Workspace,trans database.WorkspaceTransition)error {
109130
template,err:=store.GetTemplateByID(ctx,workspace.TemplateID)
110131
iferr!=nil {
111132
returnxerrors.Errorf("get template: %w",err)
112133
}
113134

114135
priorHistory,err:=store.GetWorkspaceBuildByWorkspaceIDWithoutAfter(ctx,workspace.ID)
136+
iferr!=nil {
137+
returnxerrors.Errorf("get prior history: %w",err)
138+
}
139+
115140
priorJob,err:=store.GetProvisionerJobByID(ctx,priorHistory.JobID)
116141
iferr==nil&&!priorJob.CompletedAt.Valid {
117142
returnxerrors.Errorf("workspace build already active")
@@ -160,7 +185,7 @@ func doBuild(ctx context.Context, store database.Store, workspace database.Works
160185
Name:namesgenerator.GetRandomName(1),
161186
ProvisionerState:priorHistory.ProvisionerState,
162187
InitiatorID:workspace.OwnerID,
163-
Transition:database.WorkspaceTransitionStart,
188+
Transition:trans,
164189
JobID:newProvisionerJob.ID,
165190
})
166191
iferr!=nil {
@@ -184,24 +209,3 @@ func doBuild(ctx context.Context, store database.Store, workspace database.Works
184209
}
185210
returnnil
186211
}
187-
188-
funcprovisionerJobStatus(j database.ProvisionerJob,now time.Time) codersdk.ProvisionerJobStatus {
189-
switch {
190-
casej.CanceledAt.Valid:
191-
ifj.CompletedAt.Valid {
192-
returncodersdk.ProvisionerJobCanceled
193-
}
194-
returncodersdk.ProvisionerJobCanceling
195-
case!j.StartedAt.Valid:
196-
returncodersdk.ProvisionerJobPending
197-
casej.CompletedAt.Valid:
198-
ifj.Error.String=="" {
199-
returncodersdk.ProvisionerJobSucceeded
200-
}
201-
returncodersdk.ProvisionerJobFailed
202-
casenow.Sub(j.UpdatedAt)>30*time.Second:
203-
returncodersdk.ProvisionerJobFailed
204-
default:
205-
returncodersdk.ProvisionerJobRunning
206-
}
207-
}

‎coderd/autostart/lifecycle/lifecycle_executor_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ func Test_Executor_Autostart_OK(t *testing.T) {
4343
// When: the lifecycle executor ticks
4444
gofunc() {
4545
tickCh<-time.Now().UTC().Add(time.Minute)
46+
close(tickCh)
4647
}()
4748

4849
// Then: the workspace should be started
@@ -83,6 +84,7 @@ func Test_Executor_Autostart_AlreadyRunning(t *testing.T) {
8384
// When: the lifecycle executor ticks
8485
gofunc() {
8586
tickCh<-time.Now().UTC().Add(time.Minute)
87+
close(tickCh)
8688
}()
8789

8890
// Then: the workspace should not be started.
@@ -113,6 +115,7 @@ func Test_Executor_Autostart_NotEnabled(t *testing.T) {
113115
// When: the lifecycle executor ticks
114116
gofunc() {
115117
tickCh<-time.Now().UTC().Add(time.Minute)
118+
close(tickCh)
116119
}()
117120

118121
// Then: the workspace should not be started.
@@ -151,12 +154,13 @@ func Test_Executor_Autostop_OK(t *testing.T) {
151154
// When: the lifecycle executor ticks
152155
gofunc() {
153156
tickCh<-time.Now().UTC().Add(time.Minute)
157+
close(tickCh)
154158
}()
155159

156160
// Then: the workspace should be started
157161
require.Eventually(t,func()bool {
158162
ws:=coderdtest.MustWorkspace(t,client,workspace.ID)
159-
returnws.LatestBuild.ID!=workspace.LatestBuild.ID&&ws.LatestBuild.Transition==database.WorkspaceTransitionStart
163+
returnws.LatestBuild.ID!=workspace.LatestBuild.ID&&ws.LatestBuild.Transition==database.WorkspaceTransitionStop
160164
},5*time.Second,250*time.Millisecond)
161165
}
162166
funcTest_Executor_Autostop_AlreadyStopped(t*testing.T) {
@@ -189,6 +193,7 @@ func Test_Executor_Autostop_AlreadyStopped(t *testing.T) {
189193
// When: the lifecycle executor ticks
190194
gofunc() {
191195
tickCh<-time.Now().UTC().Add(time.Minute)
196+
close(tickCh)
192197
}()
193198

194199
// Then: the workspace should not be stopped.
@@ -219,6 +224,7 @@ func Test_Executor_Autostop_NotEnabled(t *testing.T) {
219224
// When: the lifecycle executor ticks
220225
gofunc() {
221226
tickCh<-time.Now().UTC().Add(time.Minute)
227+
close(tickCh)
222228
}()
223229

224230
// Then: the workspace should not be stopped.

‎coderd/database/databasefake/databasefake.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,32 @@ func (q *fakeQuerier) GetWorkspacesAutostart(_ context.Context) ([]database.Work
313313
returnworkspaces,nil
314314
}
315315

316+
func (q*fakeQuerier)GetWorkspacesAutostop(_ context.Context) ([]database.Workspace,error) {
317+
q.mutex.RLock()
318+
deferq.mutex.RUnlock()
319+
workspaces:=make([]database.Workspace,0)
320+
for_,ws:=rangeq.workspaces {
321+
ifws.AutostopSchedule.String!="" {
322+
workspaces=append(workspaces,ws)
323+
}
324+
}
325+
returnworkspaces,nil
326+
}
327+
328+
func (q*fakeQuerier)GetWorkspacesAutostartAutostop(_ context.Context) ([]database.Workspace,error) {
329+
q.mutex.RLock()
330+
deferq.mutex.RUnlock()
331+
workspaces:=make([]database.Workspace,0)
332+
for_,ws:=rangeq.workspaces {
333+
ifws.AutostartSchedule.String!="" {
334+
workspaces=append(workspaces,ws)
335+
}elseifws.AutostopSchedule.String!="" {
336+
workspaces=append(workspaces,ws)
337+
}
338+
}
339+
returnworkspaces,nil
340+
}
341+
316342
func (q*fakeQuerier)GetWorkspaceOwnerCountsByTemplateIDs(_ context.Context,templateIDs []uuid.UUID) ([]database.GetWorkspaceOwnerCountsByTemplateIDsRow,error) {
317343
q.mutex.RLock()
318344
deferq.mutex.RUnlock()

‎coderd/database/querier.go

Lines changed: 2 additions & 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: 94 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp