User Tools

Site Tools


flight_booking_bff

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
flight_booking_bff [2025/12/31 09:11] – [OpenTelemetry Tracing] pradnyaflight_booking_bff [2026/01/24 05:44] (current) – [Error Handling Strategy] madan
Line 15: Line 15:
 ==== Key Services / Core Components ==== ==== Key Services / Core Components ====
  
-^Service^Responsibility| +^Service^Responsibility^Local Port
-|**API Gateway / BFF (Node.js)** |Single entry point for UI| +|**API Gateway / BFF (Node.js)** |Single entry point for UI|4000
-|**Auth Service** |Issues & validates tokens| +|**Auth Service** |Issues & validates tokens|4001
-|**Flight Service** |Calls supplier API + Redis cache| +|**Flight Service** |Calls supplier API + Redis cache|4002
-|**Booking Service (MySQL)** |Stores booking data| +|**Booking Service (MySQL)** |Stores booking data|4003
-|**Payment Service** |Payment initiation + webhooks|+|**Payment Service** |Payment initiation + webhooks|4004| 
  
 ==== Observability Stack ==== ==== Observability Stack ====
  
-  * +  * **Pino** 
- +  * **Pino-Http** 
-**Pino** +  * **OpenTelemetry** 
-  * +  * **Cloud Logging (ELK / CloudWatch / Loki)**
- +
-**Pino-Http** +
-  * +
- +
-**OpenTelemetry** +
-  * +
- +
-**Cloud Logging (ELK / CloudWatch / Loki)**+
 === Token Flow Diagram === === Token Flow Diagram ===
 <code> <code>
Line 71: Line 64:
 <code> <code>
 Search Flights → Cache Results Search Flights → Cache Results
-Select Flight → Create Order+Select Flight → Create booking
 Initiate Payment → Payment Gateway Initiate Payment → Payment Gateway
-Webhook Received → Confirm Order+Webhook Received → Confirm booking
 Persist in MySQL → Send Confirmation Persist in MySQL → Send Confirmation
  
Line 80: Line 73:
 ===== Node.js Folder Structure (Clean Architecture) ===== ===== Node.js Folder Structure (Clean Architecture) =====
  
 +^Layer^Purpose^Examples^Should define errors?|
 +|**Domain** |Business rules|Entities, aggregates|**Business errors ** |
 +|**Domain/Application** |Use-cases / orchestration|Services, DTOs|**App errors ** |
 +|**Infrastructure** |Technical adapters|DB, Redis, HTTP|**Adapter-only errors ** |
 +|**Interface/API** |Controllers|REST/GraphQL|no core errors|
 <code> <code>
 +
 src/ src/
  ├ api/  ├ api/
  │   ├ controllers/  │   ├ controllers/
  │   ├ routes/  │   ├ routes/
- │   └ middlewares/+ │   ├ middlewares
 + │   └ errors/
  ├ domain/  ├ domain/
  │   ├ entities/  │   ├ entities/
  │   ├ services/  │   ├ services/
- │   └ repositories/+ │   ├ repositories
 + │   └ errors/
  ├ infrastructure/  ├ infrastructure/
  │   ├ db/  │   ├ db/
  │   ├ redis/  │   ├ redis/
  │   ├ logger/  │   ├ logger/
- │   └ http/+ │   ├ http
 + │   └ errors/
  └ tests/  └ tests/
  
 </code> </code>
 +
 +
 +
  
 ===== MySQL — Connection Pool ===== ===== MySQL — Connection Pool =====
Line 334: Line 339:
       * trace id       * trace id
   * Support dashboards & SLIs   * Support dashboards & SLIs
- 
  
 ===== Correlation ID Strategy ===== ===== Correlation ID Strategy =====
Line 374: Line 378:
 ==== Required JSON Fields ==== ==== Required JSON Fields ====
  <font 9px/inherit;;inherit;;inherit>bash</font>  <font 9px/inherit;;inherit;;inherit>bash</font>
- 
 <code> <code>
 +
 timestamp timestamp
 service service
Line 390: Line 394:
  
 </code> </code>
- 
  
 ===== Pino Implementation ===== ===== Pino Implementation =====
Line 397: Line 400:
  <font 9px/inherit;;inherit;;inherit>bash</font>  <font 9px/inherit;;inherit;;inherit>bash</font>
  
-<code>npm i pino pino-http pino-pretty+<code> 
 +npm i pino pino-http pino-pretty 
 </code> </code>
  
Line 416: Line 421:
  
 </code> </code>
- 
  
 ==== HTTP Logger ( /src/infrastructure/logger/http-logger.ts ) ==== ==== HTTP Logger ( /src/infrastructure/logger/http-logger.ts ) ====
  <font 9px/inherit;;inherit;;inherit>ts</font>  <font 9px/inherit;;inherit;;inherit>ts</font>
- 
 <code> <code>
  
Line 437: Line 440:
  
 </code> </code>
- 
  
 ==== Express Usage ==== ==== Express Usage ====
  <font 9px/inherit;;inherit;;inherit>ts</font>  <font 9px/inherit;;inherit;;inherit>ts</font>
- 
 <code> <code>
  
Line 452: Line 453:
  
 </code> </code>
- 
  
 ==== Business Logging Example ==== ==== Business Logging Example ====
Line 459: Line 459:
 <code> <code>
 req.log.info({ req.log.info({
-  orderId,+  bkgId,
   redisKey,   redisKey,
-  step: 'order-confirmation' +  step: 'booking-confirmation' 
-}, 'Order confirmed');+}, 'Booking confirmed');
  
 </code> </code>
- 
  
 ==== OpenTelemetry Tracing ==== ==== OpenTelemetry Tracing ====
Line 473: Line 472:
   * traceId   * traceId
   * spanId   * spanId
- 
  
 ==== Benefits ==== ==== Benefits ====
Line 481: Line 479:
   * error attribution   * error attribution
  
-<code>Code to link trace → logs → DB query+<code> 
 +Code to link trace → logs → DB query 
 </code> </code>
  
Line 495: Line 495:
  <font 9px/inherit;;inherit;;inherit>ts</font>  <font 9px/inherit;;inherit;;inherit>ts</font>
  
-<code>describe('logger', () => { \\ +<code> 
-  it('logs JSON structure', () => { \\ +describe('logger', () => { 
-    const log = logger.info({ test: true }, 'hello'); \\ +  it('logs JSON structure', () => { 
-    expect(log).toBeDefined(); \\ +    const log = logger.info({ test: true }, 'hello'); 
-  }); \\ +    expect(log).toBeDefined(); 
-}); \\+  }); 
 +});
  
 </code> </code>
  
 +====== Error Handling Strategy ======
 +
 +**1. Client Errors (4xx)**
 +
 +^Code^Meaning|
 +|400|Bad Request/validation failure|
 +|401|unauthorized|
 +|404|cache expired|
 +|409|idempotency conflict|
 +|500|internal error|
 +
 +**2. Server Errors (5xx)**
 +
 +^Type^Source^Action|
 +|Dependency Failure|Redis/MySQL|Retry / Circuit Breaker|
 +|Timeout|3rd-party API|Fail fast|
 +|Internal Crash|unexpected bug|Log & alert|
 +
 +**3. Business Errors**
 +
 +^Example^Handling|
 +|Flight unavailable|409|
 +|Payment declined|422|
 +|Invalid state transition|409|
 +
 +===== Recommended Placement =====
 +
 +**1. ****Business / Domain Errors**
 +
 +When business rule is violeted -
 + <font inherit/inherit;;inherit;;#dddddd>/src/domain/errors</font>
 + <font 9px/inherit;;inherit;;inherit>ts</font>
 +
 +<code>
 +export class FlightUnavailableError extends Error {
 +  code = 'FLIGHT_UNAVAILABLE';
 +}
 +
 +</code>
 +
 +**2. ****Application Errors**
 +
 +Use-case level\\
 +Validation / workflow / orchestration
 +
 +/src/application/errors
 + <font 9px/inherit;;inherit;;inherit>ts</font>
 +
 +<code>
 +export class ValidationError extends Error {
 +  status = 400;
 +  code = 'VALIDATION_ERROR';
 +}
 +
 +</code>
 +
 +**3. ****Infrastructure Errors**
 +
 +ONLY for wrapping technical failures
 +
 +/src/infrastructure/errors
 + <font 9px/inherit;;inherit;;inherit>ts</font>
 +
 +<code>
 +export class RedisConnectionError extends Error {
 +  code = 'REDIS_CONNECTION_ERROR';
 +}
 +
 +</code>
 +
 +BUT — these should usually be **mapped upward** into application-level errors.
 +
 +Example mapping:
 + <font 9px/inherit;;inherit;;inherit>ts</font>
 +
 +<code>
 +try {
 +   await redis.get(key);
 +} catch(e) {
 +   throw new CacheUnavailableError();
 +}
 +
 +</code>
 +
 +So the **API layer never leaks Redis internals.**
 +
 +
 +===== Error Flow (Best Practice) =====
 +
 +<code>
 +Infrastructure error
 +   ⬇ wrap / map
 +Application error
 +   ⬇ serialized to client
 +HTTP response
 +
 +</code>
 +
 +final structure should look like
 +
 +<code>
 +/src
 + ┣ /domain
 + ┃   ┗ /errors   ← Business rule errors
 + ┣ /application
 + ┃   ┗ /errors   ← Validation + workflow errors
 + ┣ /infrastructure
 + ┃   ┗ /errors   ← Technical adapter errors (wrapped)
 + ┗ /api (interfaces)
 +     ┗ error-middleware.ts  ← converts to HTTP response
 +
 +</code>
 +
 +**What to AVOID**
 +
 +Defining all errors in ''infrastructure'' \\
 +→ couples business logic to technology
 +
 +Throwing raw DB/Redis errors upward\\
 +→ leaks internal details
  
 +Mixed styles (sometimes returning strings, sometimes errors)\\
 +→ debugging nightmare
  
  
flight_booking_bff.1767172292.txt.gz · Last modified: by pradnya