-
Notifications
You must be signed in to change notification settings - Fork 69
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
Do not purge inUse connections #260
Conversation
Simplified test logic to not worry about connection validation if not needed Renamed `AvailableConnections` to `IdleConnections`
Added tests for verify deactiviation
throw error; | ||
} | ||
|
||
public async Task OnErrorAsync(Exception error) |
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.
@ali-ince This is the method that need to be plugged in DelegatedConnection
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 think adding DelegatedConnection.OnErrorAsync
makes sense. The only actual place where async job is done seems to be ClusterConnection
though. This also brings another option of introducing IAsyncErrorHandler
interface with OnErrorAsync
and selectively calling it from within DelegatedConnection.TaskWithErrorHandling
?
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.
Looks good to me, with a couple of small comments.
} | ||
|
||
// Just dequeue any one connection and close it will ensure that all connections in the pool will finally be closed | ||
if (IsClosed && _availableConnections.TryTake(out connection)) | ||
if (IsZombieOrClosed && _idleConnections.TryTake(out connection)) |
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.
Shall we consider adding IsZombieOrClosed ||
check also to L438
} | ||
|
||
// Just dequeue any one connection and close it will ensure that all connections in the pool will finally be closed | ||
if (IsClosed && _availableConnections.TryTake(out connection)) | ||
if (IsZombieOrClosed && _idleConnections.TryTake(out connection)) |
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.
Shall we consider adding IsZombieOrClosed ||
check also to L478?
@@ -116,26 +115,62 @@ public void Add(IEnumerable<Uri> servers) | |||
{ | |||
foreach (var uri in servers) | |||
{ | |||
Add(uri); | |||
if (_pools.ContainsKey(uri)) |
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.
It may be better and safer to make use of _pools.AddOrUpdate(uri, CreateNewConnectionPool, ActivateConnectionPool)
where ActivateConnectionPool
is a new method that just activates and returns the activated pool instance.
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.
And also we can change GetOrAdd
to TryAdd
at L104.
} | ||
catch (ServiceUnavailableException e) | ||
{ | ||
OnConnectionError(uri, e); | ||
await OnConnectionErrorAsync(uri, e).ConfigureAwait(false); | ||
} | ||
return null; |
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.
We probably did not notice the problem here before, but we should be returning Task.FromResult(null)
instead of null
.
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.
Seems we do not need to cast as we have async
keywords in the method declaration. And it will cast it to a Task automatically.
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.
Of course!
throw error; | ||
} | ||
|
||
public async Task OnErrorAsync(Exception error) |
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 think adding DelegatedConnection.OnErrorAsync
makes sense. The only actual place where async job is done seems to be ClusterConnection
though. This also brings another option of introducing IAsyncErrorHandler
interface with OnErrorAsync
and selectively calling it from within DelegatedConnection.TaskWithErrorHandling
?
I really do not know whether we should do or it would worth it but @lutovich introduced a fallback mechanism for Java Driver at LoadBalancer. What do you think? |
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.
@zhenlineo changes look good to me. Made couple small comments. Is it possible to add cluster IT for this new behaviour?
|
||
var exception = Record.Exception(()=>pool.Acquire()); | ||
|
||
exception.Should().BeOfType<ObjectDisposedException>(); |
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.
Maybe worth throwing some other exception when acquiring from zombie pool?
I thought ObjectDisposedException
should only be thrown after Dispose()
invocation.
private int _closedMarker = 0; | ||
private int _poolStatus = Open; | ||
private bool IsClosed => _poolStatus == Closed; | ||
private bool IsZombieOrClosed => _poolStatus != Open; |
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.
Field _poolStatus
is modified using Interlocked
but is read using regular field accesses, is it ok?
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.
Good point!
public IConnection Acquire(Uri uri) | ||
{ | ||
IConnectionPool pool; | ||
if (!_pools.TryGetValue(uri, out pool)) | ||
if (!_pools.TryGetValue(uri, out var pool)) |
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.
Wow!
public async Task UpdateAsync(IEnumerable<Uri> added, IEnumerable<Uri> removed) | ||
{ | ||
await AddAsync(added).ConfigureAwait(false); | ||
// TODO chain this part and use task.waitAll |
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.
Is this TODO still relevant?
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 is the second TODO. Will do in another PR.
{ | ||
public const int Open = 0; | ||
public const int Closed = 1; | ||
public const int Zombie = 2; |
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.
Maybe rename "open" to "active" and "zombie" to "inactive"?
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.
How about alive
, zombie
and totallyDead
? :P I will renaming as you suggested.
This PR consists of two parts:
TODOs (Not in this PR but comes later):
DelegatedConnection.OnError
should also provides a Async impl so that the connections could be closed synchronically. This will be left to some future work.