Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions api/models/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from graphon.enums import WorkflowExecutionStatus
from graphon.file import FILE_MODEL_IDENTITY, File, FileTransferMethod, FileType
from graphon.file import helpers as file_helpers
from libs.datetime_utils import naive_utc_now
from libs.helper import generate_string # type: ignore[import-not-found]
from libs.url_utils import normalize_api_base_url
from libs.uuid_utils import uuidv7
Expand Down Expand Up @@ -1144,9 +1145,20 @@ class Conversation(Base):
read_at = mapped_column(sa.DateTime)
read_account_id = mapped_column(StringUUID)
dialogue_count: Mapped[int] = mapped_column(default=0)
created_at = mapped_column(sa.DateTime, nullable=False, server_default=func.current_timestamp())
# Keep conversation timestamps on the same naive-UTC convention as the
# application write paths instead of mixing DB-local current_timestamp().
created_at = mapped_column(
sa.DateTime,
nullable=False,
default=naive_utc_now,
server_default=func.current_timestamp(),
)
updated_at = mapped_column(
sa.DateTime, nullable=False, server_default=func.current_timestamp(), onupdate=func.current_timestamp()
sa.DateTime,
nullable=False,
default=naive_utc_now,
server_default=func.current_timestamp(),
onupdate=naive_utc_now,
)

messages = db.relationship("Message", backref="conversation", lazy="select", passive_deletes="all")
Expand Down Expand Up @@ -1491,9 +1503,19 @@ class Message(Base):
)
from_end_user_id: Mapped[str | None] = mapped_column(StringUUID)
from_account_id: Mapped[str | None] = mapped_column(StringUUID)
created_at: Mapped[datetime] = mapped_column(sa.DateTime, server_default=func.current_timestamp())
# Messages share the same timestamp contract as conversations so MySQL
# DATETIME rows do not mix DB-local creation times with UTC updates.
created_at: Mapped[datetime] = mapped_column(
sa.DateTime,
default=naive_utc_now,
server_default=func.current_timestamp(),
)
updated_at: Mapped[datetime] = mapped_column(
sa.DateTime, nullable=False, server_default=func.current_timestamp(), onupdate=func.current_timestamp()
sa.DateTime,
nullable=False,
default=naive_utc_now,
server_default=func.current_timestamp(),
onupdate=naive_utc_now,
)
agent_based: Mapped[bool] = mapped_column(sa.Boolean, nullable=False, server_default=sa.text("false"))
workflow_run_id: Mapped[str | None] = mapped_column(StringUUID)
Expand Down
17 changes: 17 additions & 0 deletions api/tests/unit_tests/models/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from core.workflow.file_reference import build_file_reference
from graphon.file import FILE_MODEL_IDENTITY, FileTransferMethod
from libs.datetime_utils import naive_utc_now
from models.model import Conversation, Message


Expand Down Expand Up @@ -121,3 +122,19 @@ def test_inputs_restore_external_remote_url_file_mappings(owner_cls: type[Conver

assert restored_file.transfer_method == FileTransferMethod.REMOTE_URL
assert restored_file.remote_url == "https://example.com/report.pdf"


@pytest.mark.parametrize("owner_cls", [Conversation, Message])
def test_timestamp_columns_use_naive_utc_defaults(owner_cls: type[Conversation] | type[Message]) -> None:
created_at_column = owner_cls.__table__.c.created_at
updated_at_column = owner_cls.__table__.c.updated_at

assert created_at_column.default is not None
assert created_at_column.default.arg.__name__ == naive_utc_now.__name__
assert created_at_column.default.arg.__module__ == naive_utc_now.__module__
assert updated_at_column.default is not None
assert updated_at_column.default.arg.__name__ == naive_utc_now.__name__
assert updated_at_column.default.arg.__module__ == naive_utc_now.__module__
assert updated_at_column.onupdate is not None
assert updated_at_column.onupdate.arg.__name__ == naive_utc_now.__name__
assert updated_at_column.onupdate.arg.__module__ == naive_utc_now.__module__
Loading