Skip to content

Commit 96ccbc7

Browse files
jopemachineclaude
andcommitted
refactor: merge admin deployment search back into the main layers
Fold DeploymentAdminRepository / DeploymentAdminService / DeploymentAdminProcessors back into DeploymentRepository / DeploymentService / DeploymentProcessors. admin_search_deployments now lives alongside the scoped search methods, distinguished only by its admin_ prefix and the absence of a scope filter — no dedicated admin classes. Drops the now-unused DEPLOYMENT_ADMIN_REPOSITORY metric layer. Also fix two rebase-induced CI breakages: - main renamed execute_batch_querier's scope= kwarg to scopes=; update the user/project scoped search calls to scopes=[scope]. - repoint the new sokovan deploying_rolling_back handler (and its test) at the common DeploymentLifecycleSubStep location, since this branch moved the enum off manager.data.deployment.types. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 52149cd commit 96ccbc7

15 files changed

Lines changed: 55 additions & 177 deletions

File tree

src/ai/backend/common/metrics/metric.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,6 @@ class LayerType(enum.StrEnum):
420420
AUDIT_LOG_REPOSITORY = "audit_log_repository"
421421
CONTAINER_REGISTRY_REPOSITORY = "container_registry_repository"
422422
DEPLOYMENT_REPOSITORY = "deployment_repository"
423-
DEPLOYMENT_ADMIN_REPOSITORY = "deployment_admin_repository"
424423
DOMAIN_REPOSITORY = "domain_repository"
425424
DOTFILE_REPOSITORY = "dotfile_repository"
426425
ETCD_CONFIG_REPOSITORY = "etcd_config_repository"

src/ai/backend/manager/api/adapters/deployment/adapter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ async def admin_search(
621621
"""Search deployments (admin, no scope)."""
622622
querier = self._build_deployment_querier(input)
623623
action_result = (
624-
await self._processors.deployment_admin.admin_search_deployments.wait_for_complete(
624+
await self._processors.deployment.admin_search_deployments.wait_for_complete(
625625
AdminSearchDeploymentsAction(querier=querier)
626626
)
627627
)
@@ -1370,7 +1370,7 @@ async def batch_load_by_ids(
13701370
conditions=[DeploymentConditions.by_ids(deployment_ids)],
13711371
)
13721372
action_result = (
1373-
await self._processors.deployment_admin.admin_search_deployments.wait_for_complete(
1373+
await self._processors.deployment.admin_search_deployments.wait_for_complete(
13741374
AdminSearchDeploymentsAction(querier=querier)
13751375
)
13761376
)

src/ai/backend/manager/repositories/deployment/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@
33
from ai.backend.manager.models.endpoint.conditions import DeploymentConditions
44
from ai.backend.manager.models.routing.conditions import RouteConditions
55

6-
from .admin_repository import DeploymentAdminRepository
76
from .repository import DeploymentRepository
87

98
__all__ = [
10-
"DeploymentAdminRepository",
119
"DeploymentRepository",
1210
"DeploymentConditions",
1311
"RouteConditions",

src/ai/backend/manager/repositories/deployment/admin_repository.py

Lines changed: 0 additions & 82 deletions
This file was deleted.

src/ai/backend/manager/repositories/deployment/db_source/db_source.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,7 +1135,7 @@ async def admin_search_deployments(
11351135
"""Search every endpoint without a scope filter, projecting each row
11361136
directly to ``ModelDeploymentData``.
11371137
1138-
Backs ``DeploymentAdminRepository.admin_search_deployments`` — the
1138+
Backs ``DeploymentRepository.admin_search_deployments`` — the
11391139
admin label makes the unscoped intent explicit at every layer of
11401140
the stack (db_source → repository → service).
11411141
"""
@@ -1166,7 +1166,7 @@ async def search_user_deployments(
11661166
11671167
Backs the v2 adapter's ``my_search`` path. Scope filter
11681168
(``EndpointRow.created_user == user_id``) is injected via
1169-
``execute_batch_querier``'s ``scope`` argument.
1169+
``execute_batch_querier``'s ``scopes`` argument.
11701170
"""
11711171
async with self._begin_readonly_session_read_committed() as db_sess:
11721172
query = sa.select(EndpointRow)
@@ -1175,7 +1175,7 @@ async def search_user_deployments(
11751175
db_sess,
11761176
query,
11771177
querier,
1178-
scope=scope,
1178+
scopes=[scope],
11791179
)
11801180

11811181
items = [row.EndpointRow.to_model_deployment_data() for row in result.rows]
@@ -1205,7 +1205,7 @@ async def search_project_deployments(
12051205
db_sess,
12061206
query,
12071207
querier,
1208-
scope=scope,
1208+
scopes=[scope],
12091209
)
12101210

12111211
items = [row.EndpointRow.to_model_deployment_data() for row in result.rows]

src/ai/backend/manager/repositories/deployment/repositories.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
from ai.backend.manager.repositories.types import RepositoryArgs
77

8-
from .admin_repository import DeploymentAdminRepository
98
from .repository import DeploymentRepository
109

1110

@@ -14,7 +13,6 @@ class DeploymentRepositories:
1413
"""Container for deployment-related repositories."""
1514

1615
repository: DeploymentRepository
17-
admin_repository: DeploymentAdminRepository
1816

1917
@classmethod
2018
def create(cls, args: RepositoryArgs) -> Self:
@@ -26,5 +24,4 @@ def create(cls, args: RepositoryArgs) -> Self:
2624
args.valkey_live_client,
2725
args.valkey_schedule_client,
2826
)
29-
admin_repository = DeploymentAdminRepository(args.db)
30-
return cls(repository=repository, admin_repository=admin_repository)
27+
return cls(repository=repository)

src/ai/backend/manager/repositories/deployment/repository.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,6 +1544,20 @@ async def get_route(
15441544
"""
15451545
return await self._db_source.get_route(route_id)
15461546

1547+
@deployment_repository_resilience.apply()
1548+
async def admin_search_deployments(
1549+
self,
1550+
querier: BatchQuerier,
1551+
) -> ModelDeploymentDataSearchResult:
1552+
"""Search every deployment without a scope filter (admin / DataLoader).
1553+
1554+
The absence of a scope filter is what makes this admin-only; callers
1555+
may still narrow the result through the querier's conditions. The
1556+
``admin_`` prefix is kept across db_source → repository → service so
1557+
the unscoped intent is obvious at every call site.
1558+
"""
1559+
return await self._db_source.admin_search_deployments(querier)
1560+
15471561
@deployment_repository_resilience.apply()
15481562
async def search_user_deployments(
15491563
self,

src/ai/backend/manager/services/deployment/actions/admin_search_deployments.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
class AdminSearchDeploymentsAction(DeploymentBaseAction):
1313
"""Search every deployment with no scope (superadmin path).
1414
15-
Routed through ``DeploymentAdminProcessors`` so callers make the
16-
admin intent explicit; scope-restricted variants live on the regular
17-
``DeploymentService`` and ``DeploymentRepository``.
15+
The ``admin_`` prefix makes the unscoped intent explicit; scope-restricted
16+
variants (``search_user_deployments`` / ``search_project_deployments``)
17+
live alongside this on the same ``DeploymentService`` /
18+
``DeploymentRepository`` / ``DeploymentProcessors``.
1819
"""
1920

2021
querier: BatchQuerier

src/ai/backend/manager/services/deployment/admin_service.py

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/ai/backend/manager/services/deployment/processors.py

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,6 @@
146146
)
147147

148148
if TYPE_CHECKING:
149-
from ai.backend.manager.services.deployment.admin_service import DeploymentAdminService
150149
from ai.backend.manager.services.deployment.service import DeploymentService
151150

152151

@@ -167,6 +166,9 @@ class DeploymentProcessors(AbstractProcessorPackage):
167166
destroy_deployment: SingleEntityActionProcessor[
168167
DestroyDeploymentAction, DestroyDeploymentActionResult
169168
]
169+
admin_search_deployments: ActionProcessor[
170+
AdminSearchDeploymentsAction, AdminSearchDeploymentsActionResult
171+
]
170172
search_user_deployments: ActionProcessor[
171173
SearchUserDeploymentsAction, SearchUserDeploymentsActionResult
172174
]
@@ -262,6 +264,9 @@ def __init__(
262264
self.destroy_deployment = SingleEntityActionProcessor(
263265
service.destroy_deployment, action_monitors, validators=rbac_single_entity_validators
264266
)
267+
self.admin_search_deployments = ActionProcessor(
268+
service.admin_search_deployments, action_monitors
269+
)
265270
self.search_user_deployments = ActionProcessor(
266271
service.search_user_deployments,
267272
action_monitors,
@@ -347,6 +352,7 @@ def supported_actions(self) -> list[ActionSpec]:
347352
UpdateDeploymentAction.spec(),
348353
ReplaceDeploymentOptionsAction.spec(),
349354
DestroyDeploymentAction.spec(),
355+
AdminSearchDeploymentsAction.spec(),
350356
SearchUserDeploymentsAction.spec(),
351357
SearchProjectDeploymentsAction.spec(),
352358
SearchProjectDeploymentSummaryAction.spec(),
@@ -382,31 +388,3 @@ def supported_actions(self) -> list[ActionSpec]:
382388
BulkDeleteAccessTokensAction.spec(),
383389
SearchAccessTokensAction.spec(),
384390
]
385-
386-
387-
class DeploymentAdminProcessors(AbstractProcessorPackage):
388-
"""Admin (no-scope) processors for deployments.
389-
390-
Counterpart of :class:`DeploymentProcessors` that owns the no-scope
391-
queries — admin search and the DataLoader batch path. Scoped reads
392-
stay on :class:`DeploymentProcessors`.
393-
"""
394-
395-
admin_search_deployments: ActionProcessor[
396-
AdminSearchDeploymentsAction, AdminSearchDeploymentsActionResult
397-
]
398-
399-
def __init__(
400-
self,
401-
service: DeploymentAdminService,
402-
action_monitors: list[ActionMonitor],
403-
) -> None:
404-
self.admin_search_deployments = ActionProcessor(
405-
service.admin_search_deployments, action_monitors
406-
)
407-
408-
@override
409-
def supported_actions(self) -> list[ActionSpec]:
410-
return [
411-
AdminSearchDeploymentsAction.spec(),
412-
]

0 commit comments

Comments
 (0)