perf(tenancy): batch list-page summaries

This commit is contained in:
2026-07-30 01:15:28 +02:00
parent 922b3f43b7
commit b40615f8ac
+35 -8
View File
@@ -1,5 +1,6 @@
from __future__ import annotations from __future__ import annotations
from collections.abc import Mapping, Sequence
from typing import Any from typing import Any
from fastapi import APIRouter, Body, Depends, HTTPException, Query, status from fastapi import APIRouter, Body, Depends, HTTPException, Query, status
@@ -33,6 +34,7 @@ from govoplan_core.tenancy.service import (
assert_tenant_governance_override_allowed, assert_tenant_governance_override_allowed,
effective_tenant_governance, effective_tenant_governance,
tenant_counts, tenant_counts,
tenant_counts_many,
) )
from govoplan_tenancy.backend.db.models import Tenant from govoplan_tenancy.backend.db.models import Tenant
from govoplan_tenancy.backend.lifecycle import ( from govoplan_tenancy.backend.lifecycle import (
@@ -125,7 +127,12 @@ def _tenant_or_404(session: Session, tenant_id: str) -> Tenant:
return tenant return tenant
def _tenant_item(session: Session, tenant: Tenant) -> TenantAdminItem: def _tenant_item(
session: Session,
tenant: Tenant,
*,
counts: Mapping[str, int] | None = None,
) -> TenantAdminItem:
governance = effective_tenant_governance(session, tenant) governance = effective_tenant_governance(session, tenant)
return TenantAdminItem( return TenantAdminItem(
id=tenant.id, id=tenant.id,
@@ -143,16 +150,36 @@ def _tenant_item(session: Session, tenant: Tenant) -> TenantAdminItem:
"allow_api_keys": governance.allow_api_keys, "allow_api_keys": governance.allow_api_keys,
}, },
is_active=tenant.is_active, is_active=tenant.is_active,
counts=tenant_counts( counts=(
session, dict(counts)
tenant.id, if counts is not None
module_ids=("campaigns", "files"), else tenant_counts(
session,
tenant.id,
module_ids=("campaigns", "files"),
)
), ),
created_at=tenant.created_at, created_at=tenant.created_at,
updated_at=tenant.updated_at, updated_at=tenant.updated_at,
) )
def _tenant_items(session: Session, tenants: Sequence[Tenant]) -> list[TenantAdminItem]:
counts_by_tenant = tenant_counts_many(
session,
[tenant.id for tenant in tenants],
module_ids=("campaigns", "files"),
)
return [
_tenant_item(
session,
tenant,
counts=counts_by_tenant.get(tenant.id, {}),
)
for tenant in tenants
]
def _tenant_deletion_plan(session: Session, tenant: Tenant, principal: ApiPrincipal, *, mode: str = "retire") -> TenantDeletionPlanResponse: def _tenant_deletion_plan(session: Session, tenant: Tenant, principal: ApiPrincipal, *, mode: str = "retire") -> TenantDeletionPlanResponse:
issues: list[TenantLifecycleIssue] = [] issues: list[TenantLifecycleIssue] = []
counts = tenant_counts(session, tenant.id) counts = tenant_counts(session, tenant.id)
@@ -480,7 +507,7 @@ def list_tenants(
page_size=page_size, page_size=page_size,
) )
return TenantListResponse( return TenantListResponse(
tenants=[_tenant_item(session, tenant) for tenant in tenants], tenants=_tenant_items(session, tenants),
**pagination, **pagination,
) )
@@ -504,7 +531,7 @@ def _full_tenant_list_delta_response(
) )
has_more = page < pagination["pages"] has_more = page < pagination["pages"]
return TenantListDeltaResponse( return TenantListDeltaResponse(
tenants=[_tenant_item(session, tenant) for tenant in tenants], tenants=_tenant_items(session, tenants),
deleted=[], deleted=[],
watermark=( watermark=(
_tenant_full_cursor( _tenant_full_cursor(
@@ -544,7 +571,7 @@ def list_tenants_delta(
tenants = session.query(Tenant).filter(Tenant.id.in_(changed_ids)).order_by(Tenant.name.asc()).all() tenants = session.query(Tenant).filter(Tenant.id.in_(changed_ids)).order_by(Tenant.name.asc()).all()
visible_tenant_ids = {tenant.id for tenant in tenants} visible_tenant_ids = {tenant.id for tenant in tenants}
return TenantListDeltaResponse( return TenantListDeltaResponse(
tenants=[_tenant_item(session, tenant) for tenant in tenants], tenants=_tenant_items(session, tenants),
deleted=_tenant_list_deleted_entries(entries, visible_tenant_ids), deleted=_tenant_list_deleted_entries(entries, visible_tenant_ids),
watermark=_tenant_list_response_watermark(session, entries=entries, has_more=has_more), watermark=_tenant_list_response_watermark(session, entries=entries, has_more=has_more),
has_more=has_more, has_more=has_more,