11from datetime import datetime
2- from typing import Annotated , Any
2+ from typing import Any
33from uuid import NAMESPACE_DNS , UUID , uuid5
44
5- from pydantic import AliasChoices , PlainSerializer , PlainValidator , ValidationInfo , model_validator
5+ from pydantic import AliasChoices , ValidationInfo , model_validator
66from sqlalchemy .dialects import postgresql
77from sqlalchemy .ext .mutable import MutableDict , MutableList
88from sqlalchemy .types import PickleType
9- from sqlmodel import Column , Enum , Field , SQLModel , String
9+ from sqlmodel import Column , Enum , Field , MetaData , SQLModel , String
1010
1111from ..common .enums import ManifestKind , StatusEnum
12+ from ..common .types import KindField , StatusField
1213from ..config import config
1314
1415_default_campaign_namespace = uuid5 (namespace = NAMESPACE_DNS , name = "io.lsst.cmservice" )
1516"""Default UUID5 namespace for campaigns"""
1617
18+ metadata : MetaData = MetaData (schema = config .db .table_schema )
19+ """SQLModel metadata for table models"""
20+
1721
1822def jsonb_column (name : str , aliases : list [str ] | None = None ) -> Any :
1923 """Constructor for a Field based on a JSONB database column.
@@ -47,34 +51,10 @@ def jsonb_column(name: str, aliases: list[str] | None = None) -> Any:
4751# 3. the model of the manifest when updating an object
4852# 4. a response model for APIs related to the object
4953
50- EnumSerializer = PlainSerializer (
51- lambda x : x .name ,
52- return_type = "str" ,
53- when_used = "always" ,
54- )
55- """A serializer for enums that produces its name, not the value."""
56-
57-
58- StatusEnumValidator = PlainValidator (lambda x : StatusEnum [x ] if isinstance (x , str ) else StatusEnum (x ))
59- """A validator for the StatusEnum that can parse the enum from either a name
60- or a value.
61- """
62-
63-
64- ManifestKindEnumValidator = PlainValidator (
65- lambda x : ManifestKind [x ] if isinstance (x , str ) else ManifestKind (x )
66- )
67- """A validator for the ManifestKindEnum that can parse the enum from a name
68- or a value.
69- """
70-
71-
72- type StatusField = Annotated [StatusEnum , StatusEnumValidator , EnumSerializer ]
73- type KindField = Annotated [ManifestKind , ManifestKindEnumValidator , EnumSerializer ]
74-
7554
7655class BaseSQLModel (SQLModel ):
7756 __table_args__ = {"schema" : config .db .table_schema }
57+ metadata = metadata
7858
7959
8060class CampaignBase (BaseSQLModel ):
@@ -116,10 +96,10 @@ class Campaign(CampaignModel, table=True):
11696
11797 __tablename__ : str = "campaigns_v2" # type: ignore[misc]
11898
119- machine : UUID | None
99+ machine : UUID | None = Field ( foreign_key = "machines_v2.id" , default = None , ondelete = "CASCADE" )
120100
121101
122- class CampaignUpdate (SQLModel ):
102+ class CampaignUpdate (BaseSQLModel ):
123103 """Model representing updatable fields for a PATCH operation on a Campaign
124104 using RFC7396.
125105 """
@@ -168,7 +148,7 @@ def custom_model_validator(cls, data: Any, info: ValidationInfo) -> Any:
168148class Node (NodeModel , table = True ):
169149 __tablename__ : str = "nodes_v2" # type: ignore[misc]
170150
171- machine : UUID | None
151+ machine : UUID | None = Field ( foreign_key = "machines_v2.id" , default = None , ondelete = "CASCADE" )
172152
173153
174154class EdgeBase (BaseSQLModel ):
@@ -215,13 +195,19 @@ class MachineBase(BaseSQLModel):
215195 state : Any | None = Field (sa_column = Column ("state" , PickleType ))
216196
217197
198+ class Machine (MachineBase , table = True ):
199+ """machines_v2 db table."""
200+
201+ __tablename__ : str = "machines_v2" # type: ignore[misc]
202+
203+
218204class ManifestBase (BaseSQLModel ):
219205 """manifests_v2 db table"""
220206
221207 id : UUID = Field (primary_key = True )
222208 name : str
223209 version : int
224- namespace : UUID
210+ namespace : UUID = Field ( foreign_key = "campaigns_v2.id" )
225211 kind : KindField = Field (
226212 default = ManifestKind .other ,
227213 sa_column = Column ("kind" , Enum (ManifestKind , length = 20 , native_enum = False , create_constraint = False )),
@@ -252,14 +238,14 @@ class Manifest(ManifestBase, table=True):
252238 __tablename__ : str = "manifests_v2" # type: ignore[misc]
253239
254240
255- class Task (SQLModel , table = True ):
241+ class Task (BaseSQLModel , table = True ):
256242 """tasks_v2 db table"""
257243
258244 __tablename__ : str = "tasks_v2" # type: ignore[misc]
259245
260246 id : UUID = Field (primary_key = True )
261- namespace : UUID
262- node : UUID
247+ namespace : UUID = Field ( foreign_key = "campaigns_v2.id" )
248+ node : UUID = Field ( foreign_key = "nodes_v2.id" )
263249 priority : int
264250 created_at : datetime
265251 last_processed_at : datetime
@@ -280,8 +266,8 @@ class Task(SQLModel, table=True):
280266
281267class ActivityLogBase (BaseSQLModel ):
282268 id : UUID = Field (primary_key = True )
283- namespace : UUID
284- node : UUID
269+ namespace : UUID = Field ( foreign_key = "campaigns_v2.id" )
270+ node : UUID = Field ( foreign_key = "nodes_v2.id" )
285271 operator : str
286272 to_status : StatusField = Field (
287273 sa_column = Column (
0 commit comments