fix(bigtable): truncate client generated timestamps on the emulator c… - #14234
Merged
Conversation
…hannel Auto generated cell timestamps now carry true microsecond precision and are tagged as CLIENT_AUTO_GENERATED. The service truncates those to the target table's granularity, so writes to a MILLIS table keep working. The emulator predates timestamp_origin and instead rejects any timestamp that isn't a multiple of 1000, which broke every auto timestamped write: UNKNOWN: invalid timestamp 1788287743903953 Install a MillisTimestampInterceptor on the emulator channel that performs the truncation the emulator is missing, so it behaves like a MILLIS granularity table. Explicitly specified timestamps are left alone, since a MILLIS table rejects those in production too. This lets the five integration tests that were skipped on the emulator run again.
Contributor
There was a problem hiding this comment.
Code Review
This pull request introduces a MillisTimestampInterceptor that rounds client-generated cell timestamps down to millisecond granularity when running against the Bigtable emulator. This resolves issues where the emulator would reject non-millisecond-aligned auto-generated timestamps, whereas the production service would truncate them. Consequently, several integration tests have been updated to remove the environment checks that previously skipped the emulator. I have no feedback to provide.
nimf
requested changes
Sep 1, 2026
Addresses review feedback: dropping the "null means nothing changed" sentinel lets truncate/truncateAll always return a value, which removes the incremental copy-on-first-change bookkeeping from all three request types. Requests are now always rebuilt, but unchanged mutations are shared by reference rather than copied, and this only runs against the emulator.
nimf
approved these changes
Sep 2, 2026
mutianf
enabled auto-merge (squash)
September 2, 2026 15:37
mutianf
disabled auto-merge
September 3, 2026 17:57
This was referenced Sep 4, 2026
lqiu96
pushed a commit
that referenced
this pull request
Sep 4, 2026
🤖 I have created a release *beep* *boop* --- <details><summary>1.91.0</summary> ## [1.91.0](v1.90.0...v1.91.0) (2026-09-04) ### ⚠ BREAKING CHANGES * **datalabeling:** remove java-datalabeling library ([#14189](#14189)) * **datacatalog:** remove java-datacatalog library ([#14178](#14178)) ### Features * **apptopology:** onboard a new library ([#14204](#14204)) ([f871a07](f871a07)) * **bigtable:** Option to disable direct access fallback ([#14193](#14193)) ([5b6a974](5b6a974)) * **datacatalog:** remove java-datacatalog library ([#14178](#14178)) ([2910f63](2910f63)) * **datalabeling:** remove java-datalabeling library ([#14189](#14189)) ([334d35a](334d35a)), refs [#14176](#14176) * **gax:** add getSingleHeader to HttpHeadersUtils ([#14137](#14137)) ([f114422](f114422)) * **gax:** add ResumableUploadClient.startUpload() and supporting types ([#14138](#14138)) ([d7e2be2](d7e2be2)) * **gax:** add ResumableUploadResponseParser ([#14135](#14135)) ([e1a0b17](e1a0b17)) * **gax:** allow non-JSON HttpContent and absolute request URLs in HttpRequestRunnable ([#14134](#14134)) ([ac4a49a](ac4a49a)) * **gax:** implement queryStatusCallable for resumable uploads ([#14155](#14155)) ([67719c0](67719c0)) * **gax:** implement startUploadCallable for resumable uploads ([#14139](#14139)) ([4e65b6c](4e65b6c)) * **gax:** implement uploadChunkCallable for resumable uploads ([#14140](#14140)) ([1c643de](1c643de)) * **google/shopping/merchant/loyaltycustomers/v1:** onboard new library ([#14257](#14257)) ([590a51c](590a51c)) * **grpc-gcp:** drain scaled-down channels ([#14216](#14216)) ([bbbd18c](bbbd18c)) * **grpc-gcp:** move scale-up to background worker ([#14206](#14206)) ([41f0a2e](41f0a2e)) * **grpc-gcp:** penalize retryable channel errors ([#14219](#14219)) ([829872e](829872e)) * **grpc-gcp:** prime scaled channels before publish ([#14232](#14232)) ([dd75645](dd75645)) * **spanner:** add client-level CallContextConfigurator to SpannerOptions ([#14256](#14256)) ([eef74d2](eef74d2)) * **spanner:** prime scaled-up dynamic channel pool channels with SELECT 1 ([#14254](#14254)) ([4d26645](4d26645)) ### Bug Fixes * **auth:** refine JSpecify nullability annotations for external account credentials ([#14164](#14164)) ([385e1f2](385e1f2)) * **bigquery-jdbc:** resolve `statementType` via `getJob` fallback to avoid post-execution dry run for DDL ([#14265](#14265)) ([d38d9f0](d38d9f0)) * **bigtable:** truncate client generated timestamps on the emulator c… ([#14234](#14234)) ([94e680f](94e680f)) * **gax:** propagate structured LRO error details to ApiException ([#14022](#14022)) ([865a15b](865a15b)) * **grpc-gcp:** correct channel lifecycle bookkeeping ([#14196](#14196)) ([3df32ba](3df32ba)) * **grpc-gcp:** prevent hot-channel skew ([#14198](#14198)) ([07a7505](07a7505)) * **java-sql:** temp fix for lint and skip generate ([#14005](#14005)) ([b6f73db](b6f73db)) * **spanner:** prioritize leader replica for read-write transactions in location-aware routing ([#14195](#14195)) ([6383f81](6383f81)) * **spanner:** route ExecuteBatchDml through transaction affinity endpoint ([#14192](#14192)) ([5e9e3cd](5e9e3cd)) * **storage:** resolve GraalVM Native Image test failure for java-storage ([#14226](#14226)) ([93e0920](93e0920)) ### Performance Improvements * **bigquery-jdbc:** eliminate sync getJob RPC call ([#14197](#14197)) ([ccf12b0](ccf12b0)) * **ci:** replace mvn help:evaluate with native bash and sed extraction ([#14218](#14218)) ([744a522](744a522)) ### Dependencies * Upgrade grpc-java to 1.83.0 ([#13967](#13967)) ([0cdc695](0cdc695)) </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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…hannel
Auto generated cell timestamps now carry true microsecond precision and are tagged as CLIENT_AUTO_GENERATED. The service truncates those to the target table's granularity, so writes to a MILLIS table keep working. The emulator predates timestamp_origin and instead rejects any timestamp that isn't a multiple of 1000, which broke every auto timestamped write.
Install a MillisTimestampInterceptor on the emulator channel that performs the truncation the emulator is missing, so it behaves like a MILLIS granularity table. Explicitly specified timestamps are left alone, since a MILLIS table rejects those in production too.
This lets the five integration tests that were skipped on the emulator run again.