Skip to content

Commit a95a7fb

Browse files
jopemachineclaude
andcommitted
refactor(BA-5829): split AppConfig merged-view into its own adapter; drop scoped GQL root
Per review on PR #11285: - Split the merged-view (AppConfig, BEP-1052 §5) surface and the self-service `my_bulk_*` writes out of `AppConfigFragmentAdapter` into a new `AppConfigAdapter`. Each adapter now handles a single domain DTO surface, matching the project convention. Both adapters share the same `app_config_fragment` service processors — splitting only the transport layer. - Drop the `scoped_app_config_fragments` GQL root resolver. BEP-1052 exposes the scope-bound list as child fields on `DomainV2.appConfigFragments` / `UserV2.appConfigFragments`, not as a root field. The scope-bound REST endpoint `POST /v2/app-config-fragments/{scope_type}/{scope_id}/search` continues to use `AppConfigFragmentAdapter.search()` directly. - Update the GQL resolvers (`my_app_configs`, `admin_app_configs`, `bulk_create_my_app_config_fragments`, `bulk_update_my_app_config_fragments`) to call the new `info.context.adapters.app_config` adapter. - Wire the new `app_config` field through `Adapters.__init__` and `Adapters.create()`. - DataLoader now uses `AppConfigFragmentFilter(id=UUIDFilter(...))` per the new filter shape. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent d9c05be commit a95a7fb

9 files changed

Lines changed: 71 additions & 307 deletions

File tree

src/ai/backend/manager/api/adapters/app_config.py

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""AppConfig (merged view) domain adapter
1+
"""AppConfig (merged view) domain adapter — BEP-1052 §5.
22
33
Reads the per-user merged AppConfig view and writes the underlying USER
44
fragments via the same `app_config_fragment` service processors. The
@@ -19,15 +19,15 @@
1919
)
2020
from ai.backend.common.dto.manager.v2.app_config.response import (
2121
AppConfigNode,
22+
BulkCreateMyAppConfigFragmentsPayload,
23+
BulkUpdateMyAppConfigFragmentsPayload,
2224
GetUserAppConfigPayload,
23-
MyBulkCreateAppConfigFragmentsPayload,
24-
MyBulkUpdateAppConfigFragmentsPayload,
2525
SearchAppConfigsPayload,
2626
)
2727
from ai.backend.common.dto.manager.v2.app_config.types import AppConfigOrderField, OrderDirection
2828
from ai.backend.common.dto.manager.v2.app_config_fragment.request import (
29-
MyBulkCreateAppConfigFragmentsInput,
30-
MyBulkUpdateAppConfigFragmentsInput,
29+
BulkCreateMyAppConfigFragmentsInput,
30+
BulkUpdateMyAppConfigFragmentsInput,
3131
)
3232
from ai.backend.common.dto.manager.v2.app_config_fragment.response import (
3333
AppConfigFragmentBulkError,
@@ -52,14 +52,14 @@
5252
from ai.backend.manager.services.app_config_fragment.actions.admin_search_app_configs import (
5353
AdminSearchAppConfigsAction,
5454
)
55-
from ai.backend.manager.services.app_config_fragment.actions.get_user_app_config import (
56-
GetUserAppConfigAction,
55+
from ai.backend.manager.services.app_config_fragment.actions.bulk_create_my import (
56+
BulkCreateMyAppConfigFragmentsAction,
5757
)
58-
from ai.backend.manager.services.app_config_fragment.actions.my_bulk_create import (
59-
MyBulkCreateAppConfigFragmentsAction,
58+
from ai.backend.manager.services.app_config_fragment.actions.bulk_update_my import (
59+
BulkUpdateMyAppConfigFragmentsAction,
6060
)
61-
from ai.backend.manager.services.app_config_fragment.actions.my_bulk_update import (
62-
MyBulkUpdateAppConfigFragmentsAction,
61+
from ai.backend.manager.services.app_config_fragment.actions.get_user_app_config import (
62+
GetUserAppConfigAction,
6363
)
6464
from ai.backend.manager.services.app_config_fragment.actions.search_user_app_configs import (
6565
SearchUserAppConfigsAction,
@@ -69,7 +69,7 @@
6969

7070

7171
class AppConfigAdapter(BaseAdapter):
72-
"""Adapter for the merged AppConfig view.
72+
"""Adapter for the merged AppConfig view (BEP-1052 §5).
7373
7474
Backed by the `app_config_fragment` service processors — the merged
7575
view is computed from raw fragments — but exposed as a separate
@@ -146,41 +146,55 @@ async def admin_search_app_configs(
146146
has_previous_page=result.has_previous_page,
147147
)
148148

149-
# ── Self-service bulk writes ───────────────────────
149+
# ── Self-service bulk writes (BEP-1052 §3) ───────────────────────
150150
#
151151
# Each bulk processor returns a `BulkProcessResult[T]` whose
152152
# `.result` field is the underlying `*ActionResult` produced by the
153153
# service. We discard the validator-decision trail here — RBAC
154154
# reasons travel back through the per-item `failed` list.
155155

156156
async def my_bulk_create(
157-
self, input: MyBulkCreateAppConfigFragmentsInput
158-
) -> MyBulkCreateAppConfigFragmentsPayload:
157+
self, input: BulkCreateMyAppConfigFragmentsInput
158+
) -> BulkCreateMyAppConfigFragmentsPayload:
159+
me = current_user()
160+
if me is None:
161+
raise UnreachableError("User context is not available")
159162
items = [
160163
MyAppConfigFragmentBulkItem(name=item.name, extra_config=dict(item.extra_config))
161164
for item in input.items
162165
]
163-
wrapper = await self._processors.app_config_fragment.my_bulk_create.wait_for_complete(
164-
MyBulkCreateAppConfigFragmentsAction(entity_ids=[], items=items)
166+
wrapper = await self._processors.app_config_fragment.bulk_create_my.wait_for_complete(
167+
BulkCreateMyAppConfigFragmentsAction(
168+
entity_ids=[],
169+
user_id=me.user_id,
170+
items=items,
171+
)
165172
)
166173
result = wrapper.result
167-
return MyBulkCreateAppConfigFragmentsPayload(
174+
return BulkCreateMyAppConfigFragmentsPayload(
168175
created=[self._data_to_dto(item) for item in result.created],
169176
failed=[self._bulk_error_to_dto(err) for err in result.failed],
170177
)
171178

172179
async def my_bulk_update(
173-
self, input: MyBulkUpdateAppConfigFragmentsInput
174-
) -> MyBulkUpdateAppConfigFragmentsPayload:
180+
self, input: BulkUpdateMyAppConfigFragmentsInput
181+
) -> BulkUpdateMyAppConfigFragmentsPayload:
182+
me = current_user()
183+
if me is None:
184+
raise UnreachableError("User context is not available")
175185
items = [
176186
MyAppConfigFragmentBulkItem(name=item.name, extra_config=dict(item.extra_config))
177187
for item in input.items
178188
]
179-
wrapper = await self._processors.app_config_fragment.my_bulk_update.wait_for_complete(
180-
MyBulkUpdateAppConfigFragmentsAction(entity_ids=[], items=items)
189+
wrapper = await self._processors.app_config_fragment.bulk_update_my.wait_for_complete(
190+
BulkUpdateMyAppConfigFragmentsAction(
191+
entity_ids=[],
192+
user_id=me.user_id,
193+
items=items,
194+
)
181195
)
182196
result = wrapper.result
183-
return MyBulkUpdateAppConfigFragmentsPayload(
197+
return BulkUpdateMyAppConfigFragmentsPayload(
184198
updated=[self._data_to_dto(item) for item in result.updated],
185199
failed=[self._bulk_error_to_dto(err) for err in result.failed],
186200
)

0 commit comments

Comments
 (0)