- Notifications
You must be signed in to change notification settings - Fork1k
feat: claim prebuilds based on workspace parameters instead of preset id#19279
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
0890d84
a94d03e
96f0b37
a9e0f1d
292a1a9
b40e78f
6fe0dd0
735e937
151a039
2c5647f
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1810,6 +1810,14 @@ func (q *querier) FetchVolumesResourceMonitorsUpdatedAfter(ctx context.Context, | ||
return q.db.FetchVolumesResourceMonitorsUpdatedAfter(ctx, updatedAt) | ||
} | ||
func (q *querier) FindMatchingPresetID(ctx context.Context, arg database.FindMatchingPresetIDParams) (uuid.UUID, error) { | ||
_, err := q.GetTemplateVersionByID(ctx, arg.TemplateVersionID) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. I don't like this, but I can't find a better way and there is precedent for this approach. Open to alternatives. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. The alternative is to essentially duplicate the logic in | ||
if err != nil { | ||
return uuid.Nil, err | ||
} | ||
return q.db.FindMatchingPresetID(ctx, arg) | ||
} | ||
func (q *querier) GetAPIKeyByID(ctx context.Context, id string) (database.APIKey, error) { | ||
return fetch(q.log, q.auth, q.db.GetAPIKeyByID)(ctx, id) | ||
} | ||
Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.
Uh oh!
There was an error while loading.Please reload this page.
Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.
Uh oh!
There was an error while loading.Please reload this page.
Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.
Uh oh!
There was an error while loading.Please reload this page.
Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.
Uh oh!
There was an error while loading.Please reload this page.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -245,3 +245,30 @@ INNER JOIN organizations o ON o.id = w.organization_id | ||
WHERE NOT t.deleted AND wpb.build_number = 1 | ||
GROUP BY t.name, tvp.name, o.name | ||
ORDER BY t.name, tvp.name, o.name; | ||
-- name: FindMatchingPresetID :one | ||
-- FindMatchingPresetID finds a preset ID that is the largest exact subset of the provided parameters. | ||
-- It returns the preset ID if a match is found, or NULL if no match is found. | ||
-- The query finds presets where all preset parameters are present in the provided parameters, | ||
-- and returns the preset with the most parameters (largest subset). | ||
WITH provided_params AS ( | ||
SELECT | ||
unnest(@parameter_names::text[]) AS name, | ||
unnest(@parameter_values::text[]) AS value | ||
), | ||
preset_matches AS ( | ||
SELECT | ||
tvp.id AS template_version_preset_id, | ||
COALESCE(COUNT(tvpp.name), 0) AS total_preset_params, | ||
COALESCE(COUNT(pp.name), 0) AS matching_params | ||
FROM template_version_presets tvp | ||
LEFT JOIN template_version_preset_parameters tvpp ON tvpp.template_version_preset_id = tvp.id | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. These left join suggests there is merit in including presets with no parameters as well as zero matches with provided params, why would we want this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Presets that define 0 parameters are valid. They're used in more trivial templates, usually docker based, where there really isn't much to change but one still wants prebuilds. In this case one would define a preset with no parameters that desires There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. This is useful for simpler parameters where one wants prebuilds without specifying any parameters. You could define a preset that sets no parameters. If such a preset exists, it would be selected automatically by this. | ||
LEFT JOIN provided_params pp ON pp.name = tvpp.name AND pp.value = tvpp.value | ||
WHERE tvp.template_version_id = @template_version_id | ||
GROUP BY tvp.id | ||
) | ||
SELECT pm.template_version_preset_id | ||
FROM preset_matches pm | ||
WHERE pm.total_preset_params = pm.matching_params -- All preset parameters must match | ||
ORDER BY pm.total_preset_params DESC -- Return the preset with the most parameters | ||
LIMIT 1; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package prebuilds | ||
import ( | ||
"context" | ||
"database/sql" | ||
"errors" | ||
"github.com/google/uuid" | ||
"golang.org/x/xerrors" | ||
"github.com/coder/coder/v2/coderd/database" | ||
) | ||
// FindMatchingPresetID finds a preset ID that matches the provided parameters. | ||
// It returns the preset ID if a match is found, or uuid.Nil if no match is found. | ||
// The function performs a bidirectional comparison to ensure all parameters match exactly. | ||
func FindMatchingPresetID( | ||
ctx context.Context, | ||
store database.Store, | ||
templateVersionID uuid.UUID, | ||
parameterNames []string, | ||
parameterValues []string, | ||
) (uuid.UUID, error) { | ||
if len(parameterNames) != len(parameterValues) { | ||
return uuid.Nil, xerrors.New("parameter names and values must have the same length") | ||
} | ||
result, err := store.FindMatchingPresetID(ctx, database.FindMatchingPresetIDParams{ | ||
TemplateVersionID: templateVersionID, | ||
ParameterNames: parameterNames, | ||
ParameterValues: parameterValues, | ||
}) | ||
if err != nil { | ||
// Handle the case where no matching preset is found (no rows returned) | ||
if errors.Is(err, sql.ErrNoRows) { | ||
return uuid.Nil, nil | ||
} | ||
return uuid.Nil, xerrors.Errorf("find matching preset ID: %w", err) | ||
} | ||
return result, nil | ||
} |
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.