2026-09-21 19:34:24 +00:00
|
|
|
"""SQS worker deletes completed jobs and leaves skipped messages for retry."""
|
|
|
|
|
|
|
|
|
|
import json
|
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
|
|
|
|
|
|
from server import worker
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _one_message_then_stop(body: dict):
|
|
|
|
|
def receive_message(**_kwargs):
|
|
|
|
|
worker._stop(None, None)
|
|
|
|
|
return {
|
|
|
|
|
"Messages": [
|
|
|
|
|
{
|
|
|
|
|
"ReceiptHandle": "rh-1",
|
|
|
|
|
"Body": json.dumps(body),
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return receive_message
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@patch("server.worker.boto3.client")
|
|
|
|
|
@patch("server.worker.run_job")
|
|
|
|
|
def test_worker_does_not_delete_skipped_jobs(mock_run, mock_client):
|
|
|
|
|
sqs = MagicMock()
|
|
|
|
|
mock_client.return_value = sqs
|
|
|
|
|
sqs.receive_message.side_effect = _one_message_then_stop({"event": "close"})
|
|
|
|
|
mock_run.return_value = {"status": "skipped", "reason": "outside window"}
|
|
|
|
|
|
|
|
|
|
with patch.dict("os.environ", {"JOBS_QUEUE_URL": "https://sqs.example/jobs"}):
|
|
|
|
|
worker._running = True
|
|
|
|
|
worker.main()
|
|
|
|
|
|
|
|
|
|
sqs.delete_message.assert_not_called()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@patch("server.worker.boto3.client")
|
|
|
|
|
@patch("server.worker.run_job")
|
|
|
|
|
def test_worker_deletes_completed_jobs(mock_run, mock_client):
|
|
|
|
|
sqs = MagicMock()
|
|
|
|
|
mock_client.return_value = sqs
|
|
|
|
|
sqs.receive_message.side_effect = _one_message_then_stop({"event": "close"})
|
|
|
|
|
mock_run.return_value = {"status": "closed", "week": "2026-W19"}
|
|
|
|
|
|
|
|
|
|
with patch.dict("os.environ", {"JOBS_QUEUE_URL": "https://sqs.example/jobs"}):
|
|
|
|
|
worker._running = True
|
|
|
|
|
worker.main()
|
|
|
|
|
|
|
|
|
|
sqs.delete_message.assert_called_once_with(
|
|
|
|
|
QueueUrl="https://sqs.example/jobs", ReceiptHandle="rh-1"
|
|
|
|
|
)
|
2026-09-21 23:48:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@patch("server.worker.sentry_sdk.capture_exception")
|
|
|
|
|
@patch("server.worker.boto3.client")
|
|
|
|
|
@patch("server.worker.run_job")
|
|
|
|
|
def test_worker_captures_job_failures(mock_run, mock_client, mock_capture):
|
|
|
|
|
sqs = MagicMock()
|
|
|
|
|
mock_client.return_value = sqs
|
|
|
|
|
sqs.receive_message.side_effect = _one_message_then_stop({"event": "close"})
|
|
|
|
|
mock_run.side_effect = RuntimeError("boom")
|
|
|
|
|
|
|
|
|
|
with patch.dict("os.environ", {"JOBS_QUEUE_URL": "https://sqs.example/jobs"}):
|
|
|
|
|
worker._running = True
|
|
|
|
|
worker.main()
|
|
|
|
|
|
|
|
|
|
mock_capture.assert_called_once()
|
|
|
|
|
sqs.delete_message.assert_not_called()
|