Skip to content

Database Integration

Both services share a single Oracle ATP instance with wallet-based mTLS authentication. This enables cross-service data correlation while maintaining service independence.

Connection Architecture

flowchart LR
    subgraph DroneShop ["Drone Shop"]
        DS_Main["Async Pool<br/>size=5, overflow=10"]
        DS_Sync["Sync Pool<br/>(security spans)"]
    end

    subgraph CRM ["CRM Portal"]
        CRM_Main["Async Pool<br/>size=10, overflow=20"]
        CRM_Auth["Auth Pool<br/>size=5, overflow=10"]
    end

    ATP[(Oracle ATP<br/>shared instance)]
    DBMgmt["DB Management<br/>Performance Hub"]
    OPSI["Operations Insights<br/>SQL Warehouse"]

    DS_Main --> ATP
    DS_Sync --> ATP
    CRM_Main --> ATP
    CRM_Auth --> ATP

    ATP --> DBMgmt
    ATP --> OPSI

Connection Pools

Service Pool Size Max Purpose
Drone Shop Main async 5 15 All HTTP route handlers
Drone Shop Sync 5 15 Security event persistence
CRM Portal Main async 10 30 HTTP routes + background tasks
CRM Portal Auth sync 5 15 Session validation (bounded)

Total ATP sessions: Up to 75 per replica pair (2 shop + 1 CRM)

Shared Tables

Both services use identical schemas for core tables:

Table Drone Shop CRM Sync Direction
customers Checkout creates Seed + synced CRM ← Shop
products 56 drone products 12 CRM products Independent SKU ranges
orders Checkout creates Synced + local CRM ← Shop (one-way)
order_items Via checkout Via sync CRM ← Shop
shipments Via checkout Via order sync CRM ← Shop
warehouses 4 regions 7 regions Independent
campaigns 4 campaigns 6 campaigns Independent
leads 6 leads 10 leads Independent
page_views Analytics Analytics Independent
audit_logs All requests All requests Append-only

Service-Exclusive Tables

Table Purpose
services Professional services catalog
tickets / ticket_messages Support system
cart_items Session-based shopping cart
reviews Product ratings
coupons Discount codes
security_events Attack detection records
assistant_sessions / assistant_messages GenAI chat
shops Dealer locations
Table Purpose
user_sessions ATP-backed session store (OKE replica sharing)
order_sync_audit Sync event audit trail
support_tickets CRM help desk
invoices Billing documents
reports Custom report definitions

Order Sync Data Flow

sequenceDiagram
    participant Shop as Drone Shop
    participant ATP as Oracle ATP
    participant CRM as CRM Portal

    Note over CRM: Every 300s (configurable)
    CRM->>Shop: GET /api/orders (traceparent header)
    Shop->>ATP: SELECT orders + items
    ATP-->>Shop: Order data
    Shop-->>CRM: JSON orders list

    loop For each order
        CRM->>ATP: SELECT customer WHERE email = :email
        alt Customer exists
            CRM->>ATP: UPDATE customer SET ...
        else New customer
            CRM->>ATP: INSERT INTO customers
        end
        CRM->>ATP: UPSERT order (source_system, source_order_id)
        CRM->>ATP: DELETE + INSERT order_items
        CRM->>ATP: INSERT order_sync_audit
    end

    Note over CRM: Unique constraint prevents duplicates
    Note over ATP: correlation_id links to APM trace

Sync Metadata

Orders synced from Drone Shop carry extra CRM columns:

-- CRM order columns for sync tracking
source_system       VARCHAR2(50)   -- 'octo-drone-shop'
source_order_id     NUMBER         -- Shop order ID
source_customer_email VARCHAR2(255) -- Normalized email
sync_status         VARCHAR2(50)   -- 'synced' | 'failed' | 'local'
backlog_status      VARCHAR2(50)   -- 'backlog' | 'current'
sync_error          VARCHAR2(4000) -- Error message if failed
source_payload      CLOB           -- Original JSON (audit)
correlation_id      VARCHAR2(64)   -- W3C trace ID
last_synced_at      TIMESTAMP

Oracle Session Tagging

Both services tag Oracle sessions for OPSI/DB Management correlation:

-- Set on pool checkout
DBMS_APPLICATION_INFO.SET_MODULE('octo-drone-shop-oke', 'POST /api/shop/checkout');
DBMS_SESSION.SET_IDENTIFIER('<trace_id>');

-- Result in V$SESSION
MODULE           = 'octo-drone-shop-oke'
ACTION           = 'POST /api/shop/checkout'
CLIENT_IDENTIFIER = '79c76c8173b086043b36e60422a2b317'

This enables: - DB Management → Performance Hub → filter by MODULE to see per-service SQL - OPSI → SQL Warehouse → filter by MODULE to see query patterns - APM → Trace Explorer → click SQL span → see DbOracleSqlId → jump to Performance Hub

SQL ID Computation

Both services compute Oracle-compatible SQL_IDs for APM → OPSI bridging:

# MD5(sql + '\0') → last 8 bytes → base-32 (Oracle alphabet)
# Result: 13-char SQL_ID matching V$SQL.SQL_ID

Span attribute DbOracleSqlId enables clicking a SQL span in APM Trace Explorer and jumping directly to the matching query in DB Management Performance Hub.