Skip to content

feat(BA-6553): add app_config_fragments repository layer#12307

Merged
fregataa merged 16 commits into
mainfrom
feat/BA-6553-app-config-fragments-repository
Jun 23, 2026
Merged

feat(BA-6553): add app_config_fragments repository layer#12307
fregataa merged 16 commits into
mainfrom
feat/BA-6553-app-config-fragments-repository

Conversation

@jopemachine

@jopemachine jopemachine commented Jun 18, 2026

Copy link
Copy Markdown
Member

📚 Stacked PRs

Part of the AppConfigFragment / AppConfig stack under BEP-1052 (epic BA-5781). Merge in order:

  1. feat(BA-6552): add app_config_fragments DB model and Alembic migration #12306feat(BA-6552): app_config_fragments DB model and Alembic migration
  2. 👉 feat(BA-6553): add app_config_fragments repository layer #12307feat(BA-6553): repository layer ← you are here
  3. feat(BA-6554): add app_config_fragment service layer #12358feat(BA-6554): service layer (admin/self write paths, allow-list write-gate)
  4. feat(BA-6555): AppConfig merge engine + resolve service (service layer) #12359feat(BA-6555): merge engine (deep-merge across applicable fragments)

Summary

  • Add AppConfigFragmentRepository: create / get_by_id / update / purge / admin_search / scoped_search, over a dedicated AppConfigFragmentDBSource + DBOpsProvider.
  • Rank assignment: create assigns the next rank within a config_name race-free via create_with_next_value (locking the parent app_config_definitions row; RANK_GAP=100 leaves room to re-order). update may set rank explicitly for admin re-ordering, matching BEP-1052.
  • Search: admin_search (superadmin/internal, unscoped) and scoped_search (restricted to ConfigNameSearchScope, whose existence check rejects an unregistered config_name).
  • Query conditions/orders (config_name, scope_type, scope_id, created_at/updated_at, id-cursor) and the AppConfigFragmentNotFound error.
  • Real-DB with_tables tests cover create/get, update (+missing), purge (+missing), search/pagination, scope_type/scope_id filters, rank ordering, the unique (config_name, scope_type, scope_id) violation, rank auto-assignment, and scoped_search.

Notes

  • The global repository aggregator wiring is deferred to the REST PR (BA-6556), mirroring AppConfigDefinition/AppConfigAllowList.
  • Update/purge are id-based (the db_source builds the Updater/Purger internally), consistent with the id-based purge established in the AppConfigAllowList stack.

Resolves BA-6553.

@github-actions github-actions Bot added size:XL 500~ LoC comp:manager Related to Manager component labels Jun 18, 2026
@jopemachine jopemachine force-pushed the feat/BA-6552-app-config-fragments-model branch from ee2522e to e5fdd83 Compare June 19, 2026 01:01
@jopemachine jopemachine force-pushed the feat/BA-6553-app-config-fragments-repository branch from 3096cd0 to 2894d9c Compare June 19, 2026 01:01
@jopemachine jopemachine force-pushed the feat/BA-6552-app-config-fragments-model branch from e5fdd83 to 7fa8339 Compare June 22, 2026 07:52
@jopemachine jopemachine force-pushed the feat/BA-6553-app-config-fragments-repository branch from 2894d9c to 8675751 Compare June 22, 2026 08:06
Base automatically changed from feat/BA-6552-app-config-fragments-model to main June 22, 2026 08:11
@jopemachine jopemachine force-pushed the feat/BA-6553-app-config-fragments-repository branch from 8675751 to 792f33d Compare June 22, 2026 08:13
jopemachine and others added 3 commits June 22, 2026 17:20
Add the AppConfigFragmentRepository (create / get / update / search / purge)
over a dedicated db_source and DBOpsProvider. Fragments support update
(unlike definition/allow-list) and carry a rank: create assigns the next
rank within a config_name race-free via create_with_next_value (locking the
parent app_config_definitions row), and update may set rank for re-ordering.
Adds an applicable_fragments query (public + the user's domain + user
fragments, ordered by rank) for the upcoming merge engine, plus query
conditions/orders and the AppConfigFragmentNotFound error.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…mainID/UserID

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@jopemachine jopemachine force-pushed the feat/BA-6553-app-config-fragments-repository branch from 792f33d to 520d4e5 Compare June 22, 2026 08:20
Comment thread src/ai/backend/manager/repositories/app_config_fragment/repository.py Outdated
- Introduce typed next-value dependency (AppConfigFragmentCreateDependency /
  DeploymentRevisionPresetCreateDependency) instead of a bare int passed to
  build_row; execute_next_value_creator now takes a build_dependency factory so
  each domain owns an extensible dependency type.
- Inject pre-created fragments via fixtures (existing_fragment / seeded_fragments)
  in repository tests instead of calling create inline in non-create tests.
- Drop applicable_fragments from the repository/db_source per review.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
jopemachine and others added 3 commits June 23, 2026 10:51
Match the repository convention used everywhere else (model_card, object_storage,
project_resource_policy, etc.): update() receives an `Updater[Row]` (bundling the
spec and pk_value), mirroring create()/purge() taking Creator/Purger — instead of
separate (fragment_id, spec) params.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Mirror create()/update() and the convention used elsewhere (allow_list, etc.):
purge() receives a `Purger[Row]` instead of a bare fragment_id, so the caller
composes the spec/identifier object.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Follow the two-variant search convention: admin_search (superadmin/internal,
batch_query_in_global, no scope) and scoped_search (batch_query_with_scopes,
restricted to the given scopes). Add ConfigNameSearchScope (types.py) so a search
can be scoped to one config_name; its existence check rejects an unregistered
config_name up front.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Comment thread src/ai/backend/manager/repositories/app_config_fragment/db_source/db_source.py Outdated
jopemachine and others added 3 commits June 23, 2026 11:23
Drop the per-domain dependency wrapper types and the build_dependency factory;
keep the original convention where DependentCreatorSpec.build_row receives the
computed next rank as a bare int (next_rank: int). execute_next_value_creator /
create_with_next_value go back to DependentCreatorSpec[int, TRow].

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Drop the non-conventional _to_search_result staticmethod helper; build the
AppConfigFragmentSearchResult inline in admin_search/scoped_search like every other
db_source (model_card, audit_log). Removes the awkward BatchQuerierResult[sa.Row[Any]]
typing and now-unused imports.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Follow the repository-test convention (model_card): each input is its own fixture
that inserts the row directly via db_sess.add (no repository.create for setup, no
inline spec list). Tests inject only the fixtures they need and derive expectations
from them.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
jopemachine and others added 3 commits June 23, 2026 11:47
Replace the per-input fixtures and _seed_*/_spec helpers with a few scenario
fixtures (theme_registered, existing_fragment, seeded_fragments) that inline the
direct db_sess.add seeding and are injected once per test. Tests derive their
expectations from the injected scenario.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Rename existing_fragment -> domain_scoped_fragment and seeded_fragments ->
fragments_across_scopes so each fixture reads as the test situation it sets up.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Wrap every repository method with the repository resilience policy (metrics +
fixed-backoff retry, BackendAIError treated as non-retryable), matching the
convention used across the repository layer. Add the APP_CONFIG_FRAGMENT_REPOSITORY
LayerType for the metric label.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@github-actions github-actions Bot added the comp:common Related to Common component label Jun 23, 2026
Copilot AI review requested due to automatic review settings June 23, 2026 03:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces the initial repository-layer implementation for app_config_fragments (part of the BEP-1052 AppConfig stack), including CRUD-style DB operations, search/scoping primitives, and real-DB unit tests. It also aligns related AppConfig repositories with the same resilience/metrics instrumentation pattern and registers new metric layer identifiers.

Changes:

  • Add AppConfigFragmentRepository backed by AppConfigFragmentDBSource, plus creator/updater specs and scoped-search support.
  • Add query condition/order helpers for AppConfigFragmentRow and a AppConfigFragmentSearchResult DTO.
  • Add real-DB with_tables unit tests and register new repository/db-source LayerType metric identifiers (and apply resilience decorators to app_config_definition/allow_list repos & db sources).

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/unit/manager/repositories/app_config_fragment/test_repository.py Real-DB repository tests for create/get/update/purge and search/scoped-search behavior
tests/unit/manager/repositories/app_config_fragment/BUILD Adds Pants target for the new test module
tests/unit/manager/repositories/app_config_fragment/init.py Package marker for the new test directory
src/ai/backend/manager/repositories/app_config_fragment/creators.py Creator spec for rank-assigned fragment creation
src/ai/backend/manager/repositories/app_config_fragment/updaters.py Updater spec for config replacement and optional rank update
src/ai/backend/manager/repositories/app_config_fragment/types.py Adds a ConfigNameSearchScope with existence checks
src/ai/backend/manager/repositories/app_config_fragment/db_source/db_source.py DBSource implementation for create/get/update/purge/admin_search/scoped_search + next-rank policy
src/ai/backend/manager/repositories/app_config_fragment/db_source/init.py Exposes AppConfigFragmentDBSource
src/ai/backend/manager/repositories/app_config_fragment/repository.py Repository facade with resilience wrapper methods
src/ai/backend/manager/repositories/app_config_fragment/repositories.py Repository bundle factory (local aggregator)
src/ai/backend/manager/models/app_config_fragment/conditions.py Condition helpers for filtering + cursor pagination
src/ai/backend/manager/models/app_config_fragment/orders.py Order helpers for sorting fragment queries
src/ai/backend/manager/errors/app_config.py Adds AppConfigFragmentNotFound error type
src/ai/backend/manager/data/app_config_fragment/types.py Adds AppConfigFragmentSearchResult DTO
src/ai/backend/common/metrics/metric.py Registers new LayerType entries for app_config repositories/db-sources
src/ai/backend/manager/repositories/app_config_definition/repository.py Applies resilience wrapper to existing repository methods
src/ai/backend/manager/repositories/app_config_definition/db_source/db_source.py Applies resilience wrapper to existing DBSource methods
src/ai/backend/manager/repositories/app_config_allow_list/repository.py Applies resilience wrapper to existing repository methods
src/ai/backend/manager/repositories/app_config_allow_list/db_source/db_source.py Applies resilience wrapper to existing DBSource methods
changes/12307.feature.md Towncrier news fragment for this feature

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread changes/12307.feature.md Outdated
The applicable_fragments query was removed from this PR; the news fragment now
lists only what ships (create/get/update/admin_search/scoped_search/purge + rank).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@fregataa fregataa merged commit c5a8b42 into main Jun 23, 2026
36 checks passed
@fregataa fregataa deleted the feat/BA-6553-app-config-fragments-repository branch June 23, 2026 03:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp:common Related to Common component comp:manager Related to Manager component size:XL 500~ LoC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants