Add Fabric graph read model ingest

This commit is contained in:
2026-05-23 21:17:58 +02:00
parent 52d456a7a1
commit ec5742543c
10 changed files with 1439 additions and 5 deletions

View File

@@ -22,6 +22,7 @@ from api.models.doi_cache import DOICache
from api.models.token_event import TokenEvent
from api.models.interface_change import InterfaceChange
from api.models.workplan_launch_request import WorkplanLaunchRequest
from api.models.fabric_graph import FabricGraphImport, FabricGraphNode, FabricGraphEdge
__all__ = [
"Base",
@@ -48,4 +49,5 @@ __all__ = [
"TokenEvent",
"InterfaceChange",
"WorkplanLaunchRequest",
"FabricGraphImport", "FabricGraphNode", "FabricGraphEdge",
]

110
api/models/fabric_graph.py Normal file
View File

@@ -0,0 +1,110 @@
import uuid
from datetime import datetime
from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, String, Text, UniqueConstraint
from sqlalchemy.dialects.postgresql import JSONB, UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship
from api.models.base import Base, TimestampMixin, new_uuid
class FabricGraphImport(Base, TimestampMixin):
__tablename__ = "fabric_graph_imports"
__table_args__ = (
UniqueConstraint(
"source_repo_slug",
"content_hash",
name="uq_fabric_graph_imports_source_hash",
),
)
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), primary_key=True, default=new_uuid
)
source_repo_slug: Mapped[str] = mapped_column(String(100), nullable=False, index=True)
source_url: Mapped[str | None] = mapped_column(Text, nullable=True)
source_commit: Mapped[str | None] = mapped_column(String(80), nullable=True, index=True)
source_path: Mapped[str | None] = mapped_column(Text, nullable=True)
api_version: Mapped[str | None] = mapped_column(String(100), nullable=True)
export_kind: Mapped[str | None] = mapped_column(String(100), nullable=True, index=True)
exported_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True, index=True)
content_hash: Mapped[str] = mapped_column(String(64), nullable=False, index=True)
node_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, server_default="0")
edge_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, server_default="0")
validation_status: Mapped[str] = mapped_column(String(20), nullable=False, default="valid", server_default="valid", index=True)
error_details: Mapped[dict | None] = mapped_column(JSONB, nullable=True)
graph_json: Mapped[dict] = mapped_column(JSONB, nullable=False, default=dict, server_default="{}")
is_latest: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, server_default="false", index=True)
last_seen_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
nodes: Mapped[list["FabricGraphNode"]] = relationship(
"FabricGraphNode", back_populates="import_run", cascade="all, delete-orphan", lazy="select"
)
edges: Mapped[list["FabricGraphEdge"]] = relationship(
"FabricGraphEdge", back_populates="import_run", cascade="all, delete-orphan", lazy="select"
)
class FabricGraphNode(Base):
__tablename__ = "fabric_graph_nodes"
__table_args__ = (
UniqueConstraint("import_id", "graph_id", name="uq_fabric_graph_nodes_import_graph_id"),
)
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), primary_key=True, default=new_uuid
)
import_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
ForeignKey("fabric_graph_imports.id", ondelete="CASCADE"),
nullable=False,
index=True,
)
source_repo_slug: Mapped[str] = mapped_column(String(100), nullable=False, index=True)
graph_id: Mapped[str] = mapped_column(Text, nullable=False)
kind: Mapped[str] = mapped_column(String(100), nullable=False, index=True)
name: Mapped[str] = mapped_column(Text, nullable=False)
repo_slug: Mapped[str] = mapped_column(String(100), nullable=False, index=True)
domain_slug: Mapped[str] = mapped_column(String(100), nullable=False, index=True)
lifecycle: Mapped[str] = mapped_column(String(50), nullable=False, index=True)
canonical_type: Mapped[str | None] = mapped_column(String(100), nullable=True, index=True)
canon_category: Mapped[str | None] = mapped_column(String(100), nullable=True, index=True)
canon_anchor: Mapped[str | None] = mapped_column(Text, nullable=True)
mapping_fit: Mapped[str | None] = mapped_column(String(20), nullable=True, index=True)
evidence_state: Mapped[str | None] = mapped_column(String(20), nullable=True, index=True)
display_only: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, server_default="false", index=True)
attributes: Mapped[dict] = mapped_column(JSONB, nullable=False, default=dict, server_default="{}")
raw_json: Mapped[dict] = mapped_column(JSONB, nullable=False, default=dict, server_default="{}")
import_run: Mapped["FabricGraphImport"] = relationship("FabricGraphImport", back_populates="nodes")
class FabricGraphEdge(Base):
__tablename__ = "fabric_graph_edges"
__table_args__ = (
UniqueConstraint("import_id", "edge_key", name="uq_fabric_graph_edges_import_edge_key"),
)
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), primary_key=True, default=new_uuid
)
import_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
ForeignKey("fabric_graph_imports.id", ondelete="CASCADE"),
nullable=False,
index=True,
)
source_repo_slug: Mapped[str] = mapped_column(String(100), nullable=False, index=True)
edge_key: Mapped[str] = mapped_column(String(64), nullable=False, index=True)
from_graph_id: Mapped[str] = mapped_column(Text, nullable=False)
to_graph_id: Mapped[str] = mapped_column(Text, nullable=False)
edge_type: Mapped[str] = mapped_column(String(100), nullable=False, index=True)
canonical_type: Mapped[str | None] = mapped_column(String(100), nullable=True, index=True)
canon_anchor: Mapped[str | None] = mapped_column(Text, nullable=True)
mapping_fit: Mapped[str | None] = mapped_column(String(20), nullable=True, index=True)
evidence_state: Mapped[str | None] = mapped_column(String(20), nullable=True, index=True)
display_only: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, server_default="false", index=True)
attributes: Mapped[dict] = mapped_column(JSONB, nullable=False, default=dict, server_default="{}")
raw_json: Mapped[dict] = mapped_column(JSONB, nullable=False, default=dict, server_default="{}")
import_run: Mapped["FabricGraphImport"] = relationship("FabricGraphImport", back_populates="edges")