refactor: use specific error for agpl and prebuilds (#17591)

Follow-up PR to https://github.com/coder/coder/pull/17458
Addresses this discussion:
https://github.com/coder/coder/pull/17458#discussion_r2055940797
This commit is contained in:
Yevhenii Shcherbina
2025-04-28 16:37:41 -04:00
committed by GitHub
parent 1da27a1ebc
commit a78f0fc4e1
4 changed files with 36 additions and 5 deletions
+4 -1
View File
@@ -9,7 +9,10 @@ import (
"github.com/coder/coder/v2/coderd/database"
)
var ErrNoClaimablePrebuiltWorkspaces = xerrors.New("no claimable prebuilt workspaces found")
var (
ErrNoClaimablePrebuiltWorkspaces = xerrors.New("no claimable prebuilt workspaces found")
ErrAGPLDoesNotSupportPrebuiltWorkspaces = xerrors.New("prebuilt workspaces functionality is not supported under the AGPL license")
)
// ReconciliationOrchestrator manages the lifecycle of prebuild reconciliation.
// It runs a continuous loop to check and reconcile prebuild states, and can be stopped gracefully.
+1 -1
View File
@@ -27,7 +27,7 @@ type NoopClaimer struct{}
func (NoopClaimer) Claim(context.Context, uuid.UUID, string, uuid.UUID) (*uuid.UUID, error) {
// Not entitled to claim prebuilds in AGPL version.
return nil, ErrNoClaimablePrebuiltWorkspaces
return nil, ErrAGPLDoesNotSupportPrebuiltWorkspaces
}
func (NoopClaimer) Initiator() uuid.UUID {
+22 -2
View File
@@ -650,8 +650,28 @@ func createWorkspace(
if req.TemplateVersionPresetID != uuid.Nil {
// Try and claim an eligible prebuild, if available.
claimedWorkspace, err = claimPrebuild(ctx, prebuildsClaimer, db, api.Logger, req, owner)
if err != nil && !errors.Is(err, prebuilds.ErrNoClaimablePrebuiltWorkspaces) {
return xerrors.Errorf("claim prebuild: %w", err)
// If claiming fails with an expected error (no claimable prebuilds or AGPL does not support prebuilds),
// we fall back to creating a new workspace. Otherwise, propagate the unexpected error.
if err != nil {
isExpectedError := errors.Is(err, prebuilds.ErrNoClaimablePrebuiltWorkspaces) ||
errors.Is(err, prebuilds.ErrAGPLDoesNotSupportPrebuiltWorkspaces)
fields := []any{
slog.Error(err),
slog.F("workspace_name", req.Name),
slog.F("template_version_preset_id", req.TemplateVersionPresetID),
}
if !isExpectedError {
// if it's an unexpected error - use error log level
api.Logger.Error(ctx, "failed to claim prebuilt workspace", fields...)
return xerrors.Errorf("failed to claim prebuilt workspace: %w", err)
}
// if it's an expected error - use warn log level
api.Logger.Warn(ctx, "failed to claim prebuilt workspace", fields...)
// fall back to creating a new workspace
}
}
+9 -1
View File
@@ -111,6 +111,11 @@ func TestClaimPrebuild(t *testing.T) {
markPrebuildsClaimable: true,
claimingErr: agplprebuilds.ErrNoClaimablePrebuiltWorkspaces,
},
"AGPL does not support prebuilds error is returned": {
expectPrebuildClaimed: false,
markPrebuildsClaimable: true,
claimingErr: agplprebuilds.ErrAGPLDoesNotSupportPrebuiltWorkspaces,
},
"unexpected claiming error is returned": {
expectPrebuildClaimed: false,
markPrebuildsClaimable: true,
@@ -224,8 +229,11 @@ func TestClaimPrebuild(t *testing.T) {
TemplateVersionPresetID: presets[0].ID,
})
isNoPrebuiltWorkspaces := errors.Is(tc.claimingErr, agplprebuilds.ErrNoClaimablePrebuiltWorkspaces)
isUnsupported := errors.Is(tc.claimingErr, agplprebuilds.ErrAGPLDoesNotSupportPrebuiltWorkspaces)
switch {
case tc.claimingErr != nil && errors.Is(tc.claimingErr, agplprebuilds.ErrNoClaimablePrebuiltWorkspaces):
case tc.claimingErr != nil && (isNoPrebuiltWorkspaces || isUnsupported):
require.NoError(t, err)
coderdtest.AwaitWorkspaceBuildJobCompleted(t, userClient, userWorkspace.LatestBuild.ID)