generated from coulomb/repo-seed
131 lines
5.0 KiB
Python
131 lines
5.0 KiB
Python
"""In-memory asset registry repository."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import Iterable
|
|
|
|
from kontextual_engine.core import (
|
|
Actor,
|
|
AssetRepresentation,
|
|
AssetVersion,
|
|
AuditEvent,
|
|
KnowledgeAsset,
|
|
LifecycleState,
|
|
MetadataRecord,
|
|
RepresentationKind,
|
|
)
|
|
from kontextual_engine.errors import NotFoundError, ValidationError
|
|
|
|
|
|
@dataclass
|
|
class InMemoryAssetRegistryRepository:
|
|
actors: dict[str, Actor] = field(default_factory=dict)
|
|
assets: dict[str, KnowledgeAsset] = field(default_factory=dict)
|
|
representations: dict[str, AssetRepresentation] = field(default_factory=dict)
|
|
metadata_records: dict[str, list[MetadataRecord]] = field(default_factory=dict)
|
|
versions: dict[str, list[AssetVersion]] = field(default_factory=dict)
|
|
audit_events: dict[str, AuditEvent] = field(default_factory=dict)
|
|
|
|
def save_actor(self, actor: Actor) -> Actor:
|
|
self.actors[actor.id] = actor
|
|
return actor
|
|
|
|
def get_actor(self, actor_id: str) -> Actor:
|
|
try:
|
|
return self.actors[actor_id]
|
|
except KeyError as exc:
|
|
raise NotFoundError("Actor not found", details={"actor_id": actor_id}) from exc
|
|
|
|
def save_asset(self, asset: KnowledgeAsset) -> KnowledgeAsset:
|
|
self.assets[asset.id] = asset
|
|
return asset
|
|
|
|
def get_asset(self, asset_id: str) -> KnowledgeAsset:
|
|
try:
|
|
return self.assets[asset_id]
|
|
except KeyError as exc:
|
|
raise NotFoundError("Asset not found", details={"asset_id": asset_id}) from exc
|
|
|
|
def list_assets(
|
|
self,
|
|
*,
|
|
lifecycle: LifecycleState | None = None,
|
|
asset_type: str | None = None,
|
|
) -> list[KnowledgeAsset]:
|
|
assets: Iterable[KnowledgeAsset] = self.assets.values()
|
|
if lifecycle is not None:
|
|
assets = [asset for asset in assets if asset.lifecycle == lifecycle]
|
|
if asset_type is not None:
|
|
assets = [asset for asset in assets if asset.classification.asset_type == asset_type]
|
|
return sorted(assets, key=lambda asset: (asset.title, asset.id))
|
|
|
|
def save_representation(self, representation: AssetRepresentation) -> AssetRepresentation:
|
|
self.get_asset(representation.asset_id)
|
|
self.representations[representation.representation_id] = representation
|
|
return representation
|
|
|
|
def get_representation(self, representation_id: str) -> AssetRepresentation:
|
|
try:
|
|
return self.representations[representation_id]
|
|
except KeyError as exc:
|
|
raise NotFoundError(
|
|
"Representation not found",
|
|
details={"representation_id": representation_id},
|
|
) from exc
|
|
|
|
def list_representations(
|
|
self,
|
|
*,
|
|
asset_id: str | None = None,
|
|
kind: RepresentationKind | None = None,
|
|
) -> list[AssetRepresentation]:
|
|
representations: Iterable[AssetRepresentation] = self.representations.values()
|
|
if asset_id is not None:
|
|
representations = [item for item in representations if item.asset_id == asset_id]
|
|
if kind is not None:
|
|
representations = [item for item in representations if item.kind == kind]
|
|
return sorted(representations, key=lambda item: (item.asset_id, item.kind.value, item.representation_id))
|
|
|
|
def save_metadata_record(self, asset_id: str, record: MetadataRecord) -> MetadataRecord:
|
|
self.get_asset(asset_id)
|
|
self.metadata_records.setdefault(asset_id, []).append(record)
|
|
return record
|
|
|
|
def list_metadata_records(self, asset_id: str) -> list[MetadataRecord]:
|
|
self.get_asset(asset_id)
|
|
return list(self.metadata_records.get(asset_id, []))
|
|
|
|
def save_version(self, version: AssetVersion) -> AssetVersion:
|
|
self.get_asset(version.asset_id)
|
|
current = self.versions.setdefault(version.asset_id, [])
|
|
if any(existing.sequence == version.sequence for existing in current):
|
|
raise ValidationError(
|
|
"Version sequence already exists for asset",
|
|
details={"asset_id": version.asset_id, "sequence": version.sequence},
|
|
)
|
|
current.append(version)
|
|
return version
|
|
|
|
def list_versions(self, asset_id: str) -> list[AssetVersion]:
|
|
self.get_asset(asset_id)
|
|
return sorted(self.versions.get(asset_id, []), key=lambda version: version.sequence)
|
|
|
|
def save_audit_event(self, event: AuditEvent) -> AuditEvent:
|
|
self.audit_events[event.event_id] = event
|
|
return event
|
|
|
|
def list_audit_events(
|
|
self,
|
|
*,
|
|
target: str | None = None,
|
|
correlation_id: str | None = None,
|
|
) -> list[AuditEvent]:
|
|
events: Iterable[AuditEvent] = self.audit_events.values()
|
|
if target is not None:
|
|
events = [event for event in events if event.target == target]
|
|
if correlation_id is not None:
|
|
events = [event for event in events if event.correlation_id == correlation_id]
|
|
return sorted(events, key=lambda event: (event.occurred_at, event.event_id))
|
|
|