-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
🔥 feat: Improve and Optimize ShutdownWithContext Func #3162
base: main
Are you sure you want to change the base?
🔥 feat: Improve and Optimize ShutdownWithContext Func #3162
Conversation
- Reorder mutex lock acquisition to the start of the function - Early return if server is not running - Use defer for executing shutdown hooks - Simplify nil check for hooks - Remove TODO comment This commit improves the readability, robustness, and execution order of the shutdown process. It ensures consistent state throughout the shutdown and guarantees hook execution even in error cases.
- Add shutdown hook verification - Implement better synchronization with channels - Improve error handling and assertions - Adjust timeouts for more consistent results - Add server state check after shutdown attempt - Include comments explaining expected behavior This commit improves the comprehensiveness and reliability of the ShutdownWithContext test, ensuring proper verification of shutdown hooks, timeout behavior, and server state during long-running requests.
Thanks for opening this pull request! 🎉 Please check out our contributing guidelines. If you need help or want to chat with us, join us on Discord https://gofiber.io/discord |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #3162 +/- ##
==========================================
+ Coverage 82.77% 82.87% +0.09%
==========================================
Files 114 114
Lines 11197 11197
==========================================
+ Hits 9268 9279 +11
+ Misses 1528 1520 -8
+ Partials 401 398 -3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
app_test.go
Outdated
}() | ||
|
||
<-clientDone | ||
time.Sleep(100 * time.Millisecond) |
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.
why do we need a sleep here? i think it's arbitrary since we already wait for clientDone channel
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.
why do we need a sleep here? i think it's arbitrary since we already wait for clientDone channel
This sleep is to ensure that our server has started processing the request. Although we have confirmed that the client has sent the request through <-clientDone, this means that the request has been sent to the server's listening port, and there is no guarantee that the server's processing coroutine has been sent. Start processing the request, so I think sleep 100 * Millisecond is required here as well.
WalkthroughThe changes enhance the Fiber web framework by introducing a new method Changes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
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
CodeRabbit Configuration File (
|
…e/improve-shutdown-with-context
…ub.com:JIeJaitt/fiber into jiejaitt-feature/improve-shutdown-with-context
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 (1)
docs/api/fiber.md (1)
208-208
: Approve with minor suggestions for improvementThe added description for
ShutdownWithContext
is informative and aligns well with the PR objectives. It provides important details about the method's behavior, especially regarding the execution of shutdown hooks. To enhance clarity and readability, consider the following suggestions:
- Add a comma after "including" for better sentence structure.
- Split the long sentence into two for improved readability.
Here's a suggested revision:
- ShutdownWithContext shuts down the server including by force if the context's deadline is exceeded.Shutdown hooks will still be executed, even if an error occurs during the shutdown process, as they are deferred to ensure cleanup happens regardless of errors. + ShutdownWithContext shuts down the server, including by force if the context's deadline is exceeded. Shutdown hooks will still be executed, even if an error occurs during the shutdown process, as they are deferred to ensure cleanup happens regardless of errors.🧰 Tools
🪛 LanguageTool
[uncategorized] ~208-~208: Possible missing comma found.
Context: ...es. ShutdownWithContext shuts down the server including by force if the context's dea...(AI_HYDRA_LEO_MISSING_COMMA)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
- app.go (1 hunks)
- app_test.go (1 hunks)
- docs/api/fiber.md (1 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/api/fiber.md
[uncategorized] ~208-~208: Possible missing comma found.
Context: ...es. ShutdownWithContext shuts down the server including by force if the context's dea...(AI_HYDRA_LEO_MISSING_COMMA)
🔇 Additional comments (1)
app.go (1)
846-855
: Improved shutdown process with deferred hook executionThe changes to the
ShutdownWithContext
method enhance the shutdown process in several ways:
- Thread-safety is ensured by acquiring a mutex lock at the beginning of the method.
- A nil check for the server prevents potential panics if the server hasn't been initialized.
- The deferral of
executeOnShutdownHooks
guarantees that shutdown hooks are executed even if an error occurs during the shutdown process.These improvements contribute to a more robust and reliable shutdown mechanism.
app_test.go
Outdated
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) | ||
defer cancel() | ||
shutdownErr <- app.ShutdownWithContext(ctx) | ||
}() |
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.
Ensure Proper Context Cancellation
The context created with context.WithTimeout
should have its cancellation function deferred immediately to prevent potential resource leaks, even if an error occurs before the defer statement is reached.
Suggested Improvement
Move the defer cancel()
directly after context creation.
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
+ defer cancel()
shutdownErr <- app.ShutdownWithContext(ctx)
- defer cancel()
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) | |
defer cancel() | |
shutdownErr <- app.ShutdownWithContext(ctx) | |
}() | |
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) | |
defer cancel() | |
shutdownErr <- app.ShutdownWithContext(ctx) | |
}() |
app_test.go
Outdated
case err := <-serverErr: | ||
assert.NoError(t, err, "Server should have shut down without error") | ||
default: | ||
// Server is still running, which is expected as the long-running request prevented full shutdown | ||
} |
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.
🛠️ Refactor suggestion
Avoid Skipping Server Error Handling
Using a default
case in the select
statement may cause the test to proceed without waiting for the server to shut down, potentially leading to flaky tests. It's important to handle the server error explicitly.
Suggested Fix: Remove the default
Case
This ensures the test waits for serverErr
to receive an error or completes the shutdown process.
select {
case err := <-serverErr:
assert.NoError(t, err, "Server should have shut down without error")
- default:
- // Server is still running, which is expected as the long-running request prevented full shutdown
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
case err := <-serverErr: | |
assert.NoError(t, err, "Server should have shut down without error") | |
default: | |
// Server is still running, which is expected as the long-running request prevented full shutdown | |
} | |
case err := <-serverErr: | |
assert.NoError(t, err, "Server should have shut down without error") |
app_test.go
Outdated
shutdownHookCalled := false | ||
app.Hooks().OnShutdown(func() error { | ||
shutdownHookCalled = true | ||
return nil | ||
}) |
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.
Possible Data Race on shutdownHookCalled
Variable
The shutdownHookCalled
boolean is accessed by multiple goroutines without proper synchronization, which could lead to a data race. In Go, variables shared between goroutines should be protected using synchronization mechanisms like channels, mutexes, or atomic operations.
Suggested Fix: Use an Atomic Variable
Replace shutdownHookCalled
with an int32
and use atomic.StoreInt32
and atomic.LoadInt32
for thread-safe operations.
+import "sync/atomic"
- shutdownHookCalled := false
+ var shutdownHookCalled int32
app.Hooks().OnShutdown(func() error {
- shutdownHookCalled = true
+ atomic.StoreInt32(&shutdownHookCalled, 1)
return nil
})
// ...
- assert.True(t, shutdownHookCalled, "Shutdown hook was not called")
+ assert.Equal(t, int32(1), atomic.LoadInt32(&shutdownHookCalled), "Shutdown hook was not called")
Committable suggestion was skipped due to low confidence.
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
🧹 Outside diff range and nitpick comments (1)
docs/api/fiber.md (1)
208-208
: Enhance documentation clarity and completenessThe current documentation could be improved in both grammar and completeness. Consider the following suggestions:
- Add a comma for better readability
- Improve the phrasing of the force shutdown description
- Include details about the mutex lock optimization
Apply this change to improve the documentation:
-ShutdownWithContext shuts down the server including by force if the context's deadline is exceeded. Shutdown hooks will still be executed, even if an error occurs during the shutdown process, as they are deferred to ensure cleanup happens regardless of errors. +ShutdownWithContext shuts down the server, forcefully terminating if the context's deadline is exceeded. Shutdown hooks will still be executed, even if an error occurs during the shutdown process, as they are deferred to ensure cleanup happens regardless of errors. The method is optimized to acquire locks early, allowing for immediate return if the server is not running.🧰 Tools
🪛 LanguageTool
[uncategorized] ~208-~208: Possible missing comma found.
Context: ...es. ShutdownWithContext shuts down the server including by force if the context's dea...(AI_HYDRA_LEO_MISSING_COMMA)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
- docs/api/fiber.md (1 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/api/fiber.md
[uncategorized] ~208-~208: Possible missing comma found.
Context: ...es. ShutdownWithContext shuts down the server including by force if the context's dea...(AI_HYDRA_LEO_MISSING_COMMA)
…e/improve-shutdown-with-context
- Reorder mutex lock acquisition to the start of the function - Early return if server is not running - Use defer for executing shutdown hooks - Simplify nil check for hooks - Remove TODO comment This commit improves the readability, robustness, and execution order of the shutdown process. It ensures consistent state throughout the shutdown and guarantees hook execution even in error cases.
- Add shutdown hook verification - Implement better synchronization with channels - Improve error handling and assertions - Adjust timeouts for more consistent results - Add server state check after shutdown attempt - Include comments explaining expected behavior This commit improves the comprehensiveness and reliability of the ShutdownWithContext test, ensuring proper verification of shutdown hooks, timeout behavior, and server state during long-running requests.
…ub.com:JIeJaitt/fiber into jiejaitt-feature/improve-shutdown-with-context
…/improve-shutdown-with-context
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: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
- app.go (1 hunks)
- app_test.go (2 hunks)
- docs/api/fiber.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- docs/api/fiber.md
🔇 Additional comments (7)
app.go (2)
883-887
: LGTM! Improved concurrency safety and error handling.The changes correctly acquire the mutex lock at the start and add an early return if the server is not running. This prevents unnecessary processing and ensures thread safety.
888-892
: LGTM! Robust shutdown hook execution.The changes ensure that shutdown hooks are executed even if errors occur during shutdown by:
- Using
defer
to guarantee hook execution- Adding a nil check for hooks
- Maintaining clean code structure with proper spacing
app_test.go (5)
23-23
: Importing 'sync/atomic' for safe concurrencyThe import of
sync/atomic
is appropriate to enable atomic operations on shared variables, ensuring thread safety in concurrent environments.
864-868
: Proper use of atomic variables to avoid data racesThe variable
shutdownHookCalled
is correctly declared asatomic.Int32
, and atomic methodsStore
andLoad
are used to prevent data races, addressing previous concurrency concerns.
899-900
: Proper placement ofdefer cancel()
after context creationPlacing
defer cancel()
immediately after creating the context ensures that resources are released promptly, preventing potential leaks even if an error occurs.
905-909
: Improved test reliability by removing thedefault
case inselect
By removing the
default
case, the test now correctly waits for either the shutdown to complete or the timeout to occur, ensuring accurate and reliable test behavior.
912-912
: Correctly verifying shutdown hook executionThe assertion confirms that the
shutdownHookCalled
variable is set, verifying that the shutdown hook was indeed called during the shutdown process.
…/improve-shutdown-with-context
false positive for the benchmark because of the same naming @gaby can you check your last comments again to see if it is ready to merge |
@JIeJaitt can you make another comment in the whats new markdown? |
No problem, I will add it in what new later |
…/improve-shutdown-with-context
@@ -205,7 +205,7 @@ Shutdown gracefully shuts down the server without interrupting any active connec | |||
|
|||
ShutdownWithTimeout will forcefully close any active connections after the timeout expires. | |||
|
|||
ShutdownWithContext shuts down the server including by force if the context's deadline is exceeded. | |||
ShutdownWithContext shuts down the server including by force if the context's deadline is exceeded. Shutdown hooks will still be executed, even if an error occurs during the shutdown process, as they are deferred to ensure cleanup happens regardless of errors. |
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.
Not sure about this behavior. I think we should only execute them during successful shutdown. Maybe we can OnShutdownError hook. What do you think @gaby @ReneWerner87
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'm not sure either. Also not sure about the defer of the hook
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 would prefer to add Post Pre hook
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 add Post Pre hook is a good idea, but how do I tell which hooks are pre closed and which are post closed? @efectn
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.
You can add new hook called PostShutdown, PreShutdown and replace the old one with them
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.
sound good, @JIeJaitt can you do the suggested change
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.
This means making a change below the type Hooks struct
to add these two fields that mean PreShutdownHandler
and PostShutdownHandler
respectively , if I understand it correctly I'll try to implement it @ReneWerner87 @efectn @gaby
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.
This means making a change below the
type Hooks struct
to add these two fields that meanPreShutdownHandler
andPostShutdownHandler
respectively , if I understand it correctly I'll try to implement it @ReneWerner87 @efectn @gaby
Yes it is. You can also add err parameter to PostShutdown hook, so that we can also get rid of OnShutdownError, OnShutdownSuccess properties of ListenerConfig.
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
🧹 Outside diff range and nitpick comments (1)
app_test.go (1)
913-918
: Consider removing commented codeThe commented
default
case on line 917 should be removed as it's no longer needed.- // default: - // Server is still running, which is expected as the long-running request prevented full shutdown
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
app.go
(1 hunks)app_test.go
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- app.go
🧰 Additional context used
📓 Learnings (1)
app_test.go (1)
Learnt from: efectn
PR: gofiber/fiber#3162
File: app_test.go:893-895
Timestamp: 2024-11-29T12:37:27.581Z
Learning: In the `Test_App_ShutdownWithContext` function in `app_test.go`, the `clientDone` channel is used to synchronize the client's request completion before proceeding, eliminating the need for additional `time.Sleep` calls.
🔇 Additional comments (6)
app_test.go (6)
24-24
: LGTM: Import atomic package for thread-safe operations
The addition of the sync/atomic
import is appropriate for implementing thread-safe operations in the test.
865-869
: LGTM: Thread-safe shutdown hook tracking
The use of atomic.Int32
for tracking the shutdown hook call is a thread-safe approach, ensuring accurate state tracking in concurrent scenarios.
878-881
: LGTM: Proper error handling with buffered channel
Using a buffered channel for server errors prevents potential goroutine leaks and ensures errors are properly captured.
885-891
: LGTM: Proper client request setup with synchronization
The client request is properly set up with error handling and synchronization using a channel to signal completion.
894-896
: Consider removing the sleep after clientDone
The sleep after the clientDone
channel might be unnecessary since we already have synchronization through the channel.
Based on the past review comments and learnings, the clientDone
channel is sufficient for synchronization, making the sleep redundant.
898-911
: LGTM: Robust shutdown handling with timeout
The shutdown handling is well-implemented with:
- Proper context timeout
- Deferred context cancellation
- Clear error assertions for timeout scenarios
Description
feat: Optimize ShutdownWithContext method in app.go
This commit improves the readability, robustness, and execution order
of the shutdown process. It ensures consistent state throughout the
shutdown and guarantees hook execution even in error cases.
feat: Enhance ShutdownWithContext test for improved reliability
This commit improves the comprehensiveness and reliability of the
ShutdownWithContext
test, ensuring proper verification of shutdown hooks, timeout behavior, and server state during long-running requests.Changes introduced
Type of change
Please delete options that are not relevant.
Checklist
Before you submit your pull request, please make sure you meet these requirements:
/docs/
directory for Fiber's documentation.Commit formatting
Sorry, I just initiated the PR and saw this regulation. I will definitely add it in the next commit