diff --git a/backend/druks/contrib/ship/models.py b/backend/druks/contrib/ship/models.py index adee5f96..0491fc14 100644 --- a/backend/druks/contrib/ship/models.py +++ b/backend/druks/contrib/ship/models.py @@ -76,7 +76,7 @@ class ProjectRepo(StoredSubject): profile: Mapped[dict[str, Any]] = mapped_column(JSONB, default=dict) created_at: Mapped[datetime] = mapped_column(default=Base.utc_now) - project: Mapped[Project] = relationship(back_populates="repos") + project: Mapped[Project] = relationship(back_populates="repos", lazy="joined") @classmethod def create( diff --git a/backend/druks/durable/models.py b/backend/druks/durable/models.py index b5259d0c..2bf2ffdd 100644 --- a/backend/druks/durable/models.py +++ b/backend/druks/durable/models.py @@ -419,7 +419,7 @@ class AgentCall(Base, Uuid7Pk): model: Mapped[str] = mapped_column(String) # The run this LLM call ran in. ON DELETE CASCADE, so a call never outlives it. run_id: Mapped[str] = mapped_column(ForeignKey("durable_runs.id", ondelete="CASCADE")) - run: Mapped["Run"] = relationship(back_populates="agent_calls") + run: Mapped["Run"] = relationship(back_populates="agent_calls", lazy="joined") # Which agent (registry id: "scope", "implement", …) made this call — the # timeline's grouping label. An agent is what makes a call, so there is no # unattributed one: the row is written from the registered agent's own id. diff --git a/backend/druks/models.py b/backend/druks/models.py index 92921ee7..8b1b196d 100644 --- a/backend/druks/models.py +++ b/backend/druks/models.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Any, ClassVar, Self from sqlalchemy import DateTime, Integer, cast, select +from sqlalchemy.ext.asyncio import AsyncAttrs from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column from sqlalchemy.types import TypeDecorator @@ -29,7 +30,7 @@ def process_result_value(self, value: datetime | None, dialect: Any) -> datetime return ensure_utc(value) if value else value -class Base(DeclarativeBase): +class Base(AsyncAttrs, DeclarativeBase): # Every ``Mapped[datetime]`` column stores tz-aware UTC — the decorator # guarantees aware values on read (writes are unaffected). Mapping it here # means models declare ``Mapped[datetime]`` with no per-column type. diff --git a/backend/druks/skills/models.py b/backend/druks/skills/models.py index 849b7e7c..d396f709 100644 --- a/backend/druks/skills/models.py +++ b/backend/druks/skills/models.py @@ -21,6 +21,7 @@ class SkillCollection(Base, Uuid7Pk): skills: Mapped[list["Skill"]] = relationship( back_populates="collection", cascade="all, delete-orphan", + lazy="selectin", order_by="Skill.name", ) @@ -64,7 +65,7 @@ class Skill(Base, Uuid7Pk): name: Mapped[str] = mapped_column(String, unique=True) description: Mapped[str] = mapped_column(String, default="") - collection: Mapped[SkillCollection] = relationship(back_populates="skills") + collection: Mapped[SkillCollection] = relationship(back_populates="skills", lazy="raise_on_sql") collection_id: Mapped[str] = mapped_column(ForeignKey("skill_collections.id")) # Disabled skills stay on disk but the delivery projection excludes them # from every sandbox upload.