fix worker lock

This commit is contained in:
qananasikq
2026-04-14 19:32:45 +03:00
parent cac68bda4c
commit d9111be2d2
3 changed files with 204 additions and 6 deletions

View File

@@ -58,6 +58,7 @@ class TestWorkerTaskLockHelpers(unittest.TestCase):
with patch.object(tasks, "_get_persistence") as get_persistence, \
patch.object(tasks, "_get_redis") as get_redis, \
patch.object(tasks, "_acquire_lock", return_value=True), \
patch.object(tasks, "_is_full_scan_done", return_value=True), \
patch.object(tasks, "_start_lock_heartbeat") as start_heartbeat, \
patch.object(tasks, "_release_lock_if_owner") as release_lock, \
patch.object(tasks, "_run_browser_job", return_value={
@@ -87,6 +88,74 @@ class TestWorkerTaskLockHelpers(unittest.TestCase):
heartbeat_thread.join.assert_called_once()
release_lock.assert_called_once()
def test_clear_orphan_sync_listing_lock_deletes_when_no_tasks_running(self) -> None:
redis_client = MagicMock()
redis_client.get.return_value = "owner-token"
redis_client.ttl.return_value = 120
celery_app = MagicMock()
inspector = MagicMock()
inspector.active.return_value = {"worker@node": []}
inspector.reserved.return_value = {"worker@node": []}
inspector.scheduled.return_value = {"worker@node": []}
celery_app.control.inspect.return_value = inspector
cleared = tasks._clear_orphan_sync_listing_lock(redis_client, celery_app)
self.assertTrue(cleared)
redis_client.delete.assert_called_once_with(tasks.SYNC_LISTING_LOCK_KEY)
def test_clear_orphan_sync_listing_lock_keeps_when_task_detected(self) -> None:
redis_client = MagicMock()
redis_client.get.return_value = "owner-token"
celery_app = MagicMock()
inspector = MagicMock()
inspector.active.return_value = {
"worker@node": [{"name": tasks.SYNC_LISTING_TASK_NAME}]
}
inspector.reserved.return_value = {"worker@node": []}
inspector.scheduled.return_value = {"worker@node": []}
celery_app.control.inspect.return_value = inspector
cleared = tasks._clear_orphan_sync_listing_lock(redis_client, celery_app)
self.assertFalse(cleared)
redis_client.delete.assert_not_called()
def test_sync_listing_task_recovers_orphan_lock_and_runs(self) -> None:
with patch.object(tasks, "_get_persistence") as get_persistence, \
patch.object(tasks, "_get_redis") as get_redis, \
patch.object(tasks, "_acquire_lock", side_effect=[False, True]) as acquire_lock, \
patch.object(tasks, "_clear_orphan_sync_listing_lock", return_value=True) as clear_orphan, \
patch.object(tasks, "_is_full_scan_done", return_value=True), \
patch.object(tasks, "_start_lock_heartbeat") as start_heartbeat, \
patch.object(tasks, "_release_lock_if_owner") as release_lock, \
patch.object(tasks, "_run_browser_job", return_value={
"run_id": 9,
"cars_upserted": 3,
"cars_failed": 0,
"images_upserted": 5,
"skipped_existing": 0,
"elapsed_seconds": 2.0,
}):
persistence = MagicMock()
get_persistence.return_value = persistence
redis_client = MagicMock()
get_redis.return_value = redis_client
stop_event = MagicMock()
heartbeat_thread = MagicMock()
start_heartbeat.return_value = (stop_event, heartbeat_thread)
tasks.sync_listing_task.push_request(id="task-456")
try:
result = tasks.sync_listing_task.run(make="Honda")
finally:
tasks.sync_listing_task.pop_request()
self.assertEqual(result["status"], "success")
clear_orphan.assert_called_once()
self.assertEqual(acquire_lock.call_count, 2)
release_lock.assert_called_once()
if __name__ == "__main__":
unittest.main()