Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@olavloite
Copy link

A ConnectionImpl instance, which is the internal Spanner connection API, can only be created from a ConnectionOptions instance. All connections that are created by ConnectionOptions are registered with a SpannerPool that keeps track of the connections that have been opened and which Spanner instances from the client library are associated with which connection. The Spanner instances are kept in a pool and reused for connections because these are heavyweight objects that are expensive to create and maintain, and are intended to live as long as the application interacts with Cloud Spanner.

This change also adds a client lib token property to SpannerOptions in the client library. This token will be used to track the usage of the JDBC driver. The actual usage of this token will be added in a separate PR.

This PR contains a couple of stub classes that will be replaced by the actual classes in subsequent PRs. This is done to keep the PR as small as possible. The stubs are:

  • ConnectionImpl
  • CredentialsService
  • JdbcDriver
  • UnitOfWork

@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Jul 26, 2019
@olavloite olavloite requested a review from kolea2 July 26, 2019 05:36
@olavloite olavloite force-pushed the spanner-jdbc-15-connection-options branch from d0f3f18 to 4829312 Compare July 26, 2019 14:44

@Override
public boolean isClosed() {
// TODO Auto-generated method stub
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please delete these

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@olavloite olavloite requested a review from kolea2 July 26, 2019 15:48
@olavloite olavloite force-pushed the spanner-jdbc-15-connection-options branch from 51a3ceb to a6d9f88 Compare July 26, 2019 17:50
Spanner createSpanner(SpannerPoolKey key) {
SpannerOptions.Builder builder = SpannerOptions.newBuilder();
builder
.setClientLibToken(MoreObjects.firstNonNull(key.userAgent, JdbcDriver.getClientLibToken()))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's something that we would need to discuss with the Spanner team in that case. The header used by spring-cloud-gcp sets a 'User-Agent' header, the client lib token of the JDBC driver sets the ApiClientHeader ('x-goog-api-client'). My initial solution was also what spring-cloud-gcp did, but it didn't show up in the monitoring that the Spanner team had. The ApiClientHeader did, which is why this solution was chosen, and the monitoring is now built around that.

That being said, I looked a little bit more into the spring-cloud-gcp solution and compared that with the original solution for the JDBC driver, and I noticed one important difference: spring-cloud-gcp sets a 'User-Agent' header, the JDBC driver used a 'user-agent' header, so that could be the reason it didn't show up.

if (!initialized) {
initialize();
}
if (spanners.containsKey(key)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

personal preference, but I'd make this a get and null check

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, in this case that is more appropriate, as the return value of the getSpanner(...) method should never be null (even if the map somehow contained a null value for the key).

registeredConnectionsForSpanner = new ArrayList<>();
connections.put(key, registeredConnectionsForSpanner);
}
registeredConnectionsForSpanner.add(connection);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it possible to have duplicate connections?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% sure what you mean with 'duplicate' connections in this case, but:

  • Several Connection instances can share the same Spanner instance, and a Spanner instance should only be closed once all the related Connection instances have been closed. The reason behind this is that Spanner instances are heavy-weight objects that should live throughout (most of) the lifetime of an application. A Spanner instance also maintains a session pool. Connection instances are relatively light-weight objects that an application may create and close many times during its lifetime. In Cloud Spanner terms, a Connection is comparable to a Session. But as the JDBC driver is built on top of the client library, and the client library does not expose sessions and session management, this solution is the closest we can get having Connection == Session.
  • Connection instances are not thread safe and should not be used by several processes at the same time. An application will normally either maintain its own connection pool and reuse connections through this pool, or create and close connections when needed for a process. ConnectionImpl does not override the default equals(Object) method, so different connection instances will never be considered equal.

* should not have been used for a {@link Connection} before it is closed by this method.
*/
@VisibleForTesting
void closeUnusedSpanners(long closeSpannerAfterMillisecondsUnused) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where does this parameter get its value?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default value that is used when nothing else is configured is found here:

This value is currently only configurable for testing. A client application cannot change this value and will always use the default.

get and check for null is more appropriate in this case, as we would
never want to return null from this method
initialize();
}
if (spanners.containsKey(key)) {
if (spanners.get(key) == null) {
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 this is backwards now?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add some more testing around this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, that's indeed backward. It's already covered by the test case here, but because this PR has build errors, I didn't pick up on that one. I added the same error to the private repo and ran the test cases, and there were multiple test failures.

@olavloite olavloite merged commit e50f15a into googleapis:spanner-jdbc Jul 30, 2019
olavloite added a commit to olavloite/google-cloud-java that referenced this pull request Aug 5, 2019
…#5890)

* add ConnectionOptions

* add SpannerPool

* removed auto-generated methods

* changed to get-and-check-for-null

get and check for null is more appropriate in this case, as we would
never want to return null from this method

* added documentation

* fixed wrong null check
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla: yes This human has signed the Contributor License Agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants