Allow cluster subclasses to delegate to another instance

Description

Final agreed upon changes:

In Cluster, all significant initialization was moved to the init method, so that subclasses that call the parent constructor but override init don't have to pay the initialization price.

DelegatingCluster was added as a base class for custom "delegating" implementations (see the code comments for internal implementation details).


Initial ticket description:
We have use cases where there are more than 40K clients connecting to cassandra ring. Due to various driver defects, we have occasionally seen the bad state accumulate on the client cassandra cluster. The only way to clear that bad state for now is to bounce the 40K clients. This is super disruptive. Instead they are asking for a resetCluster functionality that basically recreates the cluster object.

Each client can implement the logic to abandon existing cluster, create new cluster/sessions and start using them. However it is better to provide that functionality in a central library that all clients can use. One way for the library to do this is to provide a Cluster Wrapper object to clients. This cluster simply delegates to the real cluster object. When ever reset is requested, a new delegate is created and the Wrapper now delegates to this new Cluster.

In order to provide this wrapper cluster, Cluster needs to be turned in to interface.

Environment

None

Pull Requests

None

Activity

Show:
Sylvain Lebresne
January 19, 2015, 9:47 AM

However, Manager is package-private so I had to create a new protected method to delegate the call.

Couldn't the subclass just call super.close().get()?

Olivier Michallat
January 19, 2015, 10:00 AM

You're right, super.closeAsync().get() only calls manager.close so we can use it. I'm updating the code.

Olivier Michallat
January 28, 2015, 9:20 AM

There is one additional problem when wrapping a delegate Cluster: prepared statement ids are stored per Cluster instance, so if we transparently switch the delegate to a new one, it won't be able to handle the statements prepared by the old one.

Moving the ticket back to "in progress" to find a solution to this. We need to copy Cluster.Manager.preparedQueries from the old instance to the new one.

Sylvain Lebresne
January 28, 2015, 10:20 AM

There is one additional problem when wrapping a delegate Cluster: prepared statement ids are stored per Cluster instance, so if we transparently switch the delegate to a new one, it won't be able to handle the statements prepared by the old one.

Yes but that's a different problem (typically, making Cluster an interface wouldn't solve that). In practice, since to do the hot-swapping of cluster instance you'll have to use your own Session object anyway, it's not terribly complicated to record prepared statements in your own cache and re-prepare against the new Cluster before hot-swapping it. So I'm in favor of not considering thatas a problem.

NateM
April 1, 2015, 8:19 PM

I saw the reference to this issue on a recent commit, and I wanted to put out there the idea of moving to JDK 8 as the target for the 3.0 driver (fyi - JDK 7 is EOL as of now: http://www.oracle.com/technetwork/java/eol-135779.html).

This would provide for making Cluster an interface with default methods.

Either way folks will have to change code so may be as good a time as any to make the move.

Fixed

Assignee

Olivier Michallat

Reporter

Vishy Kasar

Labels

None

PM Priority

None

Affects versions

Fix versions

Pull Request

None

Doc Impact

None

Size

None

External issue ID

None

External issue ID

None

Components

Priority

Major
Configure