PMFlow/backend/app/services/signal_source_repair/mixin_data_access.py

82 lines
2.8 KiB
Python

"""Data-access helpers for signal source repair service."""
from __future__ import annotations
from .shared import Optional, SignalSourceRegistry, User, and_, select
class SignalSourceRepairDataAccessMixin:
"""Database read helpers for repair workflow."""
async def _load_registry(
self,
*,
tenant_id: int,
project_id: int,
registry_id: int,
) -> Optional[SignalSourceRegistry]:
return (
await self.db.execute(
select(SignalSourceRegistry)
.where(
and_(
SignalSourceRegistry.tenant_id == int(tenant_id),
SignalSourceRegistry.project_id == int(project_id),
SignalSourceRegistry.id == int(registry_id),
)
)
.limit(1)
)
).scalar_one_or_none()
async def _find_reusable_signal_id(
self,
*,
tenant_id: int,
project_id: int,
row: SignalSourceRegistry,
) -> Optional[int]:
target_key = self._normalize_identifier_key(row.source_identifier)
if not target_key:
return None
candidates = (
await self.db.execute(
select(SignalSourceRegistry)
.where(
and_(
SignalSourceRegistry.tenant_id == int(tenant_id),
SignalSourceRegistry.project_id == int(project_id),
SignalSourceRegistry.id != int(row.id),
SignalSourceRegistry.signal_id.is_not(None),
)
)
.order_by(SignalSourceRegistry.created_at.desc(), SignalSourceRegistry.id.desc())
.limit(50)
)
).scalars().all()
for candidate in candidates:
current_key = self._normalize_identifier_key(candidate.source_identifier)
if current_key and current_key == target_key:
return self._safe_int(candidate.signal_id)
for candidate in candidates:
current_key = self._normalize_identifier_key(candidate.source_identifier)
if current_key and (
current_key.endswith(target_key)
or target_key.endswith(current_key)
):
return self._safe_int(candidate.signal_id)
return None
async def _active_user_ids(self, *, tenant_id: int) -> list[int]:
rows = (
await self.db.execute(
select(User.id).where(
and_(
User.tenant_id == int(tenant_id),
User.is_active.is_(True),
)
)
)
).scalars().all()
return [int(item) for item in rows if item is not None]