tesco interview experience
Anonymous User
654

/*
You're developing a backend service for a real-time analytics dashboard that tracks user interactions across an e-commerce platform. Your service needs to:

Process incoming event data from multiple sources
Perform aggregation operations
Provide API endpoints for the frontend dashboard with summarized data (given below)

Core Requirements:

Your service needs to fetch and combine data from three internal data sources:

User Activity Service: Tracks page views, clicks, and session data
Transaction Service: Tracks purchases, cart additions, and checkout events
Inventory Service: Tracks product stock levels and alerts

Note that each service has different response characteristics, data formats, and reliability issues:

/**

  • Fetches recent user activity data

  • Returns detailed user interaction events

  • High volume data, occasionally returns partial results

  • ~150ms average response time with occasional spikes
    */
    async function fetchUserActivity(timeWindow) {
    return new Promise((resolve, reject) => {
    const delay = 100 + Math.random() * 100; // 100-200ms
    setTimeout(() => {
    if (Math.random() < 0.15) {
    // Sometimes returns partial data with an error flag
    resolve({
    events: generateRandomEvents(Math.floor(Math.random() * 10) + 5),
    complete: false,
    error: "Service degraded, partial data returned"
    });
    } else if (Math.random() < 0.05) {
    // Occasionally fails completely
    reject(new Error("User activity service temporarily unavailable"));
    } else {
    resolve({
    events: generateRandomEvents(Math.floor(Math.random() * 20) + 10),
    complete: true
    });
    }
    }, delay);
    });

    function generateRandomEvents(count) {
    const events = [];
    const eventTypes = ["page_view", "click", "scroll", "search"];

     for (let i = 0; i < count; i++) {
         events.push({
             eventId: `evt-${Math.random().toString(36).substring(2, 10)}`,
             userId: `user-${Math.floor(Math.random() * 1000)}`,
             type: eventTypes[Math.floor(Math.random() * eventTypes.length)],
             timestamp: Date.now() - Math.floor(Math.random() * 60000),
             data: {
                 page: Math.random() < 0.5 ? "/products" : "/checkout",
                 duration: Math.floor(Math.random() * 300)
             }
         });
     }
     return events;

    }
    }

/**

  • Fetches recent transaction data

  • Returns financial transaction information

  • Slower but fairly reliable service

  • Data format differs from user activity
    */
    async function fetchTransactions(timeWindow) {
    return new Promise((resolve, reject) => {
    const delay = 200 + Math.random() * 150; // 200-350ms
    setTimeout(() => {
    if (Math.random() < 0.08) {
    reject(new Error("Transaction service unavailable"));
    } else {
    const transactions = [];
    const count = Math.floor(Math.random() * 8) + 2;

             for (let i = 0; i < count; i++) {
                 transactions.push({
                     transactionId: `tx-${Date.now()}-${Math.random().toString(36).substring(2, 7)}`,
                     customerData: {
                         id: `user-${Math.floor(Math.random() * 1000)}`,
                     },
                     amount: +(Math.random() * 200 + 10).toFixed(2),
                     status: Math.random() < 0.9 ? "completed" : "pending",
                     items: Math.floor(Math.random() * 5) + 1,
                     createdAt: new Date(Date.now() - Math.floor(Math.random() * 3600000)).toISOString()
                 });
             }
             resolve({
                 data: transactions,
                 meta: {
                     total: transactions.length,
                     timeframe: timeWindow
                 }
             });
         }
     }, delay);

    });
    }

/**

  • Fetches inventory status updates

  • Returns stock level alerts and changes

  • Fast but returns data in a completely different structure
    */
    async function fetchInventoryAlerts(urgencyLevel = "all") {
    return new Promise((resolve, reject) => {
    const delay = 50 + Math.random() * 100; // 50-150ms
    setTimeout(() => {
    if (Math.random() < 0.1) {
    reject(new Error("Inventory service connection refused"));
    } else {
    // Returns XML-like string that needs parsing
    const alertCount = Math.floor(Math.random() * 5);
    let xmlResponse = <inventory-alerts generated="${new Date().toISOString()}" count="${alertCount}">;

             for (let i = 0; i < alertCount; i++) {
                 const productId = Math.floor(Math.random() * 1000);
                 const currentStock = Math.floor(Math.random() * 10);
                 const threshold = 5;
                 const urgency = currentStock < 2 ? "high" : "medium";
    
                 if (urgencyLevel === "all" || urgencyLevel === urgency) {
                     xmlResponse += `
             <alert type="stock" urgency="${urgency}">
               <product id="${productId}" />
               <current-stock>${currentStock}</current-stock>
               <threshold>${threshold}</threshold>
               <location warehouse="${Math.floor(Math.random() * 5) + 1}" />
             </alert>
           `;
                 }
             }
    
             xmlResponse += '</inventory-alerts>';
             resolve(xmlResponse);
         }
     }, delay);

    });
    }
    /*

Task:
Create an Express.js API endpoint that:

Implements a GET /api/dashboard endpoint that accepts a timeWindow query parameter (e.g., "15m", "1h", "24h")
Fetches data from all three services concurrently
Handles the different response formats, error scenarios, and partial data
Aggregates the data into a unified dashboard response
Implements proper timeout handling (maximum 300ms total response time)

Sample response :
{
"dashboard": {
"timeWindow": "15m", // or whatever was requested
"summary": {
"activeUsers": 42,
"revenueTotal": 1234.56,
"conversionRate": 2.7,
"inventoryAlerts": 3
},
"details": {
"userActivity": {
// Processed user activity data
"complete": true|false,
// Additional details
},
"transactions": {
// Processed transaction data
// Additional details
},
"inventory": {
// Processed inventory data
// Additional details
}
},
"status": {
"servicesResponded": ["userActivity", "transactions", "inventory"],
"servicesFailed": [],
"responseTime": 298
}
}
}
*/

Comments (1)