refactor(recipe,validator): per-DataProvider sources + criteria-registry de-globalization#1107
Conversation
…stry de-globalization Thread an explicit DataProvider through the recipe loader, validator catalog, and criteria parsing so consumers can resolve against their own data source instead of the process-global provider/registry. Global shims are retained for back-compat (DefaultRegistry, ParseCriteria*, catalog.Load, LoadFromFile, config.ResolveCriteria) so existing callers are unaffected. - recipe: GetCriteriaRegistryFor(dp) per-provider registry + EvictCachedCriteriaRegistry; registry-aware parse + BuildCriteriaWithRegistry; LoadFromFileWithProvider; RecipeResult.DeepCopy/BindDataProvider - validator: catalog.LoadWithDataProvider(dp,...) + WithDataProvider option - config: ResolveCriteriaWithRegistry Foundation for migrating the CLI/REST consumers onto aicr.Client (#1077).
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Enterprise Run ID: 📒 Files selected for processing (3)
📝 Walkthrough<review_stack_artifact> </review_stack_artifact> 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pkg/validator/catalog/catalog.go`:
- Around line 72-77: The LoadWithDataProvider function performs unbounded I/O
via dp.ReadFile(...) and must accept a context so callers can enforce timeouts;
change the signature of LoadWithDataProvider(dp recipe.DataProvider, version,
commit string) to include ctx context.Context, update callers to pass a
timeout-bounded context from validator entrypoints, and replace the dp.ReadFile
call with the context-aware DataProvider method (e.g., dp.ReadFile(ctx,
"validators/catalog.yaml") or the provider's equivalent). Ensure you do not
introduce context.Background() anywhere in the implementation—propagate the
provided ctx through the read and any downstream calls and handle context errors
appropriately (cancel/return on ctx.Err()).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 7b94424c-f8da-4621-b32b-25a5451ceb76
📒 Files selected for processing (14)
pkg/config/resolve.gopkg/recipe/components.gopkg/recipe/criteria.gopkg/recipe/criteria_registry.gopkg/recipe/criteria_registry_test.gopkg/recipe/loader.gopkg/recipe/loader_provider_test.gopkg/recipe/metadata.gopkg/recipe/metadata_store.gopkg/validator/catalog/catalog.gopkg/validator/catalog/catalog_test.gopkg/validator/options.gopkg/validator/types.gopkg/validator/validator.go
Coverage Report ✅
Coverage BadgeMerging this branch changes the coverage (3 decrease, 1 increase)
Coverage by fileChanged files (no unit tests)
Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code. |
mchmarny
left a comment
There was a problem hiding this comment.
Clean foundation refactor — thanks for splitting this off, the per-provider isolation model is well-shaped and the doc comments are exceptional. Per-provider isolation test, eviction test, strict-per-registry test, and the marker-validator proof in TestLoadHonorsExplicitProvider together pin the behavior I'd want pinned. RecipeResult.DeepCopy handling nested Overrides via deepCopyAnyMap cleanly addresses the prior aliasing bug. All 32 checks green.
Four discussion points, none blocking:
- M1 (
criteria_registry.go):sync.Mapkeyed byDataProviderinterface needs the dynamic type to be comparable — worth one sentence in theDataProviderinterface godoc so external implementers don't trip a runtime panic. - M2 (
criteria.go): the newWith<X>Registry/BuildCriteriaWithRegistryship as a parallel API alongside the existingWith<X>/BuildCriteria— what's the long-term plan? EitherDeprecated:markers on the originals or a doc note on why both coexist. - M3 (
criteria_registry.go): cache-eviction wiring for the newcriteriaRegistryCachelives in #1108 — worth a forward reference in this PR's body so the cache lifecycle isn't a hidden assumption. - L1 (nit):
//nolint:staticcheckreference style varies (#983 Stage 2vs#983/#987); standardize.
Happy to take this as-is once M1/M2/M3 get a quick pass.
Address review feedback on #1107: - DataProvider interface godoc now states the comparability requirement (the dynamic type must be comparable per the Go language spec) so external implementers don't trip a runtime panic from the sync.Map keys used by metadata-store, component-registry, and criteria-registry caches (M1). - CriteriaOption and BuildCriteria godoc now correctly describe their relationship to RegistryCriteriaOption / BuildCriteriaWithRegistry, and explicitly point per-provider callers at the new path. Drops the misleading "shim over BuildCriteriaWithRegistry" claim that didn't match the actual call structure (M2). - catalog.go nolint:staticcheck reference style now matches criteria_registry.go: "back-compat fallback for pre-WithDataProvider callers (#983 Stage 2)" (L1). No functional change.
|
Pushed eac3ecf addressing M1/M2/L1 inline; updated PR body with a Cache lifecycle section addressing M3. Summary:
|
Summary
Thread an explicit
DataProviderthrough the recipe loader, validator catalog, and criteria parsing so consumers can resolve against their own data source instead of the process-global provider/registry. Foundation (PR 1 of 2) for migrating the CLI/REST ontoaicr.Client(#1077).What changes
recipe:GetCriteriaRegistryFor(dp)per-provider criteria registry (+EvictCachedCriteriaRegistry); registry-aware parsing +BuildCriteriaWithRegistry;LoadFromFileWithProvider;RecipeResult.DeepCopy/BindDataProvider.validator:catalog.LoadWithDataProvider(dp, …)+WithDataProvideroption.config:ResolveCriteriaWithRegistry.Behavior
No consumer-facing behavior change. Global shims are retained for back-compat (
DefaultRegistry,ParseCriteria*,catalog.Load,LoadFromFile,config.ResolveCriteria) so existing callers compile and behave identically. The criteria-registry global is distinct fromSetDataProvider/GetDataProvider(#987, closed); shim removal will be tracked separately.Cache lifecycle
This PR adds
criteriaRegistryCache(per-DataProvider,sync.Map-backed, lazy viasync.Once) alongside the existingregistryCache(pkg/recipe/components.go) andstoreCache(pkg/recipe/metadata_store.go). All three caches grow on first access perDataProviderand haveEvict*primitives but no automatic eviction from this PR alone.Client.Close()wiring that callsEvictCachedCriteriaRegistry,EvictCachedStore, andEvictCachedRegistryfor the Client'sDataProviderlands in #1108. Long-running consumers that churn through Clients should wait for #1108 (or evict manually) to avoid monotonic cache growth.Testing
go build ./...,go test -race ./pkg/recipe/... ./pkg/validator/... ./pkg/config/..., andgolangci-lintall pass standalone.Relates to #1077. PR 2 (CLI/API migration) stacks on this branch.