Skip to content

Order Sync

One-way order synchronization from Drone Shop to CRM Portal, with full audit trail and trace correlation.

Sync Architecture

sequenceDiagram
    participant Timer as Sync Timer (300s)
    participant CRM as CRM Portal
    participant Shop as Drone Shop
    participant ATP as Oracle ATP
    participant APM as OCI APM

    Timer->>CRM: Trigger sync
    CRM->>Shop: GET /api/orders (traceparent header)
    Shop-->>CRM: JSON order list

    loop Each order
        CRM->>ATP: SELECT customer WHERE email = :email
        alt Customer exists
            CRM->>ATP: UPDATE customer
        else New
            CRM->>ATP: INSERT customer
        end
        CRM->>ATP: UPSERT order (source_system + source_order_id)
        CRM->>ATP: DELETE + INSERT order_items
        CRM->>ATP: INSERT order_sync_audit
    end

    CRM->>APM: Span: orders.sync.external
    Note over ATP: correlation_id links all records to APM trace

Sync Configuration

Variable Default Purpose
ORDERS_SYNC_ENABLED true Enable/disable sync
ORDERS_SYNC_INTERVAL_SECONDS 300 Sync frequency
EXTERNAL_ORDERS_URL from OCTO_DRONE_SHOP_URL Source URL
EXTERNAL_ORDERS_PATH /api/orders API path
SUSPICIOUS_ORDER_TOTAL_THRESHOLD 50000 Alert threshold
BACKLOG_ORDER_AGE_MINUTES 30 Stale order threshold

Idempotency

Orders are upserted using a unique constraint:

UNIQUE (source_system, source_order_id)

Re-running sync updates existing orders instead of creating duplicates.

Audit Trail

Every sync operation records in order_sync_audit:

Column Example
source_system octo-drone-shop
source_order_id 3142
sync_action created / updated / failed
sync_status success / error
correlation_id 79c76c8173b086043b36e60422a2b317
trace_id Same as APM trace

Security Checks

  • Negative quantity detectionATTACK:MASS_ASSIGNMENT (critical)
  • Total mismatch (declared vs computed) → security event logged
  • Invalid order ID → skipped with audit record
  • Missing customer email → auto-generated fallback

Backlog Monitoring

Orders stuck in processing for > 30 minutes are flagged:

GET /api/integrations/security/summary
→ { "backlog_orders": 3, "oldest_age_minutes": 45, "high_value_pending": 1 }