Skip to content

Request Lifecycle

Two kinds of "requests" run through Prism: synchronous HTTP requests and asynchronous queue/cron work. Understanding both is essential — most Prism features are initiated by HTTP but completed asynchronously.

1. Synchronous HTTP request

flowchart TD
    A[Incoming HTTP request] --> B["bodyParser (urlencoded + json)"]
    B --> C[CORS wildcard]
    C --> D["traceIdMiddleware<br/>(AsyncLocalStorage sets trace_id)"]
    D --> E["requestLogger<br/>(detects plaintext password, never logs value)"]
    E --> F{Route match}
    F --> G["Route-level auth middleware<br/>(authMiddleware / adminMiddleware /<br/>appMiddleware / jwt* / crm_offer / injestion)"]
    G -->|reject| G2[403/401 fail-closed]
    G -->|pass, sets req.body.created_by /<br/>req.parent_business_id| H[Controller function]
    H --> I["Business logic:<br/>commonFunctions / processLibrary / raw SQL / mongoose"]
    I --> J{Work type}
    J -->|read| K[Query Mongo/MySQL/Redis → respond]
    J -->|write that needs async| L[Enqueue into a queue collection → respond 'accepted']
    K --> M[JSON response]
    L --> M

Middleware order (from index.js)

  1. bodyParser.urlencoded + bodyParser.json
  2. cors()wildcard origin ⚠️
  3. loggerService.traceIdMiddleware() — sets a request-scoped trace_id (from x-trace-id header or a new UUID v4) so every log line in the request correlates.
  4. requestLogger — security monitor: flags requests carrying a plaintext password (logs metadata, never the value).
  5. Route mounting, each route attaching its own auth middleware.

Auth selection by route family

Route family Base path Typical middleware
CRM app (staff/web) /crm_api, /crm_api/v2, /stats authMiddleware (some open)
Admin within /crm_api adminMiddleware (business_id==1)
Customer app (loyalty) prism_routes/loyalty_rewards appMiddleware
POS / 3rd-party integration /integration/v1, parts of /injestion crm_offer_middleware
Order ingestion (specific) /injestion/ls_center, /sync/crm/token injestion_middleware (static token)
WhatsApp login prism_routes/whatsapp_login jwtWhatsappMiddleware

Details: Authentication. Full route tables: API.

Important pattern: many controllers enqueue rather than fully process. E.g. an ingestion POST returns 200 after inserting into crm_queue with status:0; the real work happens later in a cron. Always ask: "is this endpoint synchronous or fire-and-forget?"

2. Asynchronous (cron/queue) lifecycle

The generic queue pattern used throughout Prism:

stateDiagram-v2
    [*] --> queued: producer inserts (status=0 / pending)
    queued --> in_progress: cron picks batch
    in_progress --> done: success (status=processed/sent)
    in_progress --> retry: transient failure (retry_count++)
    retry --> in_progress: next cron tick (backoff)
    retry --> failed: max retries exceeded
    in_progress --> failed: permanent error
    done --> [*]
    failed --> [*]

Concrete queues (see Queues for the full catalog):

Queue Producer Consumer cron Cadence
crm_queue (orders) ingestion (Lambda + monolith) ingestion crons frequent poll
crm_points_allocation_queue (MySQL) order processing, rewards, referral points allocation cron ~every 2 min, ~5000/batch, 5 retries
WhatsApp queue campaign/journey builders sendWhatsappMessageCron (+ transactional/remaining) ~1–3 sec poll
SMS queue campaign builders smsQueueCron ~3 min
Push queue campaign builders pushQueueCron ~5 min
notiJunk notification producers processNotiQueue / delete crons periodic

3. End-to-end: "an order becomes a WhatsApp win-back"

Ties the whole system together across sync + async boundaries:

sequenceDiagram
    autonumber
    participant POS
    participant ING as Ingestion (HTTP/Lambda)
    participant Q as crm_queue
    participant PROC as Ingestion cron
    participant C360 as Customer/Order data
    participant PTS as Points queue (MySQL)
    participant RFM as rfmSegments cron (nightly)
    participant JRNY as processAutomatedCampaigns
    participant WQ as WhatsApp queue
    participant SND as sendWhatsappCron
    participant GS as Gupshup/Meta
    participant ROI as ROI attribution cron

    POS->>ING: order
    ING->>Q: enqueue status:0
    PROC->>Q: drain
    PROC->>C360: upsert customer + order
    PROC->>PTS: enqueue earned points
    Note over RFM: nightly
    RFM->>C360: recompute R/F/M → segment=At Risk
    Note over JRNY: journey 'Lost Customers' matches
    JRNY->>WQ: enqueue message to At-Risk customer
    SND->>WQ: poll
    SND->>GS: send template
    GS-->>SND: delivered/read webhook
    Note over ROI: customer orders within attribution window
    ROI->>C360: attribute revenue to journey

4. Error handling & tracing

  • trace_id flows through logs within a single HTTP request (AsyncLocalStorage). Grep logs by trace_id to reconstruct a request. See Debugging.
  • Auth failures are fail-closed (403/500 on any error).
  • Queue failures rely on status + retry_count fields and backoff; there is no global DLQ — stuck items sit in the queue and are surfaced by cleanup/monitor crons.
  • Cron overlap protection: several crons use a status/lock document (e.g. cron_stats, checkin_cron_status) to avoid concurrent runs; stuck-cron detection is reactive (~20 min) with a force-close fallback (~4 h). ⚠️ Not fully robust — see Tech Debt.

5. What to check when "nothing happened"

Symptom Where to look
Order didn't appear crm_queue for status:0 stuck docs; ingestion cron logs
Points not credited crm_points_allocation_queue status/retry; handleWalletPointsFlow logs
Campaign not delivered WhatsApp/SMS/push queue status; business wallet balance; provider errors
Segment stale rfmSegments / customerInsightsCron last run (cron_stats)
Dashboard number off MIS/aggregation cron freshness; cross-widget integrity (see Common Issues)

Assessment

Level-5 production-debugging: ../15-Assessments/Level-5-Production-Debugging.md