-
Notifications
You must be signed in to change notification settings - Fork 61
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
fix(core): Handle SIGTERM
for graceful shutdowns
#16882
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThe pull request introduces a new function, Changes
Possibly related PRs
Suggested reviewers
📜 Recent review detailsConfiguration used: .coderabbit.yaml 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #16882 +/- ##
=======================================
Coverage 35.68% 35.68%
=======================================
Files 6941 6941
Lines 147233 147234 +1
Branches 41863 41863
=======================================
+ Hits 52540 52542 +2
+ Misses 94693 94692 -1 Flags with carried forward coverage won't be shown. Click here to find out more.
... and 1 file with indirect coverage changes Continue to review full report in Codecov by Sentry.
|
Datadog ReportAll test runs ✅ 51 Total Test Services: 0 Failed, 44 Passed Test ServicesThis report shows up to 10 services
🔻 Code Coverage Decreases vs Default Branch (6)
|
SIGTERM
for graceful shutdownsSIGTERM
for graceful shutdowns
Affected services are: air-discount-scheme-api,air-discount-scheme-backend,api,application-system-api,download-service,financial-aid-api,financial-aid-backend,financial-aid-open-api,icelandic-names-registry-backend,judicial-system-api,judicial-system-digital-mailbox-api,judicial-system-backend,judicial-system-xrd-api,license-api,reference-backend,regulations-admin-backend,services-auth-admin-api,services-auth-ids-api,services-auth-delegation-api,services-auth-personal-representative,services-auth-personal-representative-public,services-auth-public-api,services-bff,services-documents,services-endorsements-api,services-form-system,services-search-indexer,services-sessions,services-university-gateway,services-user-notification,services-user-profile,skilavottord-ws,air-discount-scheme-web,auth-admin-web,consultation-portal,contentful-apps,financial-aid-web-osk,financial-aid-web-veita,judicial-system-web,skilavottord-web,web,application-system-form,island-ui-storybook,portals-admin,service-portal,system-e2e, Deployed services: application-system-api,application-system-form,service-portal,service-portal-api,portals-admin,consultation-portal,api,web,skilavottord-web,skilavottord-ws,services-documents,island-ui-storybook,download-service,icelandic-names-registry-backend,endorsement-system-api,air-discount-scheme-web,air-discount-scheme-backend,air-discount-scheme-api,regulations-admin-backend,application-system-api-worker,license-api,services-sessions,services-sessions-worker,services-sessions-cleanup,services-university-gateway,services-university-gateway-worker,services-bff-portals-admin. |
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: 2
🧹 Outside diff range and nitpick comments (3)
libs/infra-next-server/src/lib/bootstrap.ts (2)
Line range hint
108-116
: Enhance error handling type safety and developer experienceWhile the error logging is comprehensive, there's room for improvement in type safety and developer experience.
Consider these enhancements:
- } catch (err: any) { + } catch (err: unknown) { + const error = err instanceof Error ? err : new Error(String(err)) logger.error('Error in Next.js request handler!', { - message: err.message, - stack: err.stack, - err, + message: error.message, + stack: error.stack, + error, }) - res.status(500).send('Internal Server Error') + res.status(500).send( + dev ? `Internal Server Error: ${error.message}` : 'Internal Server Error' + ) }
Line range hint
1-144
: Consider improving module architecture for better reusabilityAs this module is in the
libs
directory, it should prioritize reusability and separation of concerns.Consider these architectural improvements:
- Extract server lifecycle management into a separate class:
class NextServerLifecycle { private server: Express; private nextApp: NextApp; async start(options: BootstrapOptions): Promise<void> { // initialization logic } async shutdown(): Promise<void> { // graceful shutdown logic } }
- Return the lifecycle instance from bootstrap:
export const bootstrap = async (options: BootstrapOptions) => { const lifecycle = new NextServerLifecycle(); await lifecycle.start(options); return lifecycle; }This would:
- Make the server state manageable
- Improve testability
- Allow proper cleanup in consuming applications
libs/infra-express-server/src/lib/infra-express-server.ts (1)
84-89
: Consider using a custom error type instead ofany
While the eslint disable comment acknowledges the
any
usage, consider creating a custom error type for better type safety and documentation.Example implementation:
interface AppError extends Error { status?: number; // Add other common error properties } function errorHandler( err: AppError, _req: Request, res: Response, _next: NextFunction, ) { // ... existing implementation }
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (2)
libs/infra-express-server/src/lib/infra-express-server.ts
(5 hunks)libs/infra-next-server/src/lib/bootstrap.ts
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
libs/infra-express-server/src/lib/infra-express-server.ts (1)
Pattern libs/**/*
: "Confirm that the code adheres to the following:
- Reusability of components and hooks across different NextJS apps.
- TypeScript usage for defining props and exporting types.
- Effective tree-shaking and bundling practices."
libs/infra-next-server/src/lib/bootstrap.ts (1)
Pattern libs/**/*
: "Confirm that the code adheres to the following:
- Reusability of components and hooks across different NextJS apps.
- TypeScript usage for defining props and exporting types.
- Effective tree-shaking and bundling practices."
🔇 Additional comments (2)
libs/infra-express-server/src/lib/infra-express-server.ts (2)
61-65
: LGTM! Parameter naming improved for clarity
The renaming of unused parameters to _req
follows TypeScript conventions and improves code readability.
105-105
: LGTM! Verify server shutdown behavior
The placement of setupExitHook
after server setup is correct. However, let's verify the shutdown behavior across the codebase.
✅ Verification successful
Let me gather more information about signal handlers with a corrected regex pattern.
Let me search for the setupExitHook implementation to verify the shutdown behavior.
Let me search for the setupExitHook implementation in the specific file and its imports.
LGTM! Server shutdown behavior is properly implemented
The setupExitHook implementation correctly handles server shutdown by:
- Setting up handlers for SIGHUP, SIGINT, and SIGTERM signals to gracefully exit
- Including special handling for test environments via NX_INVOKED_BY_RUNNER check
- Using proper logging to track shutdown events
- Calling process.exit(0) to ensure clean termination
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for other signal handlers or shutdown logic that might conflict
# Search for signal handling
rg -A 5 "process\.on\((\'|\")SIG"
# Search for server shutdown logic
ast-grep --pattern 'server.close($$$)'
Length of output: 574
Script:
#!/bin/bash
# Search for signal handling with corrected regex
rg -A 5 "process\.on\(['\"]SIGTERM|process\.on\(['\"]SIGINT"
# Search for setupExitHook implementation
ast-grep --pattern 'function setupExitHook($$$)'
# Also check for any shutdown or cleanup functions
rg -A 5 "shutdown|cleanup|graceful.*stop"
Length of output: 153750
Script:
#!/bin/bash
# Search for setupExitHook implementation
ast-grep --pattern 'function setupExitHook($$$)'
# Also search for any signal handlers or cleanup code
rg -A 5 'process\.on\((["'\''])(SIGTERM|SIGINT)'
Length of output: 274
Script:
#!/bin/bash
# Check the file content and its imports
cat libs/infra-express-server/src/lib/infra-express-server.ts
# Search for any files importing setupExitHook
rg "setupExitHook"
Length of output: 3331
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: 3
🧹 Outside diff range and nitpick comments (3)
libs/infra-next-server/src/lib/bootstrap.ts (2)
Line range hint
32-43
: Restructure server initialization for proper shutdown handlingThe
startServer
function creates the HTTP server but doesn't return it, making it impossible for the shutdown hook to properly close the server.Consider restructuring the code to maintain the server reference:
-const startServer = (app: Express, port = 4200) => { +const startServer = (app: Express, port = 4200): Promise<http.Server> => { const nextPort = parseInt(process.env.PORT || '') || port const metricsPort = nextPort + 1 - app.listen(nextPort, () => { - logger.info( - `Next custom server listening at http://localhost:${nextPort}`, - { - context: 'Bootstrap', - }, - ) - }) - startMetricServer(metricsPort) + return new Promise((resolve) => { + const server = app.listen(nextPort, () => { + logger.info( + `Next custom server listening at http://localhost:${nextPort}`, + { + context: 'Bootstrap', + }, + ) + startMetricServer(metricsPort) + resolve(server) + }) + }) } -const setupExitHook = () => { +const setupExitHook = (server: http.Server) => { // ... signal handling code ... } export const bootstrap = async (options: BootstrapOptions) => { // ... - setupExitHook() const expressApp = createExpressApp() // ... other setup code ... - startServer(expressApp, options.port) + const server = await startServer(expressApp, options.port) + setupExitHook(server) // ... }Also applies to: 78-82
Line range hint
95-108
: Add request timeout handling for graceful shutdownsLong-running requests could prevent graceful shutdown from completing. Consider adding timeout handling to ensure requests don't hang indefinitely.
Add timeout middleware:
+const REQUEST_TIMEOUT = 5000 // 5 seconds +expressApp.use((req, res, next) => { + res.setTimeout(REQUEST_TIMEOUT, () => { + logger.warning('Request timeout exceeded', { + url: req.url, + method: req.method, + timeout: REQUEST_TIMEOUT, + }) + res.status(504).send('Gateway Timeout') + }) + next() +}) expressApp.use(async (req, res) => { // ... existing code ... })libs/infra-express-server/src/lib/infra-express-server.ts (1)
61-61
: Add error handling for version endpointWhile the parameter naming changes look good, the
/version
endpoint should handle cases whereREVISION
environment variable is undefined.Consider this improvement:
app.get('/version', function versionOfCode(_req, res) { - res.json({ version: process.env.REVISION }) + res.json({ version: process.env.REVISION || 'unknown' }) }Also applies to: 65-65
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (2)
libs/infra-express-server/src/lib/infra-express-server.ts
(5 hunks)libs/infra-next-server/src/lib/bootstrap.ts
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
libs/infra-express-server/src/lib/infra-express-server.ts (1)
Pattern libs/**/*
: "Confirm that the code adheres to the following:
- Reusability of components and hooks across different NextJS apps.
- TypeScript usage for defining props and exporting types.
- Effective tree-shaking and bundling practices."
libs/infra-next-server/src/lib/bootstrap.ts (1)
Pattern libs/**/*
: "Confirm that the code adheres to the following:
- Reusability of components and hooks across different NextJS apps.
- TypeScript usage for defining props and exporting types.
- Effective tree-shaking and bundling practices."
🔇 Additional comments (1)
libs/infra-express-server/src/lib/infra-express-server.ts (1)
Line range hint 76-88
: Security middleware requires immediate attention
The current middleware allows all requests to pass through without any authentication, which could pose a security risk in production.
Let's verify if there are any authenticated routes that might be exposed:
Consider implementing proper authentication before deploying to production. Here's a basic structure:
app.use((req, res, next) => {
const token = req.headers.authorization?.split(' ')[1]
if (!token) {
return res.status(401).json({ error: 'Authentication required' })
}
// Verify token and proceed
next()
})
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.
I was checking the other day and I'm not sure if any of our servers are using infra-express-server
. It might have been a blueprint which went unused.
I also think this SIGTERM handling is worse then the current SIGKILL fallback. There's nothing graceful about process.exit(0)
. Afaik it will just abruptly exit the process and close all open connections, resulting in socket issues.
Currently at least there's a chance that current requests finish and the load balancer stops sending new requests to the pod before its eventual SIGKILL. 🤔
db27f92
to
97d6a57
Compare
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: 2
🧹 Outside diff range and nitpick comments (11)
libs/node/utils/src/lib/setupShutdownHooks.ts (3)
8-14
: Consider adding SIGQUIT signal handlerWhile the current signal handling covers the most common scenarios, consider adding
SIGQUIT
for complete signal coverage, especially in Unix-like environments.- const terminationEvents = ['SIGHUP', 'SIGINT', 'SIGTERM'] + const terminationEvents = ['SIGHUP', 'SIGINT', 'SIGTERM', 'SIGQUIT']
37-39
: Consider cleanup of signal handlersWhile the current implementation works, it's good practice to clean up signal handlers when the server closes to prevent memory leaks in long-running applications that might restart the server.
+ const cleanupListeners = () => { + for (const signal of terminationEvents) { + process.removeListener(signal, () => shutdown(signal)) + } + } + for (const signal of terminationEvents) { process.on(signal, () => shutdown(signal)) } + + server.on('close', cleanupListeners)
1-40
: Add comprehensive documentation and testing guidelinesAs this is a critical utility function in the shared library, consider:
- Adding JSDoc documentation with examples
- Creating integration tests with different signal scenarios
- Documenting recommended usage patterns in the README
This will help other developers properly integrate the shutdown hooks in their services.
libs/node/utils/README.md (3)
9-10
: Improve parameter documentation clarityThe
onShutdown
parameter description should be restructured for better clarity.-- `onShutdown` (Function): Optional callback function that will be executed before the server shuts down. Can be used to perform and wait for other cleanup tasks before the server shuts down. ++ `onShutdown` (Function): Optional callback function that will be executed before the server shuts down. It can be used to perform and wait for other cleanup tasks.🧰 Tools
🪛 LanguageTool
[style] ~10-~10: To form a complete sentence, be sure to include a subject.
Context: ... executed before the server shuts down. Can be used to perform and wait for other c...(MISSING_IT_THERE)
16-20
: Add error handling details to behavior documentationThe behavior section should include information about error handling scenarios and potential error types.
Consider adding the following details:
- Types of errors that might occur during shutdown
- How errors are propagated
- Whether the
onShutdown
callback errors are caught and handled
22-24
: Enhance testing documentationThe testing section would benefit from examples of specific test cases that users should implement.
Consider adding:
- Test scenarios for different termination signals
- Examples of mocking the server and shutdown process
- Test cases for error conditions
- Examples of testing the
onShutdown
callback functionalitylibs/infra-express-server/src/lib/infra-express-server.ts (1)
69-72
: Consider enhancing the error handler implementationWhile the parameter naming is correct, the error handler could benefit from improvements:
+interface ApiError extends Error { + status?: number; +} app.use(function errorHandler( - err: any, + err: ApiError, _req: Request, res: Response, _next: NextFunction, ) { logger.error(`Status code: ${err.status}, msg: ${err.message}`) res.status(err.status || 500) - res.send(err.message) + res.json({ + error: { + message: err.message, + status: err.status || 500 + } + }) }libs/infra-nest-server/src/lib/bootstrap.ts (1)
49-51
: Consider documenting shutdown behavior with keep-alive connections.While the implementation is correct, the interaction between the 30-second
KEEP_ALIVE_TIMEOUT
and shutdown signals could affect shutdown timing. Long-lived connections might delay the shutdown process.Consider:
- Adding a comment documenting this interaction
- Implementing a maximum shutdown timeout
- Logging when shutdown is initiated and completed
Here's a suggested comment addition:
// Handle signals like SIGINT, SIGTERM and SIGHUP gracefully. + // Note: Active keep-alive connections (timeout: 30s) may delay shutdown app.enableShutdownHooks()
Also applies to: 18-19
libs/node/utils/src/lib/setupShutdownHooks.spec.ts (3)
18-37
: Enhance type safety in test setup.While the test setup is comprehensive, consider improving type safety:
- server = { - close: jest.fn((callback) => callback()), - } as unknown as Server + server = { + close: jest.fn((callback?: (err?: Error) => void) => { + if (callback) callback(); + return server; + }), + } as Partial<Server> as Server
39-86
: Consider extracting common test patterns.The signal handler extraction is repeated across multiple tests. Consider creating a helper function:
const getSignalHandler = (signal: string, spy: jest.SpyInstance): Function => { return spy.mock.calls.find(([event]) => event === signal)[1]; };
88-151
: Comprehensive error handling test coverage.The test cases thoroughly cover error scenarios and callback handling. Great job on including both successful and failure paths for the onShutdown callback.
However, consider adding one more test case:
it('should handle multiple signals in sequence', async () => { setupShutdownHooks(server); const sigTermHandler = getSignalHandler('SIGTERM', processOnSpy); const sigIntHandler = getSignalHandler('SIGINT', processOnSpy); await sigTermHandler(); await sigIntHandler(); expect(server.close).toHaveBeenCalledTimes(1); // Should only close once expect(processExitSpy).toHaveBeenCalledTimes(1); });
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (14)
libs/infra-express-server/src/lib/infra-express-server.ts
(5 hunks)libs/infra-nest-server/src/lib/bootstrap.ts
(1 hunks)libs/infra-next-server/src/lib/bootstrap.ts
(2 hunks)libs/node/utils/.eslintrc.json
(1 hunks)libs/node/utils/README.md
(1 hunks)libs/node/utils/jest.config.ts
(1 hunks)libs/node/utils/project.json
(1 hunks)libs/node/utils/src/index.ts
(1 hunks)libs/node/utils/src/lib/setupShutdownHooks.spec.ts
(1 hunks)libs/node/utils/src/lib/setupShutdownHooks.ts
(1 hunks)libs/node/utils/tsconfig.json
(1 hunks)libs/node/utils/tsconfig.lib.json
(1 hunks)libs/node/utils/tsconfig.spec.json
(1 hunks)tsconfig.base.json
(1 hunks)
✅ Files skipped from review due to trivial changes (7)
- libs/node/utils/.eslintrc.json
- libs/node/utils/jest.config.ts
- libs/node/utils/project.json
- libs/node/utils/src/index.ts
- libs/node/utils/tsconfig.json
- libs/node/utils/tsconfig.lib.json
- libs/node/utils/tsconfig.spec.json
🚧 Files skipped from review as they are similar to previous changes (1)
- libs/infra-next-server/src/lib/bootstrap.ts
🧰 Additional context used
📓 Path-based instructions (5)
libs/infra-express-server/src/lib/infra-express-server.ts (1)
Pattern libs/**/*
: "Confirm that the code adheres to the following:
- Reusability of components and hooks across different NextJS apps.
- TypeScript usage for defining props and exporting types.
- Effective tree-shaking and bundling practices."
libs/infra-nest-server/src/lib/bootstrap.ts (1)
Pattern libs/**/*
: "Confirm that the code adheres to the following:
- Reusability of components and hooks across different NextJS apps.
- TypeScript usage for defining props and exporting types.
- Effective tree-shaking and bundling practices."
libs/node/utils/README.md (1)
Pattern libs/**/*
: "Confirm that the code adheres to the following:
- Reusability of components and hooks across different NextJS apps.
- TypeScript usage for defining props and exporting types.
- Effective tree-shaking and bundling practices."
libs/node/utils/src/lib/setupShutdownHooks.spec.ts (1)
Pattern libs/**/*
: "Confirm that the code adheres to the following:
- Reusability of components and hooks across different NextJS apps.
- TypeScript usage for defining props and exporting types.
- Effective tree-shaking and bundling practices."
libs/node/utils/src/lib/setupShutdownHooks.ts (1)
Pattern libs/**/*
: "Confirm that the code adheres to the following:
- Reusability of components and hooks across different NextJS apps.
- TypeScript usage for defining props and exporting types.
- Effective tree-shaking and bundling practices."
🪛 LanguageTool
libs/node/utils/README.md
[style] ~10-~10: To form a complete sentence, be sure to include a subject.
Context: ... executed before the server shuts down. Can be used to perform and wait for other c...
(MISSING_IT_THERE)
🔇 Additional comments (9)
libs/node/utils/src/lib/setupShutdownHooks.ts (1)
1-7
: LGTM! Well-structured function signature with proper typing
The function signature is well-designed with TypeScript types and an optional callback for custom cleanup operations.
libs/node/utils/README.md (1)
14-15
: Verify NX runner detection implementation
The documentation mentions NX runner detection using an environment variable. Let's verify this implementation.
✅ Verification successful
Let me gather more context about the implementation to ensure a complete verification.
NX runner detection and disconnect event handling are correctly implemented
The implementation in setupShutdownHooks.ts
accurately matches the documentation:
- Checks for NX runner using
process.env.NX_INVOKED_BY_RUNNER === 'true'
- Adds 'disconnect' event to termination events when running under NX
- Implementation is well-tested with dedicated test cases verifying this behavior
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for the NX runner environment variable usage
rg -A 2 "NX_INVOKED_BY_RUNNER"
# Look for the disconnect event handler implementation
ast-grep --pattern 'process.on("disconnect"'
Length of output: 1216
Script:
#!/bin/bash
# Get the full implementation of setupShutdownHooks
cat libs/node/utils/src/lib/setupShutdownHooks.ts
# Get the full test implementation
cat libs/node/utils/src/lib/setupShutdownHooks.spec.ts
Length of output: 5125
libs/infra-express-server/src/lib/infra-express-server.ts (3)
45-50
: LGTM! Parameter naming follows best practices
The underscore prefix for unused parameters follows TypeScript conventions and improves code clarity.
88-88
: Verify graceful shutdown behavior
The addition of setupShutdownHooks
addresses the PR objective, but we should verify it properly handles in-flight requests during shutdown.
✅ Verification successful
Graceful shutdown implementation is properly handled
The setupShutdownHooks
implementation correctly handles in-flight requests by:
- Using
server.close()
which waits for existing connections to complete before shutting down - Preventing multiple shutdown attempts with the
isShuttingDown
flag - Supporting custom cleanup through the optional
onShutdown
callback - Properly handling termination signals (SIGHUP, SIGINT, SIGTERM)
- Logging shutdown progress and errors for observability
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check if setupShutdownHooks properly handles in-flight requests
# Look for timeout configurations and request handling during shutdown
ast-grep --pattern 'setupShutdownHooks($_) {
$$$
}'
Length of output: 55
Script:
#!/bin/bash
# Search for setupShutdownHooks function definition
rg -A 10 "setupShutdownHooks" --type ts
Length of output: 10770
Script:
#!/bin/bash
# Get the full implementation of setupShutdownHooks
cat libs/node/utils/src/lib/setupShutdownHooks.ts
Length of output: 1102
1-1
: Verify the implementation of setupShutdownHooks
Let's ensure the imported function properly handles graceful shutdowns.
✅ Verification successful
Implementation of setupShutdownHooks is properly integrated
The implementation is well-tested and correctly used in the Express server:
- Handles standard termination signals (SIGHUP, SIGINT, SIGTERM)
- Includes special handling for NX runner environments
- Provides graceful shutdown with proper server closure
- Supports optional cleanup through onShutdown callback
- Correctly integrated at the end of runServer function
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check the implementation of setupShutdownHooks
# Look for the implementation and documentation
fd -e md -e ts "node-utils" | xargs rg -l "setupShutdownHooks"
Length of output: 314
Script:
#!/bin/bash
# Check the implementation and documentation of setupShutdownHooks
echo "=== Implementation of setupShutdownHooks ==="
ast-grep --pattern 'export function setupShutdownHooks($_) { $$$ }'
echo -e "\n=== README Documentation ==="
cat libs/node/utils/README.md
echo -e "\n=== Test Cases ==="
cat libs/node/utils/src/lib/setupShutdownHooks.spec.ts
Length of output: 5686
Script:
#!/bin/bash
# Check the actual implementation file and usage in express server
echo "=== Implementation File ==="
cat libs/node/utils/src/lib/setupShutdownHooks.ts
echo -e "\n=== Usage in Express Server ==="
rg -A 5 "setupShutdownHooks" libs/infra-express-server/src/lib/infra-express-server.ts
Length of output: 1709
libs/infra-nest-server/src/lib/bootstrap.ts (2)
49-51
: LGTM! Graceful shutdown implementation follows best practices.
The addition of app.enableShutdownHooks()
properly implements signal handling for graceful shutdowns, which aligns with the PR objectives. This ensures that the application can properly clean up resources and complete ongoing requests before terminating.
49-51
: Verify shutdown cleanup in the close method.
The close
method handles cleanup of both the main app and metrics server. Let's verify it properly awaits all cleanup operations.
Also applies to: 156-164
✅ Verification successful
Shutdown cleanup is properly implemented
The close method correctly handles the cleanup by:
- Awaiting the NestJS application shutdown with
app.close()
- Properly closing the metrics server using a Promise-based approach
- Following the correct order: first app, then metrics server
- Using
enableShutdownHooks()
to handle system signals appropriately
The implementation ensures all resources are cleaned up gracefully during shutdown.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for potential shutdown-related issues in the codebase
# Look for other cleanup operations that might need to be included
rg -A 5 "beforeApplicationShutdown|onApplicationShutdown|close\(\)" --type typescript
# Check for any custom shutdown hooks that might need coordination
ast-grep --pattern 'app.enableShutdownHooks()'
Length of output: 810
Script:
#!/bin/bash
# Let's check the close method implementation and any shutdown hooks
ast-grep --pattern 'close() {
$$$
}'
# Also check for any beforeApplicationShutdown or onApplicationShutdown implementations
ast-grep --pattern 'beforeApplicationShutdown() {
$$$
}'
ast-grep --pattern 'onApplicationShutdown() {
$$$
}'
# Let's also check the specific file for the close method
cat libs/infra-nest-server/src/lib/bootstrap.ts
Length of output: 4705
libs/node/utils/src/lib/setupShutdownHooks.spec.ts (1)
1-11
: LGTM! Clean test setup with proper mocking.
The test setup follows best practices with clear imports and focused mocking of the logger functionality.
tsconfig.base.json (1)
956-956
: LGTM! Path mapping correctly configured for node-utils module.
The new path mapping for @island.is/node-utils
is properly configured and aligns with the PR's objective of implementing graceful shutdowns.
Let's verify the module's usage:
✅ Verification successful
Path mapping correctly configured and actively used in the codebase
The verification confirms that:
- The
@island.is/node-utils
module is properly imported in two server implementations:libs/infra-next-server/src/lib/bootstrap.ts
libs/infra-express-server/src/lib/infra-express-server.ts
- The implementation file exists at the correct location:
libs/node/utils/src/lib/setupShutdownHooks.ts
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the usage of @island.is/node-utils module
# Expected: Find imports of setupShutdownHooks from this module
# Search for imports of the module
rg "from ['|\"]@island\.is/node-utils['|\"]"
# Search for the implementation file
fd "setupShutdownHooks.ts" "libs/node/utils/src"
Length of output: 363
@eirikurn, hmm 🤔 Having forceful teardowns of connections this way is only marginally better than the current situation. Pods in |
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.
Nice work 👏
Stop forceful shutdowns in-cluster.
See https://expressjs.com/en/advanced/healthcheck-graceful-shutdown.html
Nest.js documentation has a section explicitly about this issue:
Summary by CodeRabbit