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

feat: Introduce java.time to Gax-Java #1872

Merged
merged 158 commits into from
Jun 27, 2024
Merged

feat: Introduce java.time to Gax-Java #1872

merged 158 commits into from
Jun 27, 2024

Conversation

diegomarquezp
Copy link
Contributor

@diegomarquezp diegomarquezp commented Jul 20, 2023

This introduces the use of java.time in replacement of org.threeten backport classes.

Message to library users (release note)

We have made the following backwards-compatible changes in this library:

  • We have changed the method return type and argument type in internal classes from org.threeten.bp to java.time. This has no effect in the API surface.
  • We have added java.time versions for each of the abstract methods involving org.threeten.bp. The affected classes are BatchingSettings, RetrySettings, TimedAttemptSettings and ClientContext, all of which are AutoValue classes, not meant to be extended by our users.
  • All getters and setters using org.threeten.bp will be marked final because we will force their behavior to be the same one as the java.time counterpart, which has the actual implementation. The affected classes are BatchingSettings, RetrySettings, TimedAttemptSettings and ClientContext, all of which are AutoValue classes, not meant to be extended by our users.
  • In three interfaces, we have added java.time versions for each of the methods involving org.threeten.bp. The affected interfaces are WatchdogProvider (public interface), ApiTracer (internal) and ApiCallContext (internal). The new method in WatchdogProvider has a default behavior, which is to call the threeten counterpart, in order to make this a backwards-compatible change.

Implementation

It preserves method signatures using threeten. The cases are:

@AutoValue clases and classes with public interface involving time objects

Autovalues will have an internal threeten variable with a convenience java.time wrapper method. For example:

/** Backport of {@link #getTotalTimeoutDuration()} */
@ObsoleteApi("Use getTotalTimeoutDuration() instead")
public abstract org.threeten.bp.Duration getTotalTimeout();
/**
* TotalTimeout has ultimate control over how long the logic should keep trying the remote call
* until it gives up completely. The higher the total timeout, the more retries can be attempted.
* The default value is {@code Duration.ZERO}.
*/
public final java.time.Duration getTotalTimeoutDuration() {
return toJavaTimeDuration(getTotalTimeout());
}

and

/** Backport of {@link #setTotalTimeoutDuration(java.time.Duration)} */
@ObsoleteApi("Use setTotalTimeoutDuration(java.time.Duration) instead")
public abstract Builder setTotalTimeout(org.threeten.bp.Duration totalTimeout);
/**
* TotalTimeout has ultimate control over how long the logic should keep trying the remote call
* until it gives up completely. The higher the total timeout, the more retries and polls can be
* attempted. If this value is {@code Duration.ZERO}, then the logic will instead use the number
* of attempts to determine retries. In the event that both maxAttempts and totalTimeout values
* are both 0, the logic will not retry. If this value is non-{@code Duration.ZERO}, and the
* retry duration has reaches the timeout value, the logic will give up retrying even the number
* of attempts is lower than the maxAttempts value.
*
* <p>If there are no configurations, Retries have the default timeout value of {@code
* Duration.ZERO} and LROs have a default total timeout value of {@code
* Duration.ofMillis(300000)} (5 minutes).
*/
public final Builder setTotalTimeoutDuration(java.time.Duration totalTimeout) {
return setTotalTimeout(toThreetenDuration(totalTimeout));
}

Internal variables

Duration or Instant private variables are switched to java.time. In this case, the wrappers are of threeten clasess. For example

/** Overload of {@link #withTimeout(java.time.Duration)} using {@link org.threeten.bp.Duration} */
@Override
@ObsoleteApi("Use withTimeout(java.time.Duration) instead")
public HttpJsonCallContext withTimeout(org.threeten.bp.Duration timeout) {
return withTimeout(toJavaTimeDuration(timeout));
}
@Override
public HttpJsonCallContext withTimeout(java.time.Duration timeout) {
// Default RetrySettings use 0 for RPC timeout. Treat that as disabled timeouts.
if (timeout != null && (timeout.isZero() || timeout.isNegative())) {

Deprecation warning

threeten methods will now have an @ObsoleteApi annotation. For example:

@ObsoleteApi("Use getDelayThresholdDuration() instead")

CLIRR checks

gax-java/gax

[ERROR] 7013: com.google.api.gax.batching.BatchingSettings: Abstract method 'public java.time.Duration getDelayThresholdDuration()' has been added
[ERROR] 7014: com.google.api.gax.batching.BatchingSettings$Builder: Method 'public com.google.api.gax.batching.BatchingSettings$Builder setDelayThreshold(org.threeten.bp.Duration)' is now final
[ERROR] 7013: com.google.api.gax.batching.BatchingSettings$Builder: Abstract method 'public com.google.api.gax.batching.BatchingSettings$Builder setDelayThresholdDuration(java.time.Duration)' has been added
[ERROR] 7005: com.google.api.gax.retrying.DirectRetryingExecutor: Parameter 1 of 'protected void sleep(org.threeten.bp.Duration)' has changed its type to java.time.Duration
[ERROR] 7013: com.google.api.gax.retrying.RetrySettings: Abstract method 'public java.time.Duration getInitialRetryDelayDuration()' has been added
[ERROR] 7014: com.google.api.gax.retrying.RetrySettings: Method 'public org.threeten.bp.Duration getInitialRpcTimeout()' is now final
[ERROR] 7013: com.google.api.gax.retrying.RetrySettings: Abstract method 'public java.time.Duration getInitialRpcTimeoutDuration()' has been added
[ERROR] 7013: com.google.api.gax.retrying.RetrySettings: Abstract method 'public java.time.Duration getMaxRetryDelayDuration()' has been added
[ERROR] 7014: com.google.api.gax.retrying.RetrySettings: Method 'public org.threeten.bp.Duration getMaxRpcTimeout()' is now final
[ERROR] 7013: com.google.api.gax.retrying.RetrySettings: Abstract method 'public java.time.Duration getMaxRpcTimeoutDuration()' has been added
[ERROR] 7013: com.google.api.gax.retrying.RetrySettings: Abstract method 'public java.time.Duration getTotalTimeoutDuration()' has been added
[ERROR] 7014: com.google.api.gax.retrying.RetrySettings$Builder: Method 'public org.threeten.bp.Duration getInitialRetryDelay()' is now final
[ERROR] 7013: com.google.api.gax.retrying.RetrySettings$Builder: Abstract method 'public java.time.Duration getInitialRetryDelayDuration()' has been added
[ERROR] 7014: com.google.api.gax.retrying.RetrySettings$Builder: Method 'public org.threeten.bp.Duration getInitialRpcTimeout()' is now final
[ERROR] 7013: com.google.api.gax.retrying.RetrySettings$Builder: Abstract method 'public java.time.Duration getInitialRpcTimeoutDuration()' has been added
[ERROR] 7014: com.google.api.gax.retrying.RetrySettings$Builder: Method 'public org.threeten.bp.Duration getMaxRetryDelay()' is now final
[ERROR] 7013: com.google.api.gax.retrying.RetrySettings$Builder: Abstract method 'public java.time.Duration getMaxRetryDelayDuration()' has been added
[ERROR] 7014: com.google.api.gax.retrying.RetrySettings$Builder: Method 'public org.threeten.bp.Duration getMaxRpcTimeout()' is now final
[ERROR] 7013: com.google.api.gax.retrying.RetrySettings$Builder: Abstract method 'public java.time.Duration getMaxRpcTimeoutDuration()' has been added
[ERROR] 7014: com.google.api.gax.retrying.RetrySettings$Builder: Method 'public org.threeten.bp.Duration getTotalTimeout()' is now final
[ERROR] 7013: com.google.api.gax.retrying.RetrySettings$Builder: Abstract method 'public java.time.Duration getTotalTimeoutDuration()' has been added
[ERROR] 7014: com.google.api.gax.retrying.RetrySettings$Builder: Method 'public com.google.api.gax.retrying.RetrySettings$Builder setInitialRetryDelay(org.threeten.bp.Duration)' is now final
[ERROR] 7013: com.google.api.gax.retrying.RetrySettings$Builder: Abstract method 'public com.google.api.gax.retrying.RetrySettings$Builder setInitialRetryDelayDuration(java.time.Duration)' has been added
[ERROR] 7014: com.google.api.gax.retrying.RetrySettings$Builder: Method 'public com.google.api.gax.retrying.RetrySettings$Builder setInitialRpcTimeout(org.threeten.bp.Duration)' is now final
[ERROR] 7013: com.google.api.gax.retrying.RetrySettings$Builder: Abstract method 'public com.google.api.gax.retrying.RetrySettings$Builder setInitialRpcTimeoutDuration(java.time.Duration)' has been added
[ERROR] 7014: com.google.api.gax.retrying.RetrySettings$Builder: Method 'public com.google.api.gax.retrying.RetrySettings$Builder setMaxRetryDelay(org.threeten.bp.Duration)' is now final
[ERROR] 7013: com.google.api.gax.retrying.RetrySettings$Builder: Abstract method 'public com.google.api.gax.retrying.RetrySettings$Builder setMaxRetryDelayDuration(java.time.Duration)' has been added
[ERROR] 7014: com.google.api.gax.retrying.RetrySettings$Builder: Method 'public com.google.api.gax.retrying.RetrySettings$Builder setMaxRpcTimeout(org.threeten.bp.Duration)' is now final
[ERROR] 7013: com.google.api.gax.retrying.RetrySettings$Builder: Abstract method 'public com.google.api.gax.retrying.RetrySettings$Builder setMaxRpcTimeoutDuration(java.time.Duration)' has been added
[ERROR] 7014: com.google.api.gax.retrying.RetrySettings$Builder: Method 'public com.google.api.gax.retrying.RetrySettings$Builder setTotalTimeout(org.threeten.bp.Duration)' is now final
[ERROR] 7013: com.google.api.gax.retrying.RetrySettings$Builder: Abstract method 'public com.google.api.gax.retrying.RetrySettings$Builder setTotalTimeoutDuration(java.time.Duration)' has been added
[ERROR] 7014: com.google.api.gax.retrying.TimedAttemptSettings: Method 'public org.threeten.bp.Duration getRandomizedRetryDelay()' is now final
[ERROR] 7013: com.google.api.gax.retrying.TimedAttemptSettings: Abstract method 'public java.time.Duration getRandomizedRetryDelayDuration()' has been added
[ERROR] 7014: com.google.api.gax.retrying.TimedAttemptSettings: Method 'public org.threeten.bp.Duration getRetryDelay()' is now final
[ERROR] 7013: com.google.api.gax.retrying.TimedAttemptSettings: Abstract method 'public java.time.Duration getRetryDelayDuration()' has been added
[ERROR] 7014: com.google.api.gax.retrying.TimedAttemptSettings: Method 'public org.threeten.bp.Duration getRpcTimeout()' is now final
[ERROR] 7013: com.google.api.gax.retrying.TimedAttemptSettings: Abstract method 'public java.time.Duration getRpcTimeoutDuration()' has been added
[ERROR] 7014: com.google.api.gax.retrying.TimedAttemptSettings$Builder: Method 'public com.google.api.gax.retrying.TimedAttemptSettings$Builder setRandomizedRetryDelay(org.threeten.bp.Duration)' is now final
[ERROR] 7013: com.google.api.gax.retrying.TimedAttemptSettings$Builder: Abstract method 'public com.google.api.gax.retrying.TimedAttemptSettings$Builder setRandomizedRetryDelayDuration(java.time.Duration)' has been added
[ERROR] 7014: com.google.api.gax.retrying.TimedAttemptSettings$Builder: Method 'public com.google.api.gax.retrying.TimedAttemptSettings$Builder setRetryDelay(org.threeten.bp.Duration)' is now final
[ERROR] 7013: com.google.api.gax.retrying.TimedAttemptSettings$Builder: Abstract method 'public com.google.api.gax.retrying.TimedAttemptSettings$Builder setRetryDelayDuration(java.time.Duration)' has been added
[ERROR] 7014: com.google.api.gax.retrying.TimedAttemptSettings$Builder: Method 'public com.google.api.gax.retrying.TimedAttemptSettings$Builder setRpcTimeout(org.threeten.bp.Duration)' is now final
[ERROR] 7013: com.google.api.gax.retrying.TimedAttemptSettings$Builder: Abstract method 'public com.google.api.gax.retrying.TimedAttemptSettings$Builder setRpcTimeoutDuration(java.time.Duration)' has been added
[ERROR] 7012: com.google.api.gax.rpc.ApiCallContext: Method 'public java.time.Duration getStreamIdleTimeoutDuration()' has been added to an interface
[ERROR] 7012: com.google.api.gax.rpc.ApiCallContext: Method 'public java.time.Duration getStreamWaitTimeoutDuration()' has been added to an interface
[ERROR] 7012: com.google.api.gax.rpc.ApiCallContext: Method 'public java.time.Duration getTimeoutDuration()' has been added to an interface
[ERROR] 7012: com.google.api.gax.rpc.ApiCallContext: Method 'public com.google.api.gax.rpc.ApiCallContext withStreamIdleTimeoutDuration(java.time.Duration)' has been added to an interface
[ERROR] 7012: com.google.api.gax.rpc.ApiCallContext: Method 'public com.google.api.gax.rpc.ApiCallContext withStreamWaitTimeoutDuration(java.time.Duration)' has been added to an interface
[ERROR] 7012: com.google.api.gax.rpc.ApiCallContext: Method 'public com.google.api.gax.rpc.ApiCallContext withTimeoutDuration(java.time.Duration)' has been added to an interface
[ERROR] 7014: com.google.api.gax.rpc.ClientContext: Method 'public org.threeten.bp.Duration getStreamWatchdogCheckInterval()' is now final
[ERROR] 7013: com.google.api.gax.rpc.ClientContext: Abstract method 'public java.time.Duration getStreamWatchdogCheckIntervalDuration()' has been added
[ERROR] 7014: com.google.api.gax.rpc.ClientContext$Builder: Method 'public com.google.api.gax.rpc.ClientContext$Builder setStreamWatchdogCheckInterval(org.threeten.bp.Duration)' is now final
[ERROR] 7013: com.google.api.gax.rpc.ClientContext$Builder: Abstract method 'public com.google.api.gax.rpc.ClientContext$Builder setStreamWatchdogCheckIntervalDuration(java.time.Duration)' has been added
[ERROR] 7012: com.google.api.gax.rpc.WatchdogProvider: Method 'public com.google.api.gax.rpc.WatchdogProvider withCheckIntervalDuration(java.time.Duration)' has been added to an interface
[ERROR] 7012: com.google.api.gax.tracing.ApiTracer: Method 'public void attemptFailedDuration(java.lang.Throwable, java.time.Duration)' has been added to an interface

We have decided to ignore a these CLIRR messages due to the following reasons

  • 7005 (method type change): This has only been implemented in internal classes, not exposed to our customers
  • 7013 (new abstract method added): We have added several java.time versions for each of the methods involving org.threeten.bp. This affects AutoValue classes only.
  • 7014 (convert to final): All getters and setters using org.threeten.bp will be marked final because we will force their behavior to be the same one as the java.time counterpart, which has the actual implementation. This affects AutoValue classes only.
  • 7012 (new method in interface): We have added several java.time versions for each of the methods involving org.threeten.bp. For the only public interface WatchdogProvider, we added a default behavior.

@product-auto-label product-auto-label bot added the size: l Pull request size is large. label Jul 20, 2023
@diegomarquezp diegomarquezp changed the title feat: use java.time in gax feat: [wip] use java.time in gax Jul 20, 2023
@diegomarquezp diegomarquezp enabled auto-merge (squash) June 27, 2024 18:03
Copy link

Quality Gate Failed Quality Gate failed for 'gapic-generator-java-root'

Failed conditions
B Reliability Rating on New Code (required ≥ A)

See analysis details on SonarCloud

Catch issues before they fail your Quality Gate with our IDE extension SonarLint

Copy link

Quality Gate Failed Quality Gate failed for 'java_showcase_integration_tests'

Failed conditions
49.8% Coverage on New Code (required ≥ 80%)
B Reliability Rating on New Code (required ≥ A)

See analysis details on SonarCloud

Catch issues before they fail your Quality Gate with our IDE extension SonarLint

@diegomarquezp diegomarquezp merged commit 308aeaf into main Jun 27, 2024
43 of 47 checks passed
@diegomarquezp diegomarquezp deleted the threeten-deprecation branch June 27, 2024 18:17
@diegomarquezp
Copy link
Contributor Author

diegomarquezp commented Jul 4, 2024

The java-spanner downstream check is failing because a new method attemptFailedDuration was added to BaseApiTracer.

Error:  Failures: 
Error:    CompositeTracerTest.testMethodsOverrideMetricsTracer:238 Method not found in compositeTracerMethods: public void com.google.api.gax.tracing.MetricsTracer.attemptFailedDuration(java.lang.Throwable,java.time.Duration)

The test CompositeTracerTest.testMethodsOverrideMetricsTracer verifies that the class CompositeTracer has an overridden declaration of each method of BaseApiTracer, which is not true as of July 4th.

cc: @rahul2393

lqiu96 pushed a commit that referenced this pull request Jul 25, 2024
🤖 I have created a release *beep* *boop*
---


<details><summary>2.43.0</summary>

##
[2.43.0](v2.42.0...v2.43.0)
(2024-07-25)


### Features

* add `transport` option to `generation_config.yaml`
([#3052](#3052))
([3b1a915](3b1a915))
* get released version from versions.txt to render `README.md`
([#3007](#3007))
([99bb2b3](99bb2b3))
* Introduce java.time to Gax-Java
([#1872](#1872))
([308aeaf](308aeaf))
* Mark `getDefaultEndpoint()` with @ObsoleteApi
([#2347](#2347))
([e46648f](e46648f))
* parse `BUILD.bzel` to determine whether a commit that only changed
`BUILD.bazel` is a qualified commit
([#2937](#2937))
([502f801](502f801))


### Bug Fixes

* Fix:
([d996c2d](d996c2d))
* `BaseApiTracer` to noop on attemptFailed via overloaded method call
([#3016](#3016))
([2fc938a](2fc938a))
* Generator to skip generation for empty services.
([#3051](#3051))
([ff2c485](ff2c485))
* restore hermetic build image publication
([#2952](#2952))
([97a6d67](97a6d67))


### Dependencies

* update dependency com.fasterxml.jackson:jackson-bom to v2.17.2
([#3028](#3028))
([d16f9d1](d16f9d1))
* update dependency
com.google.cloud.opentelemetry:detector-resources-support to v0.30.0
([#2975](#2975))
([b3ec93f](b3ec93f))
* update dependency
com.google.cloud.opentelemetry:detector-resources-support to v0.31.0
([#3044](#3044))
([6bd07dc](6bd07dc))
* update dependency com.google.errorprone:error_prone_annotations to
v2.29.2
([#3058](#3058))
([8ea0868](8ea0868))
* update dependency com.google.errorprone:error_prone_annotations to
v2.29.2
([#3059](#3059))
([81b23dc](81b23dc))
* update dependency com.google.guava:guava to v33.2.1-jre
([#3027](#3027))
([12ee456](12ee456))
* update dependency commons-codec:commons-codec to v1.17.1
([#3049](#3049))
([58d94b7](58d94b7))
* update dependency dev.cel:cel to v0.6.0
([#3050](#3050))
([bc332d9](bc332d9))
* update dependency net.bytebuddy:byte-buddy to v1.14.18
([#3029](#3029))
([8799cf6](8799cf6))
* update dependency org.apache.commons:commons-lang3 to v3.15.0
([#3060](#3060))
([2538334](2538334))
* update dependency org.checkerframework:checker-qual to v3.45.0
([#2988](#2988))
([4edd216](4edd216))
* update google api dependencies
([#2951](#2951))
([c16f6c9](c16f6c9))
* update google auth library dependencies to v1.24.0
([#3039](#3039))
([98b5bd7](98b5bd7))
* update googleapis/java-cloud-bom digest to 47c5dbc
([#2974](#2974))
([57623f0](57623f0))
* update grpc dependencies to v1.65.1
([#3061](#3061))
([27497e2](27497e2))
* update junit5 monorepo to v5.10.3
([#2963](#2963))
([bc55fe1](bc55fe1))
* update netty dependencies to v4.1.112.final
([#3057](#3057))
([5af127b](5af127b))
* update opentelemetry-java monorepo to v1.40.0
([#3035](#3035))
([5c31c42](5c31c42))
* Use Gapic-Showcase v0.35.1
([#3018](#3018))
([43773f0](43773f0))


### Documentation

* add support option to 'new issue' choices
([#3055](#3055))
([6a2a17d](6a2a17d))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
if (source == null) {
return null;
}
return java.time.Instant.ofEpochMilli(source.toEpochMilli());
Copy link

@kluever kluever Jul 29, 2024

Choose a reason for hiding this comment

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

FWIW, this truncates sub-millisecond precision. I think what you probably want to do is instead:

return java.time.Instant.ofEpochSecond(source.getEpochSecond(), source.getNano());

Ditto on the other methods in this file (including converting via nanoseconds for the Duration method --- that will overflow for values > 292 years --- instead, use Duration.ofSeconds(duration.getSeconds(), duration.getNano());

Copy link
Contributor

Choose a reason for hiding this comment

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

CC: @diegomarquezp Can you take a look at this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I confirmed this causes trouble:

  @Test
  void testToThreeteenTimeInstant_bigInput_doesNotTruncate() {
    java.time.Instant jtInstant = java.time.Instant.MAX;
    org.threeten.bp.Instant ttInstant = TimeConversionUtils.toThreetenInstant(jtInstant);
    assertEquals(jtInstant.toEpochMilli(), ttInstant.toEpochMilli());
  }

It did not truncate, though. It failed with an overflow exception:

java.lang.ArithmeticException: long overflow

	at java.base/java.lang.Math.multiplyExact(Math.java:1033)
	at java.base/java.lang.Math.multiplyExact(Math.java:1009)
	at java.base/java.time.Instant.toEpochMilli(Instant.java:1262)
	at com.google.api.gax.util.TimeConversionUtils.toThreetenInstant(TimeConversionUtils.java:59)

I'll leave this test as a standard for a coming PR.

diegomarquezp added a commit that referenced this pull request Aug 29, 2024
ldetmer pushed a commit that referenced this pull request Sep 17, 2024
diegomarquezp added a commit that referenced this pull request Oct 30, 2024
…methods (#3321)

This PR leverages the changes in
#1872 so the
generated code uses the new `java.time` methods.
All test-related changes are golden file/string changes.

#### SonarCloud complaints
The SonarCloud scanner complains about code duplication in the generator
code, although after inspection I could not find a reason for stating
so.
It also complains about showcase although the changes in this folder are
strictly golden-oriented.

#### Downstream check failures
They are of the form "could not find remote branch `vX.X.X` to
checkout". This seems not related to this PR as it is also present in
#3318
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size: xl Pull request size is extra large.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants