Skip to content

Commit bf4a11d

Browse files
committed
Extraneous prebuilds can ONLY be running, so if one is already deleting it cannot be extraneous
Signed-off-by: Danny Kopping <dannykopping@gmail.com>
1 parent 8abc973 commit bf4a11d

File tree

2 files changed

+16
-60
lines changed

2 files changed

+16
-60
lines changed

coderd/prebuilds/state.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,7 @@ func (p PresetState) CalculateActions(clock quartz.Clock, backoffInterval time.D
107107

108108
// It's possible that an operator could stop/start prebuilds which interfere with the reconciliation loop, so
109109
// we check if there are somehow more prebuilds than we expect, and then pick random victims to be deleted.
110-
// There must be no active deletions in order for extraneous prebuilds to be deleted.
111-
if extraneous > 0 && deleting == 0 {
110+
if extraneous > 0 {
112111
// Sort running IDs by creation time so we always delete the oldest prebuilds.
113112
// In general, we want fresher prebuilds (imagine a mono-repo is cloned; newer is better).
114113
slices.SortFunc(p.Running, func(a, b database.GetRunningPrebuildsRow) int {

coderd/prebuilds/state_test.go

Lines changed: 15 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ func TestInProgressActions(t *testing.T) {
154154
transition database.WorkspaceTransition
155155
desired int32
156156
running int32
157-
pending int32
157+
inProgress int32
158158
checkFn func(actions prebuilds.ReconciliationActions) bool
159159
}{
160160
// With no running prebuilds and one starting, no creations/deletions should take place.
@@ -163,7 +163,7 @@ func TestInProgressActions(t *testing.T) {
163163
transition: database.WorkspaceTransitionStart,
164164
desired: 1,
165165
running: 0,
166-
pending: 1,
166+
inProgress: 1,
167167
checkFn: func(actions prebuilds.ReconciliationActions) bool {
168168
return assert.True(t, validateActions(t, prebuilds.ReconciliationActions{Desired: 1, Starting: 1}, actions))
169169
},
@@ -174,7 +174,7 @@ func TestInProgressActions(t *testing.T) {
174174
transition: database.WorkspaceTransitionStart,
175175
desired: 2,
176176
running: 1,
177-
pending: 1,
177+
inProgress: 1,
178178
checkFn: func(actions prebuilds.ReconciliationActions) bool {
179179
return assert.True(t, validateActions(t, prebuilds.ReconciliationActions{Actual: 1, Desired: 2, Starting: 1}, actions))
180180
},
@@ -186,7 +186,7 @@ func TestInProgressActions(t *testing.T) {
186186
transition: database.WorkspaceTransitionStart,
187187
desired: 2,
188188
running: 2,
189-
pending: 1,
189+
inProgress: 1,
190190
checkFn: func(actions prebuilds.ReconciliationActions) bool {
191191
return assert.True(t, validateActions(t, prebuilds.ReconciliationActions{Actual: 2, Desired: 2, Starting: 1}, actions))
192192
},
@@ -197,7 +197,7 @@ func TestInProgressActions(t *testing.T) {
197197
transition: database.WorkspaceTransitionStop,
198198
desired: 1,
199199
running: 0,
200-
pending: 1,
200+
inProgress: 1,
201201
checkFn: func(actions prebuilds.ReconciliationActions) bool {
202202
return assert.True(t, validateActions(t, prebuilds.ReconciliationActions{Desired: 1, Stopping: 1, Create: 1}, actions))
203203
},
@@ -208,7 +208,7 @@ func TestInProgressActions(t *testing.T) {
208208
transition: database.WorkspaceTransitionStop,
209209
desired: 3,
210210
running: 2,
211-
pending: 1,
211+
inProgress: 1,
212212
checkFn: func(actions prebuilds.ReconciliationActions) bool {
213213
return assert.True(t, validateActions(t, prebuilds.ReconciliationActions{Actual: 2, Desired: 3, Stopping: 1, Create: 1}, actions))
214214
},
@@ -219,7 +219,7 @@ func TestInProgressActions(t *testing.T) {
219219
transition: database.WorkspaceTransitionStop,
220220
desired: 3,
221221
running: 3,
222-
pending: 1,
222+
inProgress: 1,
223223
checkFn: func(actions prebuilds.ReconciliationActions) bool {
224224
return assert.True(t, validateActions(t, prebuilds.ReconciliationActions{Actual: 3, Desired: 3, Stopping: 1}, actions))
225225
},
@@ -230,7 +230,7 @@ func TestInProgressActions(t *testing.T) {
230230
transition: database.WorkspaceTransitionDelete,
231231
desired: 1,
232232
running: 0,
233-
pending: 1,
233+
inProgress: 1,
234234
checkFn: func(actions prebuilds.ReconciliationActions) bool {
235235
return assert.True(t, validateActions(t, prebuilds.ReconciliationActions{Desired: 1, Deleting: 1, Create: 1}, actions))
236236
},
@@ -241,7 +241,7 @@ func TestInProgressActions(t *testing.T) {
241241
transition: database.WorkspaceTransitionDelete,
242242
desired: 2,
243243
running: 1,
244-
pending: 1,
244+
inProgress: 1,
245245
checkFn: func(actions prebuilds.ReconciliationActions) bool {
246246
return assert.True(t, validateActions(t, prebuilds.ReconciliationActions{Actual: 1, Desired: 2, Deleting: 1, Create: 1}, actions))
247247
},
@@ -252,7 +252,7 @@ func TestInProgressActions(t *testing.T) {
252252
transition: database.WorkspaceTransitionDelete,
253253
desired: 2,
254254
running: 2,
255-
pending: 1,
255+
inProgress: 1,
256256
checkFn: func(actions prebuilds.ReconciliationActions) bool {
257257
return assert.True(t, validateActions(t, prebuilds.ReconciliationActions{Actual: 2, Desired: 2, Deleting: 1}, actions))
258258
},
@@ -263,22 +263,21 @@ func TestInProgressActions(t *testing.T) {
263263
transition: database.WorkspaceTransitionStart,
264264
desired: 3,
265265
running: 1,
266-
pending: 2,
266+
inProgress: 2,
267267
checkFn: func(actions prebuilds.ReconciliationActions) bool {
268268
return assert.True(t, validateActions(t, prebuilds.ReconciliationActions{Actual: 1, Desired: 3, Starting: 2, Create: 0}, actions))
269269
},
270270
},
271-
// With 3 prebuilds desired, 1 running, and 2 starting, no creations should occur since the builds are in progress.
271+
// With 3 prebuilds desired, 5 running, and 2 deleting, no deletions should occur since the builds are in progress.
272272
{
273273
name: fmt.Sprintf("%s-inhibit", database.WorkspaceTransitionDelete),
274274
transition: database.WorkspaceTransitionDelete,
275275
desired: 3,
276276
running: 5,
277-
pending: 2,
277+
inProgress: 2,
278278
checkFn: func(actions prebuilds.ReconciliationActions) bool {
279279
expected := prebuilds.ReconciliationActions{Actual: 5, Desired: 3, Deleting: 2, Extraneous: 2}
280-
//return assert.True(t, validateActions(t, expected, actions))
281-
return assert.Len(t, actions.DeleteIDs, 0, "'deleteIDs' did not match expectation") &&
280+
return assert.Len(t, actions.DeleteIDs, 2, "'deleteIDs' did not match expectation") &&
282281
assert.EqualValuesf(t, expected.Create, actions.Create, "'create' did not match expectation") &&
283282
assert.EqualValuesf(t, expected.Desired, actions.Desired, "'desired' did not match expectation") &&
284283
assert.EqualValuesf(t, expected.Actual, actions.Actual, "'actual' did not match expectation") &&
@@ -323,7 +322,7 @@ func TestInProgressActions(t *testing.T) {
323322
TemplateID: current.templateID,
324323
TemplateVersionID: current.templateVersionID,
325324
Transition: tc.transition,
326-
Count: tc.pending,
325+
Count: tc.inProgress,
327326
},
328327
}
329328

@@ -381,48 +380,6 @@ func TestExtraneous(t *testing.T) {
381380
}, *actions)
382381
}
383382

384-
// As above, but no actions will be performed because
385-
func TestExtraneousInProgress(t *testing.T) {
386-
current := opts[optionSet0]
387-
clock := quartz.NewMock(t)
388-
389-
const desiredInstances = 2;
390-
391-
// GIVEN: a preset with 2 desired prebuilds.
392-
presets := []database.GetTemplatePresetsWithPrebuildsRow{
393-
preset(true, desiredInstances, current),
394-
}
395-
396-
// GIVEN: 3 running prebuilds for the preset.
397-
running := []database.GetRunningPrebuildsRow{
398-
prebuild(current, clock),
399-
prebuild(current, clock),
400-
prebuild(current, clock),
401-
}
402-
403-
// GIVEN: a prebuild deletion in progress.
404-
inProgress := []database.GetPrebuildsInProgressRow{
405-
{
406-
TemplateID: current.templateID,
407-
TemplateVersionID: current.templateVersionID,
408-
Transition: database.WorkspaceTransitionDelete,
409-
Count: 1,
410-
},
411-
}
412-
413-
// WHEN: calculating the current preset's state.
414-
state := prebuilds.NewReconciliationState(presets, running, inProgress, nil)
415-
ps, err := state.FilterByPreset(current.presetID)
416-
require.NoError(t, err)
417-
418-
// THEN: an extraneous prebuild is detected and marked for deletion.
419-
actions, err := ps.CalculateActions(clock, backoffInterval)
420-
require.NoError(t, err)
421-
validateActions(t, prebuilds.ReconciliationActions{
422-
Actual: 3, Desired: desiredInstances, Extraneous: 1, Deleting: 1, DeleteIDs: nil, Eligible: 3,
423-
}, *actions)
424-
}
425-
426383
// A template marked as deprecated will not have prebuilds running.
427384
func TestDeprecated(t *testing.T) {
428385
current := opts[optionSet0]

0 commit comments

Comments
 (0)