mirror of
https://github.com/langgenius/dify.git
synced 2026-11-10 13:26:58 +08:00
fix(api): store retry attempt timestamps as UTC in the persistence layer (#45461)
Signed-off-by: Eapp1e <163811520+Eapp1e@users.noreply.github.com>
This commit is contained in:
1 parent
0063bb639c
commit
031a3ee8a0
2 files changed
+54
-3
No files matched your search
@@ -47,7 +47,7 @@ from graphon.enums import (
|
||||
WorkflowType,
|
||||
)
|
||||
from graphon.node_events import NodeRunResult
|
||||
from libs.datetime_utils import naive_utc_now
|
||||
from libs.datetime_utils import naive_utc_now, to_utc_timestamp
|
||||
from repositories.entities.workflow_execution import WorkflowExecution
|
||||
from services.workflow.inspector_events import (
|
||||
publish_node_changed as _inspector_publish_node_changed,
|
||||
@@ -422,8 +422,8 @@ class WorkflowPersistenceLayer(Layer):
|
||||
error=event.node_run_result.error or event.error,
|
||||
elapsed_time=max((finished_at - event.start_at).total_seconds(), 0.0),
|
||||
execution_metadata={key.value: value for key, value in event.node_run_result.metadata.items()},
|
||||
created_at=int(event.start_at.timestamp()),
|
||||
finished_at=int(finished_at.timestamp()),
|
||||
created_at=to_utc_timestamp(event.start_at),
|
||||
finished_at=to_utc_timestamp(finished_at),
|
||||
)
|
||||
history.append(attempt.model_dump(mode="json"))
|
||||
process_data[RETRY_HISTORY_PROCESS_DATA_KEY] = history
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
from dataclasses import replace
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from types import SimpleNamespace
|
||||
@@ -1257,6 +1258,56 @@ class TestPersistenceLayerCases:
|
||||
assert retry_history[0]["error"] == "attempt 1 failed"
|
||||
assert retry_history[0]["execution_metadata"] == {"iteration_id": "iteration-1"}
|
||||
|
||||
def test_retry_history_records_unix_timestamps(self, monkeypatch: pytest.MonkeyPatch):
|
||||
"""Retry attempts store epoch seconds, so the host timezone must not shift them."""
|
||||
if not hasattr(time, "tzset"):
|
||||
pytest.skip("tzset is only available on POSIX platforms")
|
||||
recorded_at = datetime(2024, 5, 1)
|
||||
expected = int(recorded_at.replace(tzinfo=UTC).timestamp())
|
||||
monkeypatch.setattr(persistence_mod, "naive_utc_now", lambda: recorded_at)
|
||||
monkeypatch.setenv("TZ", "Asia/Shanghai")
|
||||
time.tzset()
|
||||
try:
|
||||
layer, _, node_repo, _ = _make_layer(node_run_indices={"exec": 1})
|
||||
layer.on_event(GraphRunStartedEvent())
|
||||
layer.on_event(
|
||||
NodeRunStartedEvent(
|
||||
id="exec",
|
||||
node_id="node",
|
||||
node_type=BuiltinNodeTypes.HTTP_REQUEST,
|
||||
node_title="HTTP",
|
||||
start_at=recorded_at,
|
||||
)
|
||||
)
|
||||
layer.on_event(
|
||||
NodeRunRetryEvent(
|
||||
id="exec",
|
||||
node_id="node",
|
||||
node_type=BuiltinNodeTypes.HTTP_REQUEST,
|
||||
node_title="HTTP",
|
||||
start_at=recorded_at,
|
||||
error="attempt 1 failed",
|
||||
retry_index=1,
|
||||
node_run_result=NodeRunResult(inputs={}, process_data={}, outputs={}, metadata={}),
|
||||
)
|
||||
)
|
||||
layer.on_event(
|
||||
NodeRunSucceededEvent(
|
||||
id="exec",
|
||||
node_id="node",
|
||||
node_type=BuiltinNodeTypes.HTTP_REQUEST,
|
||||
node_title="HTTP",
|
||||
start_at=recorded_at,
|
||||
node_run_result=NodeRunResult(inputs={}, process_data={}, outputs={}, metadata={}),
|
||||
)
|
||||
)
|
||||
attempt = node_repo.saved_exec_data[-1].process_data["__dify_retry_history"][0]
|
||||
finally:
|
||||
monkeypatch.undo()
|
||||
time.tzset()
|
||||
assert attempt["created_at"] == expected
|
||||
assert attempt["finished_at"] == expected
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("event_type", "expected_status"),
|
||||
[
|
||||
|
||||
Reference in new issue
Block a user