-
-
Notifications
You must be signed in to change notification settings - Fork 54
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 concurrency issue in DialAndSendWithContext #386
Merged
wneessen
merged 11 commits into
main
from
bug/385_concurrency-issue-in-dialandsendwithcontext
Nov 22, 2024
Merged
Fix concurrency issue in DialAndSendWithContext #386
wneessen
merged 11 commits into
main
from
bug/385_concurrency-issue-in-dialandsendwithcontext
Nov 22, 2024
+392
−148
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Updated tests to correctly assert the absence of an SMTP client on failure. Added concurrent sending tests for DialAndSendWithContext to improve test coverage and reliability. Also, refined the `AutoDiscover` and other client methods to ensure proper parameter use.
Mutex locks are added to ensure thread safety when setting DSN mail return and recipient notify options. This prevents data races in concurrent environments, improving the client's robustness.
Refactor `DialWithContext` to delegate client creation to `SMTPClientFromDialWithContext`. Add new methods `SendWithSMTPClient`, `CloseWithSMTPClient`, and `ResetWithSMTPClient` to handle specific actions on `smtp.Client`. Simplify `auth`, `sendSingleMsg`, and `tls` methods by passing client as parameters.
Separated debug logging and logger setting methods to include SMTP client parameter for better encapsulation. Removed commented-out code for cleaner and more manageable codebase.
Added a mutex lock and unlock around the Send function to prevent concurrent access issues and ensure thread safety. This change helps avoid race conditions when multiple goroutines attempt to send messages simultaneously.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #386 +/- ##
==========================================
+ Coverage 96.64% 96.86% +0.22%
==========================================
Files 28 28
Lines 3100 3128 +28
==========================================
+ Hits 2996 3030 +34
+ Misses 72 68 -4
+ Partials 32 30 -2 ☔ View full report in Codecov by Sentry. 🚨 Try these New Features:
|
The new Send function in client.go adds thread safety by using a mutex. This change also removes duplicate Send functions from client_119.go and client_120.go, consolidating the logic in one place for easier maintenance.
Updated several Client methods to accept a smtp.Client pointer, allowing for more flexible and explicit SMTP client management. Added detailed parameter descriptions and extended error handling documentation.
Renamed `SMTPClientFromDialWithContext` to `DialToSMTPClientWithContext` for clarity and consistency. Updated method parameters and documentation to standardize context usage across the codebase.
Introduce a new test, `TestClient_DialToSMTPClientWithContext`, to verify client behavior when establishing and closing an SMTP connection with context handling. Also added a sub-test to simulate and confirm failure scenarios during SMTP connection establishment.
This change removes an unnecessary blank line at the end of the TestClient_sendSingleMsg function in the client_test.go file. Keeping the code clean and properly formatted improves readability and maintainability.
The removed check for a nil SMTP client was redundant because the previous error handling already covers this case. Streamlining this part of the code improves readability and reduces unnecessary checks.
wneessen
deleted the
bug/385_concurrency-issue-in-dialandsendwithcontext
branch
November 22, 2024 15:36
Awesome thanks! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR fixes concurrency issues when a user would use
DialAndSend
orDialAndSendWithContext
in concurrent goroutines instead of using a singleClient
and then just usingSend
within the goroutines. With this PR the overall concurrency-safety is made more reliable. Goroutines are easy, but concurrency is hard, and since we added concurrency just with the latest release, some issues were to be expected.In this PR the whole dial and send mechanic was refactored to use a dedicated, local SMTP client per
DialAndSendWithContext
call (as suggested by @firefart in #385). This fixes the concurrency issues that would arrise when theClient
accesses thesmtp.Client
stored in theClient
struct. To accomplish this, several public methods have been added that accept asmtp.Client
pointer and use this instead of theClient.smtpClient
shared on theClient
struct. Additionally some private methods have been refactored to always accept asmtp.Client
as well.To avoid breaking any current code, the old methods have been refactored in a way that they make use of the new
smtp.Client
-accepting methods, but they will still hand over theClient.smtpClient
to these functions, but with an additional mutex for sending. This way we should provide full compatibility with any code that was written before this PR.This addresses #385.