Preserve received calendar results when latest pages roll over
Keep previously captured BLS and Michigan releases valid when their rolling latest pages advance to a newer period or stage. Continue reporting missing historical releases explicitly and never substitute newer values. Verify unchanged values, first-arrival timestamps, revisions, and cleared source errors with isolated worker tests. Run all 74 calendar and history tests against the staged snapshot.
This commit is contained in:
1 parent
641351a002
commit
0886e74e21
3 files changed
+48
-2
No files matched your search
@@ -158,7 +158,8 @@ def test_result_date_mismatch_waits_without_using_stale_release(trading):
|
||||
response = httpx.Response(200, text='<html><body>October 14, 2026</body></html>',
|
||||
request=httpx.Request("GET", "https://www.bls.gov/example"))
|
||||
worker.fetch = AsyncMock(return_value=(response, 1))
|
||||
row = SimpleNamespace(source="bls", family="cpi", scheduled_at=datetime(2026, 11, 10, 13, 30, tzinfo=UTC))
|
||||
row = SimpleNamespace(source="bls", family="cpi", scheduled_at=datetime(2026, 11, 10, 13, 30, tzinfo=UTC),
|
||||
first_received_at=None)
|
||||
assert await worker.result_page(row) is None
|
||||
row.scheduled_at = datetime(2026, 9, 10, 12, 30, tzinfo=UTC)
|
||||
with pytest.raises(ValueError, match="日期与日历不符"):
|
||||
@@ -169,6 +170,46 @@ def test_result_date_mismatch_waits_without_using_stale_release(trading):
|
||||
asyncio.run(check())
|
||||
|
||||
|
||||
@pytest.mark.parametrize("source", ["bls", "umich"])
|
||||
def test_rolling_page_rollover_preserves_received_result_without_source_error(trading, monkeypatch, source):
|
||||
import httpx
|
||||
from alphapulse.calendar import worker as module
|
||||
|
||||
async def check():
|
||||
first_received = datetime(2026, 9, 24, 14, tzinfo=UTC)
|
||||
values = {"cpi_yoy" if source == "bls" else "umich_sentiment": {"actual": "2.5", "previous": "2.4"}}
|
||||
row = SimpleNamespace(id=1, source=source, family="cpi" if source == "bls" else "umich",
|
||||
scheduled_at=first_received, first_received_at=first_received,
|
||||
period="2026-09", stage="final" if source == "umich" else None,
|
||||
values=values.copy(), revision_no=3, error="旧的采集错误")
|
||||
session = SimpleNamespace(scalar=AsyncMock(return_value=row), commit=AsyncMock())
|
||||
|
||||
class Context:
|
||||
async def __aenter__(self):
|
||||
return session
|
||||
async def __aexit__(self, *args):
|
||||
pass
|
||||
|
||||
monkeypatch.setattr(module, "SessionLocal", Context)
|
||||
html = ('<html><body>October 22, 2026</body></html>' if source == "bls" else
|
||||
'<h1>Preliminary Results for October 2026</h1><table id="front_table">'
|
||||
'<tr><td></td><td>Oct</td><td>Sep</td></tr><tr><td></td><td>2026</td><td>2026</td></tr>'
|
||||
'<tr><td>Index of Consumer Sentiment</td><td>49.0</td><td>48.1</td></tr></table>')
|
||||
worker = module.CalendarWorker()
|
||||
worker.fetch = AsyncMock(return_value=(httpx.Response(200, text=html,
|
||||
request=httpx.Request("GET", "https://www.example.com/")), 9))
|
||||
try:
|
||||
await worker.poll_one(1)
|
||||
assert row.error is None
|
||||
assert row.first_received_at == first_received
|
||||
assert row.values == values and row.revision_no == 3
|
||||
session.commit.assert_awaited_once()
|
||||
finally:
|
||||
await worker.http.aclose()
|
||||
await worker.bls.aclose()
|
||||
asyncio.run(check())
|
||||
|
||||
|
||||
def test_schedule_reschedule_and_withdrawal_preserve_past_and_revisions(trading):
|
||||
from alphapulse.calendar.parsers import Scheduled
|
||||
from alphapulse.calendar.service import save_schedule
|
||||
|
||||
@@ -170,7 +170,8 @@ def test_umich_poll_waits_for_final_instead_of_reusing_preliminary(trading):
|
||||
<tr><td></td><td>Oct</td><td>Sep</td></tr><tr><td></td><td>2026</td><td>2026</td></tr>
|
||||
<tr><td>Index of Consumer Sentiment</td><td>49.0</td><td>48.1</td></tr></table>"""
|
||||
worker.fetch = AsyncMock(return_value=(httpx.Response(200, text=html, request=httpx.Request("GET", "https://www.sca.isr.umich.edu/")), 1))
|
||||
row = SimpleNamespace(source="umich", family="umich", period="2026-10", stage="final", scheduled_at=datetime.now(UTC))
|
||||
row = SimpleNamespace(source="umich", family="umich", period="2026-10", stage="final", scheduled_at=datetime.now(UTC),
|
||||
first_received_at=None)
|
||||
try:
|
||||
assert await worker.result_page(row) is None
|
||||
row.period = "2026-09"
|
||||
|
||||
Reference in new issue
Block a user