Skip to content
Merged
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
4 changes: 4 additions & 0 deletions backend/app/services/focus_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,10 @@ async def _upsert_focus_item_impl(
await db.refresh(item)
else:
await db.flush()
# The caller may serialize this item before committing its outer
# transaction. Load database-generated timestamps first so async ORM
# attribute access cannot trigger an implicit lazy-load.
await db.refresh(item)
return _serialize_focus_item(item)


Expand Down
60 changes: 60 additions & 0 deletions backend/tests/test_focus_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from types import SimpleNamespace
from unittest.mock import AsyncMock
import uuid

import pytest

from app.services import focus_service


class _Result:
def __init__(self, item):
self.item = item

def scalar_one_or_none(self):
return self.item


@pytest.mark.asyncio
async def test_upsert_with_caller_session_refreshes_before_serializing(monkeypatch):
"""Server-generated timestamps must be loaded inside the async context."""
item = SimpleNamespace(
title=None,
description="Previous description",
status="in_progress",
kind="normal",
source="user",
item_metadata={},
completed_at=None,
)
events: list[str] = []

async def flush():
events.append("flush")

async def refresh(value):
assert value is item
events.append("refresh")

session = SimpleNamespace(
execute=AsyncMock(return_value=_Result(item)),
flush=flush,
refresh=refresh,
)
monkeypatch.setattr(focus_service, "_serialize_focus_item", lambda value: {"key": "system:okr_reports"})

result = await focus_service._upsert_focus_item_impl(
session,
uuid.uuid4(),
"system:okr_reports",
None,
"OKR reports",
"in_progress",
"system",
"trigger",
None,
should_commit=False,
)

assert result == {"key": "system:okr_reports"}
assert events == ["flush", "refresh"]