Skip to content
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

Merged
merged 9 commits into from
Nov 23, 2017
Merged

Conversation

zhenlineo
Copy link
Contributor

@zhenlineo zhenlineo commented Nov 21, 2017

This PR consists of two parts:

  1. When updating routing table, the pool of the servers that are removed from routing table should not be closed but be deactivated.
  2. When a connection error happens towards a server, the pool of the server should not be purged but deactivated.

TODOs (Not in this PR but comes later):

  • While working on 2) we found that the DelegatedConnection.OnError should also provides a Async impl so that the connections could be closed synchronically. This will be left to some future work.
  • Chain async tasks if possible

throw error;
}

public async Task OnErrorAsync(Exception error)
Copy link
Contributor Author

@zhenlineo zhenlineo Nov 21, 2017

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

Copy link
Contributor

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?

Copy link
Contributor

@ali-ince ali-ince left a 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))
Copy link
Contributor

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))
Copy link
Contributor

@ali-ince ali-ince Nov 21, 2017

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))
Copy link
Contributor

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.

Copy link
Contributor

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;
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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)
Copy link
Contributor

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?

@ali-ince
Copy link
Contributor

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?

Copy link
Contributor

@lutovich lutovich left a 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>();
Copy link
Contributor

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;
Copy link
Contributor

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?

Copy link
Contributor Author

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))
Copy link
Contributor

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
Copy link
Contributor

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?

Copy link
Contributor Author

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;
Copy link
Contributor

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"?

Copy link
Contributor Author

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.

@zhenlineo zhenlineo merged commit f0fbf34 into neo4j:1.5 Nov 23, 2017
@zhenlineo zhenlineo deleted the 1.5-purge-improve branch November 23, 2017 09:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants