Wire /pushevent to device_events table (was log-only)

LOGIN/LOGOUT events from Jimi now persist to tracksolid.device_events.
Table already existed with correct schema (imei, event_type, event_time,
timezone, unique constraint). Follows same SAVEPOINT + log_ingestion
pattern as all other DB-writing endpoints.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
David Kiania 2026-04-11 18:42:22 +03:00
parent b1e4d6e85f
commit 87ecab4a72

View file

@ -15,7 +15,7 @@ ENDPOINTS:
/pushgps GPS positions (Priority 2) /pushgps GPS positions (Priority 2)
/pushhb Device heartbeats (Priority 2) /pushhb Device heartbeats (Priority 2)
/pushtripreport Trip reports (Priority 2) /pushtripreport Trip reports (Priority 2)
/pushevent Device events (Priority 3, log-only) /pushevent Device LOGIN/LOGOUT events (Priority 3)
/health Healthcheck for Docker/monitoring /health Healthcheck for Docker/monitoring
REVISIONS (QA-Verified): REVISIONS (QA-Verified):
@ -23,7 +23,7 @@ REVISIONS (QA-Verified):
[BUG-02] push_alarm: guard also checks alarm_type is not null (prevents FK violation). [BUG-02] push_alarm: guard also checks alarm_type is not null (prevents FK violation).
[BUG-03] push_trip_report: _parse_trip_ts handles Jimi BCD format YYMMDDHHmmss. [BUG-03] push_trip_report: _parse_trip_ts handles Jimi BCD format YYMMDDHHmmss.
[BUG-04] SAVEPOINT per item in all DB-writing endpoints (one bad item won't abort batch). [BUG-04] SAVEPOINT per item in all DB-writing endpoints (one bad item won't abort batch).
[BUG-05] Added /pushevent endpoint (log-only, prevents Jimi 404 errors). [BUG-05] Added /pushevent endpoint writes to tracksolid.device_events.
""" """
@ -513,14 +513,44 @@ def push_trip_report(token: str = Form(""), data_list: str = Form("")):
log.info("pushtripreport: %d/%d items processed.", inserted, len(items)) log.info("pushtripreport: %d/%d items processed.", inserted, len(items))
return JSONResponse(content=SUCCESS) return JSONResponse(content=SUCCESS)
# ── 7. Device Events (Priority 3 — log only) ───────────────────────────────── # ── 7. Device Events (LOGIN / LOGOUT) ────────────────────────────────────────
@app.post("/pushevent") @app.post("/pushevent")
def push_event(token: str = Form(""), data_list: str = Form("")): def push_event(token: str = Form(""), data_list: str = Form("")):
"""[BUG-05] Accept Jimi event pushes so they don't 404. Log for future schema work."""
_validate_token(token) _validate_token(token)
items = _parse_data_list(data_list) items = _parse_data_list(data_list)
for item in items: if not items:
log.info("pushevent: imei=%s type=%s gateTime=%s", return JSONResponse(content=SUCCESS)
item.get("deviceImei"), item.get("type"), item.get("gateTime"))
t0 = time.time()
inserted = 0
with get_conn() as conn:
with conn.cursor() as cur:
for item in items:
try:
cur.execute("SAVEPOINT sp")
imei = clean(item.get("deviceImei"))
event_type = clean(item.get("type"))
event_time = clean_ts(item.get("gateTime"))
if not imei or not event_type or not event_time:
cur.execute("RELEASE SAVEPOINT sp")
continue
cur.execute("""
INSERT INTO tracksolid.device_events
(imei, event_type, event_time, timezone)
VALUES (%s, %s, %s, %s)
ON CONFLICT (imei, event_type, event_time) DO NOTHING
""", (imei, event_type, event_time, clean(item.get("timezone"))))
cur.execute("RELEASE SAVEPOINT sp")
inserted += 1
except Exception:
cur.execute("ROLLBACK TO SAVEPOINT sp")
log.warning("Failed to process event for %s", item.get("deviceImei"), exc_info=True)
log_ingestion(cur, "webhook/pushevent", len(items), 0, inserted,
int((time.time() - t0) * 1000), True)
log.info("pushevent: %d/%d items processed.", inserted, len(items))
return JSONResponse(content=SUCCESS) return JSONResponse(content=SUCCESS)