refactor: simplify mqtt pipeline state and remove event table
All checks were successful
Deploy to Production / deploy (push) Successful in 4m55s

This commit is contained in:
魏风
2026-03-19 22:08:16 +08:00
parent 8717b9c07b
commit e8846f4831
14 changed files with 269 additions and 118 deletions

View File

@@ -18,4 +18,5 @@ def test_terminal_message_raw_model_can_persist() -> None:
session.refresh(row)
assert row.id is not None
assert row.parse_status == "pending"
assert row.parsed_at is None
assert row.parse_error is None

View File

@@ -1,6 +1,6 @@
from sqlmodel import Session, SQLModel, create_engine, select
from sqlmodel import Session, SQLModel, create_engine
from app.models import TerminalDeviceState, TerminalMessageRaw, TerminalObservationEvent
from app.models import TerminalDeviceState, TerminalMessageRaw
from app.mqtt.parser_worker import process_pending_batch
from app.mqtt.repository import insert_raw_message
@@ -11,7 +11,7 @@ def _session() -> Session:
return Session(engine)
def test_insert_raw_message_sets_pending_status() -> None:
def test_insert_raw_message_sets_unparsed_defaults() -> None:
with _session() as session:
row = insert_raw_message(
session=session,
@@ -22,12 +22,13 @@ def test_insert_raw_message_sets_pending_status() -> None:
retain=False,
)
assert row.parse_status == "pending"
assert row.parsed_at is None
assert row.parse_error is None
assert row.payload_size > 0
assert len(row.payload_sha256) == 64
def test_worker_marks_success_and_writes_events() -> None:
def test_worker_marks_success_and_updates_state() -> None:
with _session() as session:
raw = insert_raw_message(
session=session,
@@ -44,10 +45,43 @@ def test_worker_marks_success_and_writes_events() -> None:
refreshed = session.get(TerminalMessageRaw, raw.id)
assert refreshed is not None
assert refreshed.parse_status == "succeeded"
events = session.exec(select(TerminalObservationEvent)).all()
assert len(events) >= 1
assert refreshed.parsed_at is not None
assert refreshed.parse_error is None
state = session.get(TerminalDeviceState, "device-001")
assert state is not None
assert state.lat is not None
assert state.lon is not None
def test_worker_marks_failed_without_retry_schedule(monkeypatch) -> None:
def _raise_parse_error(_payload: bytes) -> list[dict[str, object]]:
raise ValueError("boom")
monkeypatch.setattr(
"app.mqtt.parser_worker.parse_mixed_payload", _raise_parse_error
)
with _session() as session:
raw = insert_raw_message(
session=session,
device_id="device-err",
topic="terminal/device-err/raw",
payload=b"$GPGGA,broken*00\r\n",
qos=1,
retain=False,
)
processed = process_pending_batch(session=session, batch_size=10)
assert processed == 1
refreshed = session.get(TerminalMessageRaw, raw.id)
assert refreshed is not None
assert refreshed.parsed_at is not None
assert refreshed.parse_error == "boom"
processed_again = process_pending_batch(session=session, batch_size=10)
assert processed_again == 0
def test_schema_excludes_terminal_observation_event_table() -> None:
assert "terminal_observation_event" not in SQLModel.metadata.tables

View File

@@ -1,6 +1,6 @@
import pytest
from app.mqtt.topic import extract_device_id
from app.mqtt.ingestor import extract_device_id
def test_extract_device_id_success() -> None: