Files
letta-server/letta/orm/job.py
Kian Jones fecf6decfb chore: migrate to ruff (#4305)
* base requirements

* autofix

* Configure ruff for Python linting and formatting

- Set up minimal ruff configuration with basic checks (E, W, F, I)
- Add temporary ignores for common issues during migration
- Configure pre-commit hooks to use ruff with pass_filenames
- This enables gradual migration from black to ruff

* Delete sdj

* autofixed only

* migrate lint action

* more autofixed

* more fixes

* change precommit

* try changing the hook

* try this stuff
2025-08-29 11:11:19 -07:00

61 lines
2.9 KiB
Python

from datetime import datetime
from typing import TYPE_CHECKING, List, Optional
from sqlalchemy import JSON, BigInteger, Index, String
from sqlalchemy.orm import Mapped, mapped_column, relationship
from letta.orm.mixins import UserMixin
from letta.orm.sqlalchemy_base import SqlalchemyBase
from letta.schemas.enums import JobStatus, JobType
from letta.schemas.job import Job as PydanticJob, LettaRequestConfig
if TYPE_CHECKING:
from letta.orm.job_messages import JobMessage
from letta.orm.message import Message
from letta.orm.step import Step
from letta.orm.user import User
class Job(SqlalchemyBase, UserMixin):
"""Jobs run in the background and are owned by a user.
Typical jobs involve loading and processing sources etc.
"""
__tablename__ = "jobs"
__pydantic_model__ = PydanticJob
__table_args__ = (Index("ix_jobs_created_at", "created_at", "id"),)
status: Mapped[JobStatus] = mapped_column(String, default=JobStatus.created, doc="The current status of the job.")
completed_at: Mapped[Optional[datetime]] = mapped_column(nullable=True, doc="The unix timestamp of when the job was completed.")
metadata_: Mapped[Optional[dict]] = mapped_column(JSON, doc="The metadata of the job.")
job_type: Mapped[JobType] = mapped_column(
String,
default=JobType.JOB,
doc="The type of job. This affects whether or not we generate json_schema and source_code on the fly.",
)
request_config: Mapped[Optional[LettaRequestConfig]] = mapped_column(
JSON, nullable=True, doc="The request configuration for the job, stored as JSON."
)
# callback related columns
callback_url: Mapped[Optional[str]] = mapped_column(String, nullable=True, doc="When set, POST to this URL after job completion.")
callback_sent_at: Mapped[Optional[datetime]] = mapped_column(nullable=True, doc="Timestamp when the callback was last attempted.")
callback_status_code: Mapped[Optional[int]] = mapped_column(nullable=True, doc="HTTP status code returned by the callback endpoint.")
callback_error: Mapped[Optional[str]] = mapped_column(
nullable=True, doc="Optional error message from attempting to POST the callback endpoint."
)
# timing metrics (in nanoseconds for precision)
ttft_ns: Mapped[Optional[int]] = mapped_column(BigInteger, nullable=True, doc="Time to first token in nanoseconds")
total_duration_ns: Mapped[Optional[int]] = mapped_column(BigInteger, nullable=True, doc="Total run duration in nanoseconds")
# relationships
user: Mapped["User"] = relationship("User", back_populates="jobs")
job_messages: Mapped[List["JobMessage"]] = relationship("JobMessage", back_populates="job", cascade="all, delete-orphan")
steps: Mapped[List["Step"]] = relationship("Step", back_populates="job", cascade="save-update")
@property
def messages(self) -> List["Message"]:
"""Get all messages associated with this job."""
return [jm.message for jm in self.job_messages]