This commit is contained in:
Your Name
2026-04-22 14:13:21 +08:00
parent e0406b5d0e
commit 7cbde2aa78
145 changed files with 23086 additions and 2243 deletions

View File

@@ -1,7 +1,15 @@
import unittest
from unittest.mock import patch
from app.sync_agent import _append_detect_result_projection_snapshot
from app.sync_agent import (
_append_detect_result_projection_snapshot,
_build_aligned_queue_health_snapshot,
_emit_structured_tick,
_emit_sync_result_breakdown,
_filter_runtime_events_for_job,
_run_pipeline_stage_processor,
_select_projection_job_snapshots,
)
class SyncAgentTests(unittest.TestCase):
@@ -30,6 +38,155 @@ class SyncAgentTests(unittest.TestCase):
self.assertEqual(1, payload["progress"]["blacklisted"])
self.assertEqual(2, payload["progress"]["failed"])
@patch("app.sync_agent.get_latest_unprojected_detect_job_summary")
@patch("app.sync_agent.get_active_detect_job_summary")
def test_select_projection_job_snapshots_returns_active_and_latest_finished(
self,
mock_get_active_detect_job_summary,
mock_get_latest_unprojected_detect_job_summary,
) -> None:
mock_get_active_detect_job_summary.return_value = {"job_id": 101, "job_code": "running-job"}
mock_get_latest_unprojected_detect_job_summary.return_value = {"job_id": 102, "job_code": "finished-job"}
snapshots = _select_projection_job_snapshots()
self.assertEqual(["running-job", "finished-job"], [item["job_code"] for item in snapshots])
@patch("app.sync_agent.get_latest_unprojected_detect_job_summary")
@patch("app.sync_agent.get_active_detect_job_summary")
def test_select_projection_job_snapshots_deduplicates_same_job(
self,
mock_get_active_detect_job_summary,
mock_get_latest_unprojected_detect_job_summary,
) -> None:
mock_get_active_detect_job_summary.return_value = {"job_id": 101, "job_code": "same-job"}
mock_get_latest_unprojected_detect_job_summary.return_value = {"job_id": 101, "job_code": "same-job"}
snapshots = _select_projection_job_snapshots()
self.assertEqual(1, len(snapshots))
self.assertEqual("same-job", snapshots[0]["job_code"])
def test_build_aligned_queue_health_snapshot_overrides_mismatched_job(self) -> None:
active_job = {
"job_id": 1891,
"job_code": "sync-overseas-31230",
"status": "running",
"progress_percent": 75.9,
"items_total": 1000,
"items_pending": 155,
"items_claimed": 45,
"items_running": 41,
"items_completed": 759,
"items_blacklisted": 0,
"items_failed": 0,
"node_stats": [
{
"node_code": "mainland-worker-01",
"items_total": 710,
"items_claimed": 45,
"items_running": 41,
"items_completed": 624,
}
],
}
queue_health = {
"job": {"job_code": "sync-overseas-31273"},
"queue": {"items_total": 1000, "pending": 838, "claimed": 162, "running": 0, "completed": 0},
"nodes": [{"node_code": "mainland-controller-01", "items_total": 162}],
}
data = _build_aligned_queue_health_snapshot(active_job, queue_health)
self.assertEqual("sync-overseas-31230", data["job"]["job_code"])
self.assertEqual(155, data["queue"]["pending"])
self.assertEqual(45, data["queue"]["claimed"])
self.assertEqual(41, data["queue"]["running"])
self.assertEqual(759, data["queue"]["completed"])
self.assertEqual("mainland-worker-01", data["nodes"][0]["node_code"])
self.assertEqual("unassigned", data["nodes"][-1]["node_code"])
@patch("app.sync_agent.push_debug_event")
def test_emit_sync_result_breakdown_marks_idle_projection_as_idle(self, mock_push_debug_event) -> None:
_emit_sync_result_breakdown(
{
"results": [
{
"sync_type": "detect_result_projection",
"ok": False,
"message": "当前没有可推送的detect_result_projection",
"data": {},
}
]
}
)
mock_push_debug_event.assert_called_once()
self.assertEqual("detect_result_projection_sync_idle", mock_push_debug_event.call_args.kwargs["event_type"])
self.assertEqual("info", mock_push_debug_event.call_args.kwargs["level"])
@patch("app.sync_agent.push_debug_event")
def test_emit_structured_tick_marks_idle_sync_push_as_idle(self, mock_push_debug_event) -> None:
_emit_structured_tick(
base_event_type="sync_push",
ok=False,
message="当前没有需要立即推送的同步投影",
data={"results": []},
)
mock_push_debug_event.assert_called_once()
self.assertEqual("sync_push_idle", mock_push_debug_event.call_args.kwargs["event_type"])
self.assertEqual("info", mock_push_debug_event.call_args.kwargs["level"])
def test_filter_runtime_events_for_job_discards_mismatched_jobs(self) -> None:
events = _filter_runtime_events_for_job(
[
{
"job_id": 2137,
"node_code": "mainland-controller-01",
"event_type": "job_created",
"message": "new job",
"payload": {"source_record_id": 35461},
"created_at": "2026-04-22 01:21:29",
},
{
"job_id": 1902,
"node_code": "mainland-controller-01",
"event_type": "worker_log",
"message": "claim batch",
"payload": {"job_code": "sync-overseas-31437"},
"created_at": "2026-04-22 01:19:25",
},
],
job_code="sync-overseas-31437",
job_id=1902,
limit=8,
)
self.assertEqual(1, len(events))
self.assertEqual("worker_log", events[0]["event_type"])
@patch("app.sync_agent.push_debug_event")
@patch("app.sync_agent.process_detect_pipeline_now")
def test_run_pipeline_stage_processor_uses_high_default_limit(
self,
mock_process_detect_pipeline_now,
mock_push_debug_event,
) -> None:
mock_process_detect_pipeline_now.return_value = (
True,
"pipeline ok",
{"processed_items": 512},
)
ok, message, data = _run_pipeline_stage_processor()
self.assertTrue(ok)
self.assertEqual("pipeline ok", message)
self.assertEqual({"processed_items": 512}, data)
mock_process_detect_pipeline_now.assert_called_once_with(limit=5000)
self.assertEqual("pipeline_tick_success", mock_push_debug_event.call_args.kwargs["event_type"])
if __name__ == "__main__":
unittest.main()