(t *testing.T)
| 1838 | } |
| 1839 | |
| 1840 | func TestFailedBuildBackoff(t *testing.T) { |
| 1841 | t.Parallel() |
| 1842 | |
| 1843 | ctx := testutil.Context(t, testutil.WaitSuperLong) |
| 1844 | |
| 1845 | // Setup. |
| 1846 | clock := quartz.NewMock(t) |
| 1847 | backoffInterval := time.Minute |
| 1848 | cfg := codersdk.PrebuildsConfig{ |
| 1849 | // Given: explicitly defined backoff configuration to validate timings. |
| 1850 | ReconciliationBackoffLookback: serpent.Duration(muchEarlier * -10), // Has to be positive. |
| 1851 | ReconciliationBackoffInterval: serpent.Duration(backoffInterval), |
| 1852 | ReconciliationInterval: serpent.Duration(time.Second), |
| 1853 | } |
| 1854 | logger := slogtest.Make( |
| 1855 | t, &slogtest.Options{IgnoreErrors: true}, |
| 1856 | ).Leveled(slog.LevelDebug) |
| 1857 | db, ps := dbtestutil.NewDB(t) |
| 1858 | cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) |
| 1859 | reconciler := prebuilds.NewStoreReconciler( |
| 1860 | db, ps, cache, cfg, logger, |
| 1861 | clock, |
| 1862 | prometheus.NewRegistry(), |
| 1863 | newNoopEnqueuer(), |
| 1864 | newNoopUsageCheckerPtr(), |
| 1865 | noop.NewTracerProvider(), |
| 1866 | 10, |
| 1867 | nil, |
| 1868 | ) |
| 1869 | |
| 1870 | // Given: an active template version with presets and prebuilds configured. |
| 1871 | const desiredInstances = 2 |
| 1872 | userID := uuid.New() |
| 1873 | dbgen.User(t, db, database.User{ |
| 1874 | ID: userID, |
| 1875 | }) |
| 1876 | org, template := setupTestDBTemplate(t, db, userID, false) |
| 1877 | templateVersionID := setupTestDBTemplateVersion(ctx, t, clock, db, ps, org.ID, userID, template.ID) |
| 1878 | |
| 1879 | preset := setupTestDBPreset(t, db, templateVersionID, desiredInstances, "test") |
| 1880 | for range desiredInstances { |
| 1881 | _, _ = setupTestDBPrebuild(t, clock, db, ps, database.WorkspaceTransitionStart, database.ProvisionerJobStatusFailed, org.ID, preset, template.ID, templateVersionID) |
| 1882 | } |
| 1883 | |
| 1884 | // When: determining what actions to take next, backoff is calculated because the prebuild is in a failed state. |
| 1885 | snapshot, err := reconciler.SnapshotState(ctx, db) |
| 1886 | require.NoError(t, err) |
| 1887 | require.Len(t, snapshot.Presets, 1) |
| 1888 | presetState, err := snapshot.FilterByPreset(preset.ID) |
| 1889 | require.NoError(t, err) |
| 1890 | state := presetState.CalculateState() |
| 1891 | actions, err := reconciler.CalculateActions(ctx, *presetState) |
| 1892 | require.NoError(t, err) |
| 1893 | require.Equal(t, 1, len(actions)) |
| 1894 | |
| 1895 | // Then: the backoff time is in the future, no prebuilds are running, and we won't create any new prebuilds. |
| 1896 | require.EqualValues(t, 0, state.Actual) |
| 1897 | require.EqualValues(t, 0, actions[0].Create) |
nothing calls this directly
no test coverage detected