|
4 | 4 |
|
5 | 5 | import pytest |
6 | 6 |
|
7 | | -from app.store.jobs import cleanup_stale_jobs |
| 7 | +from app.store.jobs import cleanup_stale_jobs, _JOB_TTL_SECONDS |
8 | 8 |
|
9 | 9 |
|
10 | 10 | # --------------------------------------------------------------------------- |
@@ -72,3 +72,60 @@ def test_cleanup_keeps_recent_files(tmp_path, monkeypatch): |
72 | 72 | cleanup_stale_jobs(max_age_hours=24) |
73 | 73 |
|
74 | 74 | assert recent_file.exists() |
| 75 | + |
| 76 | + |
| 77 | +# --------------------------------------------------------------------------- |
| 78 | +# RedisJobStore |
| 79 | + |
| 80 | +def test_redis_update_job_stores_value(redis_job_store): |
| 81 | + redis_job_store.update_job("job-001", {"status": "PENDING"}) |
| 82 | + raw = redis_job_store._client.get("job:job-001") |
| 83 | + assert json.loads(raw) == {"status": "PENDING"} |
| 84 | + |
| 85 | + |
| 86 | +def test_redis_update_job_overwrites(redis_job_store): |
| 87 | + redis_job_store.update_job("job-002", {"status": "PENDING"}) |
| 88 | + redis_job_store.update_job("job-002", {"status": "SUCCESS", "result": {}}) |
| 89 | + result = redis_job_store.get_job_status("job-002") |
| 90 | + assert result == {"status": "SUCCESS", "result": {}} |
| 91 | + |
| 92 | + |
| 93 | +def test_redis_get_job_status_existing(redis_job_store): |
| 94 | + payload = {"status": "PROCESSING"} |
| 95 | + redis_job_store.update_job("job-003", payload) |
| 96 | + assert redis_job_store.get_job_status("job-003") == payload |
| 97 | + |
| 98 | + |
| 99 | +def test_redis_get_job_status_missing_returns_none(redis_job_store): |
| 100 | + assert redis_job_store.get_job_status("nonexistent-id") is None |
| 101 | + |
| 102 | + |
| 103 | +def test_redis_update_job_sets_ttl(redis_job_store): |
| 104 | + redis_job_store.update_job("job-004", {"status": "PENDING"}) |
| 105 | + ttl = redis_job_store._client.ttl("job:job-004") |
| 106 | + # TTL should be set and within expected range (allow 1s of drift) |
| 107 | + assert 0 < ttl <= _JOB_TTL_SECONDS |
| 108 | + |
| 109 | + |
| 110 | +def test_redis_update_job_resets_ttl_on_overwrite(redis_job_store): |
| 111 | + redis_job_store.update_job("job-005", {"status": "PENDING"}) |
| 112 | + redis_job_store.update_job("job-005", {"status": "SUCCESS"}) |
| 113 | + ttl = redis_job_store._client.ttl("job:job-005") |
| 114 | + assert 0 < ttl <= _JOB_TTL_SECONDS |
| 115 | + |
| 116 | + |
| 117 | +def test_redis_key_namespacing(redis_job_store): |
| 118 | + redis_job_store.update_job("job-006", {"status": "PENDING"}) |
| 119 | + # Key must use the 'job:' prefix — bare id should not exist |
| 120 | + assert redis_job_store._client.get("job-006") is None |
| 121 | + assert redis_job_store._client.get("job:job-006") is not None |
| 122 | + |
| 123 | + |
| 124 | +def test_redis_full_success_payload(redis_job_store): |
| 125 | + payload = { |
| 126 | + "status": "SUCCESS", |
| 127 | + "result": {"values": [1.0, 2.0, 3.0], "nodata_count": 0}, |
| 128 | + "base_series": {"timesteps": ["0100", "0101", "0102"]}, |
| 129 | + } |
| 130 | + redis_job_store.update_job("job-007", payload) |
| 131 | + assert redis_job_store.get_job_status("job-007") == payload |
0 commit comments