You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

78 lines
3.0 KiB

from __future__ import annotations
from fastapi import APIRouter, Depends
from fastapi import Query
from app.api.dependencies import get_policy_service
from app.schemas.policy import (
PlacementDecisionBackendSummary,
PlacementDecisionResponse,
PlacementPolicyListResponse,
PlacementPolicyMutationResponse,
PlacementPolicySummary,
UpsertPlacementPolicyRequest,
)
from app.services.policy_service import PolicyService
router = APIRouter()
def _policy_to_summary(policy) -> PlacementPolicySummary:
return PlacementPolicySummary(
id=policy.id,
file_class=policy.file_class,
require_local=policy.require_local,
stable_replica_count=policy.stable_replica_count,
opportunistic_replica_count=policy.opportunistic_replica_count,
preferred_backend_ids=PolicyService._decode_backend_ids(policy.preferred_backend_ids_json),
excluded_backend_ids=PolicyService._decode_backend_ids(policy.excluded_backend_ids_json),
max_non_local_size_bytes=policy.max_non_local_size_bytes,
created_at=policy.created_at,
updated_at=policy.updated_at,
)
@router.get("/placement", response_model=PlacementPolicyListResponse)
async def list_placement_policies(
service: PolicyService = Depends(get_policy_service),
) -> PlacementPolicyListResponse:
policies = await service.list_policies()
return PlacementPolicyListResponse(items=[_policy_to_summary(policy) for policy in policies])
@router.get("/placement/preview", response_model=PlacementDecisionResponse)
async def preview_placement_decision(
mime_type: str | None = Query(default=None),
size_bytes: int | None = Query(default=None, ge=0),
service: PolicyService = Depends(get_policy_service),
) -> PlacementDecisionResponse:
decision = await service.get_placement_decision(mime_type, size_bytes=size_bytes)
return PlacementDecisionResponse(
file_class=decision.file_class,
mime_type=mime_type,
size_bytes=size_bytes,
non_local_allowed=decision.non_local_allowed,
policy=_policy_to_summary(decision.policy),
selected_backends=[
PlacementDecisionBackendSummary.model_validate(backend, from_attributes=True)
for backend in decision.backends
],
)
@router.put("/placement/{file_class}", response_model=PlacementPolicyMutationResponse)
async def upsert_placement_policy(
file_class: str,
payload: UpsertPlacementPolicyRequest,
service: PolicyService = Depends(get_policy_service),
) -> PlacementPolicyMutationResponse:
policy = await service.upsert_policy(
file_class=file_class,
require_local=payload.require_local,
stable_replica_count=payload.stable_replica_count,
opportunistic_replica_count=payload.opportunistic_replica_count,
preferred_backend_ids=payload.preferred_backend_ids,
excluded_backend_ids=payload.excluded_backend_ids,
max_non_local_size_bytes=payload.max_non_local_size_bytes,
)
return PlacementPolicyMutationResponse(policy=_policy_to_summary(policy))