-
Notifications
You must be signed in to change notification settings - Fork 0
Add configurable timeout handling to checkout service #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
Important Review skippedBot user detected. To trigger a single review, invoke the You can disable this status message by setting the WalkthroughThe changes introduce payment gateway timeout simulation to the NightOwl checkout service. Two environment variables control timeout duration and simulated response time. The Changes
Sequence DiagramsequenceDiagram
participant Client
participant Server as Checkout Handler
participant PaymentGateway as Payment Gateway<br/>(Simulated)
participant WebhookService as Webhook Service
Client->>Server: POST /api/checkout<br/>(email, movieId, price)
Server->>PaymentGateway: processPayment()
alt Response within timeout
PaymentGateway-->>Server: Success with<br/>transactionId
Server->>Client: 200 OK<br/>{transactionId, message}
else Response exceeds timeout
PaymentGateway-->>Server: Timeout Error
Server->>WebhookService: sendAlert()<br/>(CheckoutServiceTimeoutError)
WebhookService-->>Server: Alert sent
Server->>Client: 500 Error<br/>{service, code, message}
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
Comment |
Co-authored-by: wei <[email protected]>
Co-authored-by: wei <[email protected]>
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
NightOwl/server/index.js (1)
105-124: Minor: Response timer continues running after timeout rejection.When
PAYMENT_GATEWAY_RESPONSE_TIME > PAYMENT_GATEWAY_TIMEOUT, the timeout fires and rejects the promise, but the response timer continues running in the background. While JavaScript ignores the subsequentresolve()call (promises settle only once), the timer keeps running unnecessarily.For proper cleanup, consider clearing both timers:
async function processPayment(email, movieId, price) { return new Promise((resolve, reject) => { + let responseTimer; const timeout = setTimeout(() => { + clearTimeout(responseTimer); reject(new Error('Payment gateway did not respond in time')); }, PAYMENT_GATEWAY_TIMEOUT); // Simulate payment processing - setTimeout(() => { + responseTimer = setTimeout(() => { clearTimeout(timeout); resolve({ success: true, transactionId: `txn_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, email, movieId, price, }); }, PAYMENT_GATEWAY_RESPONSE_TIME); }); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
NightOwl/.env.example(1 hunks)NightOwl/README.md(2 hunks)NightOwl/server/index.js(3 hunks)
🧰 Additional context used
🪛 dotenv-linter (4.0.0)
NightOwl/.env.example
[warning] 10-10: [UnorderedKey] The PAYMENT_GATEWAY_RESPONSE_TIME key should go before the PAYMENT_GATEWAY_TIMEOUT key
(UnorderedKey)
🔇 Additional comments (6)
NightOwl/README.md (2)
58-73: LGTM! Clear configuration documentation.The new Configuration section properly documents all environment variables with their defaults and purposes. The guidance for copying
.env.exampleis helpful for new developers.
78-113: LGTM! API documentation accurately reflects the implementation.The updated endpoint documentation clearly explains the timeout simulation behavior, configuration options, and provides accurate request/response examples that match the server implementation.
NightOwl/.env.example (1)
5-10: LGTM! Well-documented configuration.The environment variables are properly documented with clear comments explaining their purpose and how to simulate timeouts. The current ordering (TIMEOUT before RESPONSE_TIME) is more intuitive than alphabetical ordering since it presents the constraint before the simulated value.
NightOwl/server/index.js (3)
10-11: LGTM! Proper environment variable parsing.Good use of
parseIntwith explicit radix and sensible defaults.
126-175: LGTM! Proper timeout handling implementation.The checkout handler correctly:
- Awaits
processPaymentwith proper try/catch- Returns 200 with transaction details on success
- Creates structured error with stack trace on timeout
- Sends webhook alert for monitoring
- Returns 500 with error details on failure
This properly fixes the original issue where checkout always failed with
CheckoutServiceTimeoutError.
209-210: LGTM! Helpful startup logs.Logging the configured timeout values at startup aids operational visibility and helps verify environment configuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes the checkout service that was always failing with timeout errors. It introduces configurable timeout handling that allows the payment gateway simulation to succeed under normal conditions while still being able to simulate timeout scenarios through configuration.
Key Changes:
- Implemented a
processPayment()function with Promise-based timeout logic that simulates payment gateway interaction - Added configurable timeout parameters via environment variables (
PAYMENT_GATEWAY_TIMEOUTandPAYMENT_GATEWAY_RESPONSE_TIME) - Modified
/api/checkoutendpoint to return success (200) when payment completes within timeout, error (500) only on actual timeouts
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| NightOwl/server/index.js | Added timeout configuration constants, implemented processPayment() function with race-based timeout logic, and wrapped checkout endpoint in try-catch to handle success and timeout cases differently |
| NightOwl/README.md | Added configuration section documenting new environment variables, updated API endpoint documentation with success/error response examples and timeout simulation instructions |
| NightOwl/.env.example | Added payment gateway configuration variables with descriptive comments explaining timeout simulation behavior |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| async function processPayment(email, movieId, price) { | ||
| return new Promise((resolve, reject) => { | ||
| const timeout = setTimeout(() => { | ||
| reject(new Error('Payment gateway did not respond in time')); | ||
| }, PAYMENT_GATEWAY_TIMEOUT); | ||
|
|
||
| // Simulate payment processing | ||
| setTimeout(() => { | ||
| clearTimeout(timeout); | ||
| resolve({ | ||
| success: true, | ||
| transactionId: `txn_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, | ||
| email, | ||
| movieId, | ||
| price, | ||
| }); | ||
| }, PAYMENT_GATEWAY_RESPONSE_TIME); | ||
| }); | ||
| } |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The timeout timer is not cleared when it fires, creating a resource leak. When the timeout rejects the promise on line 109, the response timer on line 113 is still scheduled and will eventually execute line 114 (clearTimeout(timeout)), but by then the promise has already been rejected. If the timeout fires, you should also clear the response timer to prevent unnecessary work and ensure clean resource cleanup.
| const timeoutError = new Error("CheckoutServiceTimeoutError: Payment gateway did not respond in time"); | ||
| timeoutError.name = "CheckoutServiceTimeoutError"; |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating a new error object here discards the original error and its stack trace from processPayment(). The original error's stack trace would show where the timeout actually occurred, which is valuable for debugging. Consider using the caught error directly or at least preserving its stack trace information.
| clearTimeout(timeout); | ||
| resolve({ | ||
| success: true, | ||
| transactionId: `txn_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The substr() method is deprecated. Use substring() or slice() instead. For this use case, slice(2, 11) would be the appropriate replacement.
| transactionId: `txn_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, | |
| transactionId: `txn_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`, |
|
|
||
| app.post('/api/checkout', async (req, res) => { | ||
| const { email, movieId, price } = req.body; | ||
|
|
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The endpoint lacks input validation for the request body parameters. Missing or invalid values for email, movieId, or price could lead to unexpected behavior or errors in downstream processing. Consider adding validation to ensure these parameters are present and have the expected types before processing the payment.
| // Input validation | |
| const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; | |
| if ( | |
| typeof email !== 'string' || !emailRegex.test(email) || | |
| typeof movieId !== 'string' || movieId.trim() === '' || | |
| typeof price !== 'number' || !isFinite(price) || price <= 0 | |
| ) { | |
| return res.status(400).json({ | |
| status: "error", | |
| service: "checkout-service", | |
| code: "InvalidRequest", | |
| message: "Invalid or missing parameters: email, movieId, and price are required and must be valid." | |
| }); | |
| } |
| const PAYMENT_GATEWAY_TIMEOUT = parseInt(process.env.PAYMENT_GATEWAY_TIMEOUT || '5000', 10); // Default 5 seconds | ||
| const PAYMENT_GATEWAY_RESPONSE_TIME = parseInt(process.env.PAYMENT_GATEWAY_RESPONSE_TIME || '2000', 10); // Simulated response time | ||
|
|
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parseInt() calls don't validate that the parsed values are positive numbers. If someone sets these environment variables to negative values or zero, it could cause unexpected behavior in the timeout logic. Consider adding validation to ensure these values are positive integers.
| const PAYMENT_GATEWAY_TIMEOUT = parseInt(process.env.PAYMENT_GATEWAY_TIMEOUT || '5000', 10); // Default 5 seconds | |
| const PAYMENT_GATEWAY_RESPONSE_TIME = parseInt(process.env.PAYMENT_GATEWAY_RESPONSE_TIME || '2000', 10); // Simulated response time | |
| // Helper to parse and validate positive integer environment variables | |
| function getPositiveIntEnv(varName, defaultValue) { | |
| const value = parseInt(process.env[varName], 10); | |
| if (Number.isInteger(value) && value > 0) { | |
| return value; | |
| } | |
| return defaultValue; | |
| } | |
| const PAYMENT_GATEWAY_TIMEOUT = getPositiveIntEnv('PAYMENT_GATEWAY_TIMEOUT', 5000); // Default 5 seconds | |
| const PAYMENT_GATEWAY_RESPONSE_TIME = getPositiveIntEnv('PAYMENT_GATEWAY_RESPONSE_TIME', 2000); // Simulated response time |
The checkout service always failed with
CheckoutServiceTimeoutErrorregardless of payment gateway responsiveness. Now implements proper timeout handling that succeeds under normal conditions and only fails on actual timeouts.Changes
Added timeout configuration via environment variables:
PAYMENT_GATEWAY_TIMEOUT(default: 5000ms) - maximum wait time for gateway responsePAYMENT_GATEWAY_RESPONSE_TIME(default: 2000ms) - simulated gateway latencyImplemented
processPayment()function with Promise-based timeout handling:Updated
/api/checkoutendpoint to return 200 on success, 500 only on actual timeoutAdded configuration documentation in
.env.exampleand READMETimeout errors can still be simulated by setting
PAYMENT_GATEWAY_RESPONSE_TIME>PAYMENT_GATEWAY_TIMEOUT.Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.
Summary by CodeRabbit
New Features
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.