Ingress — async and sync
POST /ingress vs POST /ingress/sync, auth, throttling, queue dispatch, and egress sync client
Base URL and routes
Ingress is served with globalPrefix: /ingress (port 3001 in dev). Effective routes:
| Method | Path | Guards |
|---|---|---|
POST | /ingress | AuthGuard |
POST | /ingress/sync | AuthGuard, EnterpriseSyncThrottleGuard |
GET | /ingress/health | (health controller) |
Controllers live in apps/ingress-service/src/controller/ingress.ts. The body type is Record<string, any> (validated downstream by business rules, not a single DTO class).
Async: POST /ingress
IngressService.receiveRequest:
loadInboundContext— Persists the raw JSON body to blob storage (DipV2Storage), creates an event log inpending, resolves app and events forctx.appId+ssoEnterpriseId.- Calls
requestHandler.handleRequestwithvoid(not awaited) so the HTTP response returns immediately. - Returns
{ ackId, message }whereackIdis the event log id.
So the client gets an acknowledgement while processing continues in the background.
Inside RequestHandler (async path, skipQueue false):
- Resolves connector–event mappings for the outbound event; may block the log if none exist or connectors are missing.
- Creates jobs and dip job tasks (cloning the event task tree into runtime tasks).
- For each pending job,
Dispatchpublishes to the Intent queue with job name
dip.v2.{ssoEnterpriseId}_{baCode}.regularor.prioritydepending on whether the mapping is marked priority. - Updates the event log to
jobs-createdwith connector ids.
Sync: POST /ingress/sync
receiveRequestSync awaits the same loadInboundContext, then handleRequest(..., { skipQueue: true }).
Sync-only rules enforced in request-handler.ts:
- At most one connector–event mapping for the outbound event; otherwise the log is blocked and a structured error is returned.
- With exactly one mapping, tasks must satisfy
validateLinearTaskChainForSync(single root, no branching) or sync fails with Sync API can't be used where task structure is not linear. - No
Dispatch— jobs stay queued for inline execution.
If processing succeeds and there are no jobs, the API returns a no-jobs shaped payload via SyncApiResponseTransformer.
If there are jobs, EgressSyncClient.executeJobs(pendingJobIds) runs:
- URL:
{baseUrl}/egress/internal/sync/executewherebaseUrlis the egress service root (no/egresssegment); seebuildEgressSyncExecuteUrlinegress-sync-client.ts. - Config:
services.gip.baseUrl(defaulthttp://127.0.0.1:3002),services.gip.timeoutMs(default 300000 ms). - On axios timeout,
EgressSyncTimeoutErroris caught and the client receives a timeout-shaped sync response (event log recorded; async processing may still complete).
Sequence
sequenceDiagram
participant Client
participant Ingress
participant Storage
participant Mongo
participant Kafka
participant Egress
Client->>Ingress: POST /ingress or /ingress/sync
Ingress->>Storage: persist raw payload
Ingress->>Mongo: event log, jobs, job tasks
alt async
Ingress->>Kafka: Dispatch dip.v2.enterprise_ba.regular or .priority
Ingress-->>Client: ackId
Kafka->>Egress: consumer
Egress->>Mongo: execute job tasks
else sync
Ingress->>Egress: POST .../egress/internal/sync/execute
Egress->>Mongo: executeJob inline
Egress-->>Ingress: job summaries
Ingress-->>Client: sync payload
endOther ingress behaviour
refDocNo: Extracted from the payload usingevent.refDocPath; if missing, sync returns a clear error (Ref doc no not found).- Sequential mappings (
isSequential+sequentialKey): May set job status blocked or interact with job sync checkpoints before dispatch.
Related
- Task tree — linear chain requirement for sync.
- Egress runtime and retry — what happens after dispatch or sync execute.