save_orders_batch now runs in three tiers:
1. validate_structural pre-flight splits each payload into valid or
MALFORMED. MALFORMED rows persist with status + error_message + no
items, and an append-only entry lands in sync_errors_history.log.
2. Optimistic executemany over the valid list inside a SAVEPOINT batch.
3. On IntegrityError / ValueError / TypeError, rollback the savepoint
and fall back to per-order SAVEPOINT inserts so a single bad row
cannot poison the rest of the batch.
Mid-loop SAVEPOINT rollback failure now triggers _safe_reconnect:
commit whatever survived, close the broken connection, open a fresh
one and keep processing. Preserves MALFORMED rows recorded earlier —
addresses the outside-voice gap where a crashed connection would lose
uncommitted malformed evidence.
Adds OrderStatus.MALFORMED and helper functions:
_insert_orders_only — orders + sync_run_orders, no items
_insert_valid_batch — happy-path bulk executemany
_insert_single_order — per-order execute within savepoint
_mark_malformed — non-mutating copy with wiped items
_safe_reconnect — commit-close-reconnect guard
8 integration tests covering regression 485224762, structural
pre-flight, per-order isolation on runtime fail, caller-dict
immutability, and reconnect durability. 239 unit + 33 e2e green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
23 lines
934 B
Python
23 lines
934 B
Python
"""Application-wide constants shared across services, routers, and tests."""
|
|
from enum import Enum
|
|
|
|
|
|
class OrderStatus(str, Enum):
|
|
"""Order status values stored in SQLite `orders.status` column.
|
|
|
|
Inherits from `str` so existing string comparisons (==, in, dict.get)
|
|
keep working. Always use `.value` when passing to SQL queries or JSON
|
|
payloads to avoid Python-version-specific str(enum) surprises.
|
|
"""
|
|
IMPORTED = "IMPORTED"
|
|
ALREADY_IMPORTED = "ALREADY_IMPORTED"
|
|
SKIPPED = "SKIPPED"
|
|
ERROR = "ERROR"
|
|
CANCELLED = "CANCELLED"
|
|
DELETED_IN_ROA = "DELETED_IN_ROA"
|
|
# Structural-fail: GoMag sent a payload that cannot be inserted as-is
|
|
# (missing fields, unparseable date, invalid quantity/price, or a runtime
|
|
# insert crash). Row persists with status=MALFORMED + error_message so
|
|
# operators can escalate to GoMag without blocking the rest of the batch.
|
|
MALFORMED = "MALFORMED"
|