fix(awooop): use naive utc for run lease timestamps
This commit is contained in:
@@ -29,7 +29,7 @@ from __future__ import annotations
|
||||
|
||||
import socket
|
||||
import uuid
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import structlog
|
||||
@@ -66,6 +66,11 @@ TERMINAL_STATES = frozenset({"completed", "failed", "cancelled", "timeout"})
|
||||
_WORKER_ID = f"{socket.gethostname()}:{uuid.uuid4().hex[:8]}"
|
||||
|
||||
|
||||
def _utc_now_naive() -> datetime:
|
||||
"""Return UTC now matching AwoooP timestamp-without-timezone columns."""
|
||||
return datetime.now(UTC).replace(tzinfo=None)
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# FSM 驗證
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
@@ -98,8 +103,8 @@ async def acquire_pending_run(
|
||||
同時只有一個 worker 可取得同一筆 run(PostgreSQL SKIP LOCKED 保證)。
|
||||
Returns None 表示目前沒有待處理的 run。
|
||||
"""
|
||||
lease_until = datetime.now(timezone.utc) + timedelta(seconds=LEASE_TTL_SECONDS)
|
||||
now = datetime.now(timezone.utc)
|
||||
now = _utc_now_naive()
|
||||
lease_until = now + timedelta(seconds=LEASE_TTL_SECONDS)
|
||||
|
||||
async with get_db_context(project_id) as db:
|
||||
# SKIP LOCKED:其他 worker 已鎖定的 row 直接跳過
|
||||
@@ -154,9 +159,10 @@ async def acquire_pending_run(
|
||||
return run
|
||||
|
||||
|
||||
async def heartbeat(run_id: "UUID", project_id: str) -> None:
|
||||
async def heartbeat(run_id: UUID, project_id: str) -> None:
|
||||
"""更新 run 的 heartbeat + 延長 lease TTL"""
|
||||
new_lease = datetime.now(timezone.utc) + timedelta(seconds=LEASE_TTL_SECONDS)
|
||||
now = _utc_now_naive()
|
||||
new_lease = now + timedelta(seconds=LEASE_TTL_SECONDS)
|
||||
async with get_db_context(project_id) as db:
|
||||
await db.execute(
|
||||
update(AwoooPRunState)
|
||||
@@ -165,14 +171,14 @@ async def heartbeat(run_id: "UUID", project_id: str) -> None:
|
||||
AwoooPRunState.state == "running",
|
||||
)
|
||||
.values(
|
||||
heartbeat_at=datetime.now(timezone.utc),
|
||||
heartbeat_at=now,
|
||||
lease_until=new_lease,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def transition(
|
||||
run_id: "UUID",
|
||||
run_id: UUID,
|
||||
project_id: str,
|
||||
to_state: str,
|
||||
*,
|
||||
@@ -214,7 +220,7 @@ async def transition(
|
||||
if step_count_delta:
|
||||
values["step_count"] = AwoooPRunState.step_count + step_count_delta
|
||||
if to_state in TERMINAL_STATES:
|
||||
values["completed_at"] = datetime.now(timezone.utc)
|
||||
values["completed_at"] = _utc_now_naive()
|
||||
values["lease_until"] = None
|
||||
values["worker_id"] = None
|
||||
|
||||
@@ -245,7 +251,7 @@ async def reap_stale_runs(project_id: str) -> int:
|
||||
|
||||
Returns: 處理的 stale run 數
|
||||
"""
|
||||
now = datetime.now(timezone.utc)
|
||||
now = _utc_now_naive()
|
||||
reaped = 0
|
||||
|
||||
async with get_db_context(project_id) as db:
|
||||
|
||||
Reference in New Issue
Block a user