diff --git a/openeo_fastapi/client/models.py b/openeo_fastapi/client/models.py index 1cd232d..71f41dd 100644 --- a/openeo_fastapi/client/models.py +++ b/openeo_fastapi/client/models.py @@ -77,6 +77,15 @@ class Method(Enum): OPTIONS = "OPTIONS" +class Status(Enum): + created = "created" + queued = "queued" + running = "running" + canceled = "canceled" + finished = "finished" + error = "error" + + class Endpoint(BaseModel): path: str = Field( ..., diff --git a/openeo_fastapi/client/psql/models.py b/openeo_fastapi/client/psql/models.py index c039355..e53c047 100644 --- a/openeo_fastapi/client/psql/models.py +++ b/openeo_fastapi/client/psql/models.py @@ -1,8 +1,11 @@ import datetime +from enum import Enum -from sqlalchemy import VARCHAR, Column, DateTime -from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy import BOOLEAN, VARCHAR, Column, DateTime, ForeignKey, String +from sqlalchemy.dialects.postgresql import ENUM, JSON, UUID +from sqlalchemy.orm import relationship +from openeo_fastapi.client.models import Status from openeo_fastapi.client.psql.settings import BASE @@ -15,3 +18,62 @@ class User(BASE): user_id = Column(UUID(as_uuid=True), primary_key=True, unique=True) oidc_sub = Column(VARCHAR, unique=True) created_at = Column(DateTime, default=datetime.datetime.utcnow(), nullable=False) + + +class Job(BASE): + """ORM for the job table.""" + + __tablename__ = "jobs" + + job_id = Column(UUID(as_uuid=True), primary_key=True) + process_graph_id = Column(VARCHAR, nullable=False) + status = Column(ENUM(Status), nullable=False) + user_id = Column( + UUID(as_uuid=True), + ForeignKey("users.user_id", ondelete="CASCADE"), + nullable=False, + ) + created = Column(DateTime, default=datetime.datetime.utcnow(), nullable=False) + title = Column(VARCHAR) + description = Column(VARCHAR) + synchronous = Column(BOOLEAN, default=False, nullable=False) # if null assume False + + children = relationship("User") + + +class ProcessGraph(BASE): + """ORM for the process graph table.""" + + __tablename__ = "process_graph" + + process_graph_id = Column(VARCHAR, primary_key=True) + process_graph = Column(JSON, nullable=False) + user_id = Column( + UUID(as_uuid=True), + ForeignKey("users.user_id", ondelete="CASCADE"), + nullable=False, + ) + created = Column(DateTime, default=datetime.datetime.utcnow(), nullable=False) + children = relationship("User") + + +class UserDefinedProcessGraph(BASE): + """ORM for the UDPS table.""" + + __tablename__ = "udps" + + udp_id = Column(String, primary_key=True, nullable=False) + user_id = Column( + UUID(as_uuid=True), + ForeignKey("users.user_id"), + primary_key=True, + nullable=False, + ) + process_graph = Column(JSON, nullable=False) + created = Column(DateTime, default=datetime.datetime.utcnow(), nullable=False) + parameters = Column("parameters", JSON) + returns = Column("returns", JSON) + summary = Column("summary", String) + description = Column("description", String) + + children = relationship("User") diff --git a/tests/client/test_psql.py b/tests/client/test_psql.py index ed61b93..5bd9445 100644 --- a/tests/client/test_psql.py +++ b/tests/client/test_psql.py @@ -3,10 +3,15 @@ from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import sessionmaker -from openeo_fastapi.client.psql.models import User +from openeo_fastapi.client.psql.models import ( + Job, + ProcessGraph, + User, + UserDefinedProcessGraph, +) -def test_db_setup(mock_engine): +def test_db_setup_and_user_model(mock_engine): """A test to validate the basic structure of our ORMs and get_engine functions.""" import uuid @@ -25,7 +30,83 @@ def test_db_setup(mock_engine): assert not sesh.scalars(wrong_user).first() -def test_db_models_extendable(mock_engine): +def test_job_model(mock_engine): + """ """ + import uuid + + user_uid = uuid.uuid4() + job_uid = uuid.uuid4() + + user = User(user_id=user_uid, oidc_sub="someone@egi.eu") + job = Job( + job_id=job_uid, + user_id=user_uid, + status="created", + process_graph_id=uuid.uuid4(), + ) + + session = sessionmaker(mock_engine) + with session.begin() as sesh: + sesh.add(user) + sesh.add(job) + + with session.begin() as sesh: + found_job = select(Job).filter_by(job_id=job_uid) + + assert sesh.scalars(found_job).first() + + +def test_processgraph_model(mock_engine): + """ """ + import uuid + + user_uid = uuid.uuid4() + process_graph_uid = "SOMEPGID" + + user = User(user_id=user_uid, oidc_sub="someone@egi.eu") + processgraph = ProcessGraph( + process_graph_id=process_graph_uid, + user_id=user_uid, + process_graph={"process": {"args": "one"}}, + ) + + session = sessionmaker(mock_engine) + with session.begin() as sesh: + sesh.add(user) + sesh.add(processgraph) + + with session.begin() as sesh: + found_pg = select(ProcessGraph).filter_by(process_graph_id=process_graph_uid) + + assert sesh.scalars(found_pg).first() + + +def test_userdefinedprocessgraph_model(mock_engine): + """ """ + import uuid + + user_uid = uuid.uuid4() + process_graph_uid = "SOMEPGID" + + user = User(user_id=user_uid, oidc_sub="someone@egi.eu") + processgraph = UserDefinedProcessGraph( + udp_id=process_graph_uid, + user_id=user_uid, + process_graph={"process": {"args": "one"}}, + ) + + session = sessionmaker(mock_engine) + with session.begin() as sesh: + sesh.add(user) + sesh.add(processgraph) + + with session.begin() as sesh: + found_pg = select(UserDefinedProcessGraph).filter_by(udp_id=process_graph_uid) + + assert sesh.scalars(found_pg).first() + + +def test_models_extendable(mock_engine): """Test the existing models can be extended and used to revise the database.""" import uuid