修复 MySQL 读写分离下的持久化与 SSE 重连问题,报告完成前先落库;8BF 嵌入页支持 taskId 任务卡与独立意图 metadata;前端统一 createClientId 并更新 runtime 配置。 Co-authored-by: Cursor <cursoragent@cursor.com>
84 lines
2.6 KiB
Python
84 lines
2.6 KiB
Python
"""Fault-tolerance coverage for Deep Research progress events."""
|
|
|
|
import pytest
|
|
|
|
from deerflow.agents.deep_research.adapters.event_sink import PersistingEventSink
|
|
|
|
|
|
class _UnavailableEventRepository:
|
|
async def append(self, **kwargs): # noqa: ANN003
|
|
raise RuntimeError("database temporarily unavailable")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_event_persistence_failure_keeps_job_live_and_emits_unique_fallback_event():
|
|
published: list[dict] = []
|
|
|
|
async def publish(event: dict) -> None:
|
|
published.append(event)
|
|
|
|
sink = PersistingEventSink(
|
|
_UnavailableEventRepository(),
|
|
session_id="drs_1",
|
|
job_id="drj_1",
|
|
on_event=publish,
|
|
)
|
|
|
|
first = await sink.emit("phase_changed", phase="planning", payload={"to": "planning"})
|
|
second = await sink.emit("queries_planned", phase="collecting", payload={"queries": ["AI"]})
|
|
|
|
assert (first.seq, second.seq) == (-1, -2)
|
|
assert first.payload["eventPersistenceDegraded"] is True
|
|
assert published[0]["liveId"] == "event-persistence-fallback:drj_1:1"
|
|
assert published[1]["liveId"] == "event-persistence-fallback:drj_1:2"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_live_publish_failure_does_not_fail_event_delivery():
|
|
class _EventRepository:
|
|
async def append(self, **kwargs): # noqa: ANN003
|
|
return {
|
|
"seq": 1,
|
|
"event_type": kwargs["event_type"],
|
|
"phase": kwargs["phase"],
|
|
"payload": kwargs["payload"],
|
|
}
|
|
|
|
async def broken_publisher(event: dict) -> None: # noqa: ARG001
|
|
raise RuntimeError("browser disconnected")
|
|
|
|
sink = PersistingEventSink(
|
|
_EventRepository(),
|
|
session_id="drs_1",
|
|
job_id="drj_1",
|
|
on_event=broken_publisher,
|
|
)
|
|
|
|
event = await sink.emit("phase_changed", phase="planning")
|
|
|
|
assert event.seq == 1
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_document_rewrite_milestone_is_a_supported_durable_event():
|
|
"""Guard the artifact-rewrite job path against EventType regressions."""
|
|
|
|
class _EventRepository:
|
|
async def append(self, **kwargs): # noqa: ANN003
|
|
return {
|
|
"seq": 1,
|
|
"event_type": kwargs["event_type"],
|
|
"phase": kwargs["phase"],
|
|
"payload": kwargs["payload"],
|
|
}
|
|
|
|
sink = PersistingEventSink(_EventRepository(), session_id="drs_1", job_id="drj_1")
|
|
|
|
event = await sink.emit(
|
|
"document_rewrite",
|
|
phase="planning",
|
|
payload={"type": "requirements_started"},
|
|
)
|
|
|
|
assert event.type == "document_rewrite"
|