134 lines
4.3 KiB
Python
134 lines
4.3 KiB
Python
from __future__ import annotations
|
|
|
|
from collections import defaultdict
|
|
from datetime import UTC, datetime
|
|
|
|
from sqlalchemy import or_, select
|
|
from sqlalchemy.orm import Session
|
|
|
|
from govoplan_core.core.provider_governance import (
|
|
ExternalProviderRuntimeState,
|
|
ExternalProviderStateContext,
|
|
)
|
|
from govoplan_files.backend.db.models import FileConnectorProfile, FileConnectorSpace
|
|
from govoplan_files.backend.storage.connector_providers import (
|
|
ConnectorProviderDescriptor,
|
|
connector_provider_descriptors,
|
|
)
|
|
|
|
|
|
REMOTE_STORAGE_PROVIDER_ID = "files.remote_storage"
|
|
|
|
|
|
def remote_storage_provider_states(
|
|
context: ExternalProviderStateContext,
|
|
) -> tuple[ExternalProviderRuntimeState, ...]:
|
|
if not isinstance(context.session, Session):
|
|
raise RuntimeError("Files provider state requires a database session.")
|
|
statement = select(FileConnectorProfile)
|
|
if context.tenant_id is not None:
|
|
statement = statement.where(
|
|
or_(
|
|
FileConnectorProfile.tenant_id.is_(None),
|
|
FileConnectorProfile.tenant_id == context.tenant_id,
|
|
)
|
|
)
|
|
profiles = tuple(
|
|
context.session.scalars(
|
|
statement.order_by(
|
|
FileConnectorProfile.tenant_id,
|
|
FileConnectorProfile.id,
|
|
).limit(context.max_items + 1)
|
|
)
|
|
)
|
|
if not profiles:
|
|
return ()
|
|
|
|
profile_ids = tuple(item.id for item in profiles)
|
|
space_statement = select(FileConnectorSpace).where(
|
|
FileConnectorSpace.connector_profile_id.in_(profile_ids),
|
|
FileConnectorSpace.deleted_at.is_(None),
|
|
)
|
|
if context.tenant_id is not None:
|
|
space_statement = space_statement.where(
|
|
FileConnectorSpace.tenant_id == context.tenant_id
|
|
)
|
|
spaces_by_profile: dict[str, list[FileConnectorSpace]] = defaultdict(list)
|
|
for space in context.session.scalars(space_statement):
|
|
spaces_by_profile[space.connector_profile_id].append(space)
|
|
|
|
descriptors = {
|
|
item.provider: item for item in connector_provider_descriptors()
|
|
}
|
|
observed_at = datetime.now(UTC)
|
|
return tuple(
|
|
_profile_state(
|
|
profile,
|
|
spaces=spaces_by_profile.get(profile.id, []),
|
|
descriptor=descriptors.get(profile.provider),
|
|
observed_at=observed_at,
|
|
)
|
|
for profile in profiles
|
|
)
|
|
|
|
|
|
def _profile_state(
|
|
profile: FileConnectorProfile,
|
|
*,
|
|
spaces: list[FileConnectorSpace],
|
|
descriptor: ConnectorProviderDescriptor | None,
|
|
observed_at: datetime,
|
|
) -> ExternalProviderRuntimeState:
|
|
active_spaces = tuple(item for item in spaces if item.is_active)
|
|
active = bool(profile.enabled)
|
|
implementation_ready = bool(
|
|
descriptor is not None and descriptor.implemented and descriptor.installed
|
|
)
|
|
health = (
|
|
"inactive"
|
|
if not active
|
|
else "error"
|
|
if not implementation_ready
|
|
else "unknown"
|
|
)
|
|
recovery = (
|
|
"not_applicable"
|
|
if not active
|
|
else "unsupported"
|
|
if not implementation_ready
|
|
else "attention"
|
|
)
|
|
detail = (
|
|
"Remote-storage connector profile is disabled."
|
|
if not active
|
|
else "The configured provider is not available in this runtime."
|
|
if not implementation_ready
|
|
else "Software support is available; no live remote health observation is retained."
|
|
)
|
|
return ExternalProviderRuntimeState(
|
|
provider_id=REMOTE_STORAGE_PROVIDER_ID,
|
|
binding_ref=f"files:connector-profile:{profile.id}",
|
|
authority_mode="external_mirror",
|
|
observed_at=observed_at,
|
|
configured=True,
|
|
active=active,
|
|
health=health,
|
|
freshness="unknown" if active else "not_applicable",
|
|
conflict="not_applicable",
|
|
recovery=recovery,
|
|
detail=detail,
|
|
metrics={
|
|
"provider": profile.provider,
|
|
"configured_spaces": len(spaces),
|
|
"active_spaces": len(active_spaces),
|
|
"write_requested_spaces": sum(
|
|
1 for item in active_spaces if not item.read_only
|
|
),
|
|
"software_implemented": bool(descriptor and descriptor.implemented),
|
|
"optional_dependency_available": bool(descriptor and descriptor.installed),
|
|
},
|
|
)
|
|
|
|
|
|
__all__ = ["REMOTE_STORAGE_PROVIDER_ID", "remote_storage_provider_states"]
|