-
Notifications
You must be signed in to change notification settings - Fork 0
Fix SessionPool client leak on reconnection and query failures, and preserve server error messages #1
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 SessionPool client leak on reconnection and query failures, and preserve server error messages #1
Changes from all commits
bc96073
27cfabd
acd1f4e
fb8feb5
1b3408d
2721efd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -157,9 +157,12 @@ protected internal SessionPool(List<string> nodeUrls, string username, string pa | |
| public async Task<TResult> ExecuteClientOperationAsync<TResult>(AsyncOperation<TResult> operation, string errMsg, bool retryOnFailure = true, bool putClientBack = true) | ||
| { | ||
| Client client = _clients.Take(); | ||
| bool shouldReturnClient = true; | ||
| bool operationSucceeded = false; | ||
| try | ||
| { | ||
| var resp = await operation(client); | ||
| operationSucceeded = true; | ||
| return resp; | ||
| } | ||
| catch (TException ex) | ||
|
|
@@ -169,16 +172,25 @@ public async Task<TResult> ExecuteClientOperationAsync<TResult>(AsyncOperation<T | |
| try | ||
| { | ||
| client = await Reconnect(client); | ||
| return await operation(client); | ||
| var resp = await operation(client); | ||
| operationSucceeded = true; | ||
| return resp; | ||
| } | ||
| catch (TException retryEx) | ||
| catch (Exception retryEx) | ||
| { | ||
| throw new TException(errMsg, retryEx); | ||
| // Reconnection failed or retry operation failed | ||
| // Client is closed by Reconnect, should not be returned to pool | ||
| shouldReturnClient = false; | ||
| // Preserve original error message from server | ||
| string detailedMsg = $"{errMsg}. {retryEx.Message}"; | ||
|
Comment on lines
+184
to
+185
|
||
| throw new TException(detailedMsg, retryEx); | ||
| } | ||
|
Comment on lines
+179
to
187
|
||
| } | ||
| else | ||
| { | ||
| throw new TException(errMsg, ex); | ||
| // Preserve original error message from server | ||
| string detailedMsg = $"{errMsg}. {ex.Message}"; | ||
|
Comment on lines
+191
to
+192
|
||
| throw new TException(detailedMsg, ex); | ||
| } | ||
| } | ||
| catch (Exception ex) | ||
|
|
@@ -188,21 +200,36 @@ public async Task<TResult> ExecuteClientOperationAsync<TResult>(AsyncOperation<T | |
| try | ||
| { | ||
| client = await Reconnect(client); | ||
| return await operation(client); | ||
| var resp = await operation(client); | ||
| operationSucceeded = true; | ||
| return resp; | ||
| } | ||
| catch (TException retryEx) | ||
| catch (Exception retryEx) | ||
| { | ||
| throw new TException(errMsg, retryEx); | ||
| // Reconnection failed or retry operation failed | ||
| // Client is closed by Reconnect, should not be returned to pool | ||
|
Comment on lines
+209
to
+210
|
||
| shouldReturnClient = false; | ||
| // Preserve original error message from server | ||
| string detailedMsg = $"{errMsg}. {retryEx.Message}"; | ||
|
Comment on lines
+212
to
+213
|
||
| throw new TException(detailedMsg, retryEx); | ||
| } | ||
|
Comment on lines
+207
to
215
|
||
| } | ||
| else | ||
| { | ||
| throw new TException(errMsg, ex); | ||
| // Preserve original error message from server | ||
| string detailedMsg = $"{errMsg}. {ex.Message}"; | ||
|
Comment on lines
+219
to
+220
|
||
| throw new TException(detailedMsg, ex); | ||
| } | ||
| } | ||
| finally | ||
| { | ||
| if (putClientBack) | ||
| // Return client to pool if: | ||
| // 1. putClientBack is true (normal operations - client should always be returned), OR | ||
| // 2. putClientBack is false (query operations) BUT operation failed, meaning SessionDataSet | ||
| // wasn't created and won't manage the client | ||
| // Do NOT return if reconnection failed (shouldReturnClient is false) because client was closed by Reconnect | ||
| bool shouldReturnForQueryFailure = !putClientBack && !operationSucceeded; | ||
| if (shouldReturnClient && (putClientBack || shouldReturnForQueryFailure)) | ||
| { | ||
| _clients.Add(client); | ||
| } | ||
|
|
||
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 comment is misleading. The second line states "Client is closed by Reconnect, should not be returned to pool" but this is only true when Reconnect itself fails. When Reconnect succeeds but the retry operation fails, the client is NOT closed and SHOULD be returned to the pool. This misleading comment is related to the critical bug in this code block.