From 17f5abd6bfaded0859fbdbd26d4a44a6b42b1e9e Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Mon, 11 May 2026 16:53:16 +0700 Subject: [PATCH 1/5] fix: send correct time unit when writing Points --- CHANGELOG.md | 5 +++ .../v3/client/config/ClientConfig.java | 10 ++++- .../client/internal/InfluxDBClientImpl.java | 18 ++++++++- .../v3/client/write/WriteOptions.java | 28 +++++++++++++- .../v3/client/InfluxDBClientWriteTest.java | 10 ++++- .../v3/client/integration/E2ETest.java | 37 ++++++++++++++++++- 6 files changed, 100 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b01b05fa..ee031daf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ See [Partial writes](https://docs.influxdata.com/influxdb3/core/write-data/http-api/v3-write-lp/#partial-writes) for more. For InfluxDB Clustered version, set `useV2Api=true` for writing. +### Bug Fixes + +1. [#384](https://github.com/InfluxCommunity/influxdb3-java/pull/384): Always set `precision` to `nanosecond` when + writing Points. + ## 1.9.0 [2026-04-23] ### Features diff --git a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java index 11021d6d..3f4bce9a 100644 --- a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java +++ b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java @@ -53,7 +53,10 @@ *
  • authScheme - authentication scheme
  • *
  • organization - organization to be used for operations
  • *
  • database - database to be used for InfluxDB operations
  • - *
  • writePrecision - precision to use when writing points to InfluxDB
  • + *
  • writePrecision - precision to use when writing points to InfluxDB. + * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; + * for those writes, the client always sends {@link WritePrecision#NS} + * precision to the server.
  • *
  • defaultTags - defaultTags added when writing points to InfluxDB
  • *
  • gzipThreshold - threshold when gzip compression is used for writing points to InfluxDB
  • *
  • writeNoSync - skip waiting for WAL persistence on write
  • @@ -548,7 +551,10 @@ public Builder database(@Nullable final String database) { * if no precision is specified in the write API call. * * @param writePrecision default precision to use for the timestamp of points - * if no precision is specified in the write API call + * if no precision is specified in the write API call. + * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; + * for those writes, the client always sends {@link WritePrecision#NS} + * precision to the server. * @return this */ @Nonnull diff --git a/src/main/java/com/influxdb/v3/client/internal/InfluxDBClientImpl.java b/src/main/java/com/influxdb/v3/client/internal/InfluxDBClientImpl.java index 3dc05155..5880549c 100644 --- a/src/main/java/com/influxdb/v3/client/internal/InfluxDBClientImpl.java +++ b/src/main/java/com/influxdb/v3/client/internal/InfluxDBClientImpl.java @@ -304,7 +304,14 @@ private void writeData(@Nonnull final List data, @Nonnull final WriteOpti + "or use default configuration at 'ClientConfig.database'."); } - WritePrecision precision = options.precisionSafe(config); + WritePrecision precision; + + if (isWritePoint(data)) { + // When writing Point(s), the timestamp is always converted to nanoseconds. + precision = WritePrecision.NS; + } else { + precision = options.precisionSafe(config); + } options.validate(config); String path; @@ -472,4 +479,13 @@ private byte[] gzipData(@Nonnull final byte[] data) throws IOException { return out.toByteArray(); } + + private boolean isWritePoint(@Nonnull final List data) { + for (T writeAble : data) { + if (writeAble instanceof Point) { + return true; + } + } + return false; + } } diff --git a/src/main/java/com/influxdb/v3/client/write/WriteOptions.java b/src/main/java/com/influxdb/v3/client/write/WriteOptions.java index 00618ec1..7faf0428 100644 --- a/src/main/java/com/influxdb/v3/client/write/WriteOptions.java +++ b/src/main/java/com/influxdb/v3/client/write/WriteOptions.java @@ -40,7 +40,9 @@ *
      *
    • database - specifies the database to be used for InfluxDB operations
    • *
    • organization - specifies the organization to be used for InfluxDB operations
    • - *
    • precision - specifies the precision to use for the timestamp of points
    • + *
    • precision - specifies the precision to use for timestamps in line protocol records. + * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; for those writes, the client + * always sends {@link WritePrecision#NS} precision to the server.
    • *
    • defaultTags - specifies tags to be added by default to all write operations using points.
    • *
    • tagOrder - specifies preferred tag order for point serialization.
    • *
    • noSync - skip waiting for WAL persistence on write
    • @@ -124,6 +126,9 @@ public static WriteOptions defaultWriteOptions() { * If it is not specified then use {@link ClientConfig#getDatabase()}. * @param precision The precision to use for the timestamp of points. * If it is not specified then use {@link ClientConfig#getWritePrecision()}. + * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; + * for those writes, the client always sends {@link WritePrecision#NS} + * precision to the server. * @param gzipThreshold The threshold for compressing request body. * If it is not specified then use {@link WriteOptions#DEFAULT_GZIP_THRESHOLD}. */ @@ -140,6 +145,9 @@ public WriteOptions(@Nullable final String database, * If it is not specified then use {@link ClientConfig#getDatabase()}. * @param precision The precision to use for the timestamp of points. * If it is not specified then use {@link ClientConfig#getWritePrecision()}. + * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; + * for those writes, the client always sends {@link WritePrecision#NS} + * precision to the server. * @param gzipThreshold The threshold for compressing request body. * If it is not specified then use {@link WriteOptions#DEFAULT_GZIP_THRESHOLD}. * @param defaultTags Default tags to be added when writing points. @@ -158,6 +166,9 @@ public WriteOptions(@Nullable final String database, * If it is not specified then use {@link ClientConfig#getDatabase()}. * @param precision The precision to use for the timestamp of points. * If it is not specified then use {@link ClientConfig#getWritePrecision()}. + * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; + * for those writes, the client always sends {@link WritePrecision#NS} + * precision to the server. * @param gzipThreshold The threshold for compressing request body. * If it is not specified then use {@link WriteOptions#DEFAULT_GZIP_THRESHOLD}. * @param noSync Skip waiting for WAL persistence on write. @@ -187,6 +198,9 @@ public WriteOptions(@Nullable final Map headers) { * If it is not specified then use {@link ClientConfig#getDatabase()}. * @param precision The precision to use for the timestamp of points. * If it is not specified then use {@link ClientConfig#getWritePrecision()}. + * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; + * for those writes, the client always sends {@link WritePrecision#NS} + * precision to the server. * @param gzipThreshold The threshold for compressing request body. * If it is not specified then use {@link WriteOptions#DEFAULT_GZIP_THRESHOLD}. * @param defaultTags Default tags to be added when writing points. @@ -209,6 +223,9 @@ public WriteOptions(@Nullable final String database, * If it is not specified then use {@link ClientConfig#getDatabase()}. * @param precision The precision to use for the timestamp of points. * If it is not specified then use {@link ClientConfig#getWritePrecision()}. + * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; + * for those writes, the client always sends {@link WritePrecision#NS} + * precision to the server. * @param gzipThreshold The threshold for compressing request body. * If it is not specified then use {@link WriteOptions#DEFAULT_GZIP_THRESHOLD}. * @param noSync Skip waiting for WAL persistence on write. @@ -234,6 +251,9 @@ public WriteOptions(@Nullable final String database, * If it is not specified then use {@link ClientConfig#getDatabase()}. * @param precision The precision to use for the timestamp of points. * If it is not specified then use {@link ClientConfig#getWritePrecision()}. + * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; + * for those writes, the client always sends {@link WritePrecision#NS} + * precision to the server. * @param gzipThreshold The threshold for compressing request body. * If it is not specified then use {@link WriteOptions#DEFAULT_GZIP_THRESHOLD}. * @param noSync Skip waiting for WAL persistence on write. @@ -265,6 +285,9 @@ public WriteOptions(@Nullable final String database, * If it is not specified then use {@link ClientConfig#getDatabase()}. * @param precision The precision to use for the timestamp of points. * If it is not specified then use {@link ClientConfig#getWritePrecision()}. + * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; + * for those writes, the client always sends {@link WritePrecision#NS} + * precision to the server. * @param gzipThreshold The threshold for compressing request body. * If it is not specified then use {@link WriteOptions#DEFAULT_GZIP_THRESHOLD}. * @param noSync Skip waiting for WAL persistence on write. @@ -307,6 +330,9 @@ public WriteOptions(@Nullable final String database, * If it is not specified then use {@link ClientConfig#getDatabase()}. * @param precision The precision to use for the timestamp of points. * If it is not specified then use {@link ClientConfig#getWritePrecision()}. + * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; + * for those writes, the client always sends {@link WritePrecision#NS} + * precision to the server. * @param gzipThreshold The threshold for compressing request body. * If it is not specified then use {@link WriteOptions#DEFAULT_GZIP_THRESHOLD}. * @param noSync Skip waiting for WAL persistence on write. diff --git a/src/test/java/com/influxdb/v3/client/InfluxDBClientWriteTest.java b/src/test/java/com/influxdb/v3/client/InfluxDBClientWriteTest.java index 4382b646..4d94738d 100644 --- a/src/test/java/com/influxdb/v3/client/InfluxDBClientWriteTest.java +++ b/src/test/java/com/influxdb/v3/client/InfluxDBClientWriteTest.java @@ -412,7 +412,10 @@ void writePointWithDefaultWriteOptionsCustomConfig() throws Exception { client.writePoint(point); } - checkWriteCalled("/api/v3/write_lp", "DB", "second", true, "true", null, true); + // When writing Point, precision sent to the server is always nanosecond + var expectedPrecision = "nanosecond"; + + checkWriteCalled("/api/v3/write_lp", "DB", expectedPrecision, true, "true", null, true); } @Test @@ -447,7 +450,10 @@ void writePointsWithDefaultWriteOptionsCustomConfig() throws Exception { client.writePoints(List.of(point)); } - checkWriteCalled("/api/v3/write_lp", "DB", "second", true, "true", null, true); + // When writing Point, precision sent to the server is always nanosecond + var expectedPrecision = "nanosecond"; + + checkWriteCalled("/api/v3/write_lp", "DB", expectedPrecision, true, "true", null, true); } private void checkWriteCalled(final String expectedPath, final String expectedDB, diff --git a/src/test/java/com/influxdb/v3/client/integration/E2ETest.java b/src/test/java/com/influxdb/v3/client/integration/E2ETest.java index dc02f7da..cba42021 100644 --- a/src/test/java/com/influxdb/v3/client/integration/E2ETest.java +++ b/src/test/java/com/influxdb/v3/client/integration/E2ETest.java @@ -595,10 +595,43 @@ public void testMultipleQueries() throws Exception { } } } - - } + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_URL", matches = ".*") + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_TOKEN", matches = ".*") + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*") + @Test + public void testWriteWithDifferentTimeUnit() throws Exception { + try (InfluxDBClient client = InfluxDBClient.getInstance( + System.getenv("TESTING_INFLUXDB_URL"), + System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray(), + System.getenv("TESTING_INFLUXDB_DATABASE"), + null)) { + var writeOptions = new WriteOptions.Builder().precision(WritePrecision.MS).build(); + String measurement = "test_" + UUID.randomUUID(); + List points = List.of( + Point.measurement(measurement) + .setTag("type", "test") + .setFloatField("rads", 3.14) + .setIntegerField("life", 42) + .setTimestamp(Instant.now().toEpochMilli(), WritePrecision.MS), + Point.measurement(measurement) + .setTag("type", "test") + .setFloatField("rads", 3.14) + .setIntegerField("life", 12) + .setTimestamp(Instant.now().plusSeconds(1).getEpochSecond(), WritePrecision.S), + Point.measurement(measurement) + .setTag("type", "test") + .setFloatField("rads", 3.14) + .setIntegerField("life", 432) + .setTimestamp(Instant.now().plusSeconds(2).toEpochMilli() * 1000, WritePrecision.US) + ); + client.writePoints(points, writeOptions); + var results = client.queryPoints(String.format("select * from \"%s\"", measurement)) + .collect(Collectors.toList()); + Assertions.assertThat(results).hasSize(3); + } + } private void assertGetDataSuccess(@Nonnull final InfluxDBClient influxDBClient) { influxDBClient.writePoint( From effee32be5fcdc764bf28bd8529e84347029580b Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Wed, 13 May 2026 12:16:03 +0700 Subject: [PATCH 2/5] chore: update comments --- .../influxdb/v3/client/config/ClientConfig.java | 4 ++-- .../com/influxdb/v3/client/write/WriteOptions.java | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java index 3f4bce9a..8acb1ade 100644 --- a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java +++ b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java @@ -53,7 +53,7 @@ *
    • authScheme - authentication scheme
    • *
    • organization - organization to be used for operations
    • *
    • database - database to be used for InfluxDB operations
    • - *
    • writePrecision - precision to use when writing points to InfluxDB. + *
    • writePrecision - precision to use when writing to InfluxDB. * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; * for those writes, the client always sends {@link WritePrecision#NS} * precision to the server.
    • @@ -550,7 +550,7 @@ public Builder database(@Nullable final String database) { * Sets the default precision to use for the timestamp of points * if no precision is specified in the write API call. * - * @param writePrecision default precision to use for the timestamp of points + * @param writePrecision default precision to use for the timestamp * if no precision is specified in the write API call. * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; * for those writes, the client always sends {@link WritePrecision#NS} diff --git a/src/main/java/com/influxdb/v3/client/write/WriteOptions.java b/src/main/java/com/influxdb/v3/client/write/WriteOptions.java index 7faf0428..8e28561f 100644 --- a/src/main/java/com/influxdb/v3/client/write/WriteOptions.java +++ b/src/main/java/com/influxdb/v3/client/write/WriteOptions.java @@ -143,7 +143,7 @@ public WriteOptions(@Nullable final String database, * * @param database The database to be used for InfluxDB operations. * If it is not specified then use {@link ClientConfig#getDatabase()}. - * @param precision The precision to use for the timestamp of points. + * @param precision The precision to use for the timestamp. * If it is not specified then use {@link ClientConfig#getWritePrecision()}. * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; * for those writes, the client always sends {@link WritePrecision#NS} @@ -164,7 +164,7 @@ public WriteOptions(@Nullable final String database, * * @param database The database to be used for InfluxDB operations. * If it is not specified then use {@link ClientConfig#getDatabase()}. - * @param precision The precision to use for the timestamp of points. + * @param precision The precision to use for the timestamp. * If it is not specified then use {@link ClientConfig#getWritePrecision()}. * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; * for those writes, the client always sends {@link WritePrecision#NS} @@ -196,7 +196,7 @@ public WriteOptions(@Nullable final Map headers) { * * @param database The database to be used for InfluxDB operations. * If it is not specified then use {@link ClientConfig#getDatabase()}. - * @param precision The precision to use for the timestamp of points. + * @param precision The precision to use for the timestamp. * If it is not specified then use {@link ClientConfig#getWritePrecision()}. * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; * for those writes, the client always sends {@link WritePrecision#NS} @@ -221,7 +221,7 @@ public WriteOptions(@Nullable final String database, * * @param database The database to be used for InfluxDB operations. * If it is not specified then use {@link ClientConfig#getDatabase()}. - * @param precision The precision to use for the timestamp of points. + * @param precision The precision to use for the timestamp. * If it is not specified then use {@link ClientConfig#getWritePrecision()}. * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; * for those writes, the client always sends {@link WritePrecision#NS} @@ -249,7 +249,7 @@ public WriteOptions(@Nullable final String database, * * @param database The database to be used for InfluxDB operations. * If it is not specified then use {@link ClientConfig#getDatabase()}. - * @param precision The precision to use for the timestamp of points. + * @param precision The precision to use for the timestamp. * If it is not specified then use {@link ClientConfig#getWritePrecision()}. * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; * for those writes, the client always sends {@link WritePrecision#NS} @@ -283,7 +283,7 @@ public WriteOptions(@Nullable final String database, * * @param database The database to be used for InfluxDB operations. * If it is not specified then use {@link ClientConfig#getDatabase()}. - * @param precision The precision to use for the timestamp of points. + * @param precision The precision to use for the timestamp. * If it is not specified then use {@link ClientConfig#getWritePrecision()}. * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; * for those writes, the client always sends {@link WritePrecision#NS} @@ -328,7 +328,7 @@ public WriteOptions(@Nullable final String database, * * @param database The database to be used for InfluxDB operations. * If it is not specified then use {@link ClientConfig#getDatabase()}. - * @param precision The precision to use for the timestamp of points. + * @param precision The precision to use for the timestamp. * If it is not specified then use {@link ClientConfig#getWritePrecision()}. * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; * for those writes, the client always sends {@link WritePrecision#NS} From 703b511798f7c104329c40debe604010f5956c1f Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Wed, 13 May 2026 12:54:57 +0700 Subject: [PATCH 3/5] test: add pointWritesIgnoreWriteOptionsPrecision --- .../v3/client/InfluxDBClientWriteTest.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/test/java/com/influxdb/v3/client/InfluxDBClientWriteTest.java b/src/test/java/com/influxdb/v3/client/InfluxDBClientWriteTest.java index 4d94738d..8fb702a2 100644 --- a/src/test/java/com/influxdb/v3/client/InfluxDBClientWriteTest.java +++ b/src/test/java/com/influxdb/v3/client/InfluxDBClientWriteTest.java @@ -456,6 +456,43 @@ void writePointsWithDefaultWriteOptionsCustomConfig() throws Exception { checkWriteCalled("/api/v3/write_lp", "DB", expectedPrecision, true, "true", null, true); } + @ParameterizedTest(name = "{0}") + @MethodSource("pointPrecisionIgnoredCases") + void pointWritesIgnoreWriteOptionsPrecision( + String name, + WritePrecision configuredPrecision, + boolean manyPoints) throws Exception { + mockServer.enqueue(createResponse(200)); + ClientConfig cfg = new ClientConfig.Builder() + .host(baseURL) + .token("TOKEN".toCharArray()) + .database("DB") + .build(); + try (InfluxDBClient client = InfluxDBClient.getInstance(cfg)) { + Point point = new Point("mem"); + point.setTag("tag", "one"); + point.setField("value", 1.0); + WriteOptions options = new WriteOptions.Builder() + .precision(configuredPrecision) + .build(); + if (manyPoints) { + client.writePoints(List.of(point), options); + } else { + client.writePoint(point, options); + } + } + checkWriteCalled("/api/v3/write_lp", "DB", "nanosecond", true, null, null, false); + } + + private static Stream pointPrecisionIgnoredCases() { + return Stream.of( + Arguments.of("writePoint precision=S", WritePrecision.S, false), + Arguments.of("writePoint precision=MS", WritePrecision.MS, false), + Arguments.of("writePoints precision=S", WritePrecision.S, true), + Arguments.of("writePoints precision=US", WritePrecision.US, true) + ); + } + private void checkWriteCalled(final String expectedPath, final String expectedDB, final String expectedPrecision, final boolean expectedV3, @Nullable final String expectedNoSync, From a47f820207eedc736fa129831ddbec58e431f55a Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Wed, 13 May 2026 13:03:06 +0700 Subject: [PATCH 4/5] test: add pointWritesIgnoreWriteOptionsPrecision --- .../com/influxdb/v3/client/InfluxDBClientWriteTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/influxdb/v3/client/InfluxDBClientWriteTest.java b/src/test/java/com/influxdb/v3/client/InfluxDBClientWriteTest.java index 8fb702a2..b635fceb 100644 --- a/src/test/java/com/influxdb/v3/client/InfluxDBClientWriteTest.java +++ b/src/test/java/com/influxdb/v3/client/InfluxDBClientWriteTest.java @@ -459,9 +459,9 @@ void writePointsWithDefaultWriteOptionsCustomConfig() throws Exception { @ParameterizedTest(name = "{0}") @MethodSource("pointPrecisionIgnoredCases") void pointWritesIgnoreWriteOptionsPrecision( - String name, - WritePrecision configuredPrecision, - boolean manyPoints) throws Exception { + @Nonnull final String name, + @Nonnull final WritePrecision configuredPrecision, + final boolean manyPoints) throws Exception { mockServer.enqueue(createResponse(200)); ClientConfig cfg = new ClientConfig.Builder() .host(baseURL) From 80f95ef92cb22416e445e2b8baa03ff3e931e51a Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Wed, 13 May 2026 16:10:43 +0700 Subject: [PATCH 5/5] chore: update comments --- src/main/java/com/influxdb/v3/client/write/WriteOptions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/influxdb/v3/client/write/WriteOptions.java b/src/main/java/com/influxdb/v3/client/write/WriteOptions.java index 8e28561f..3487709b 100644 --- a/src/main/java/com/influxdb/v3/client/write/WriteOptions.java +++ b/src/main/java/com/influxdb/v3/client/write/WriteOptions.java @@ -124,7 +124,7 @@ public static WriteOptions defaultWriteOptions() { * * @param database The database to be used for InfluxDB operations. * If it is not specified then use {@link ClientConfig#getDatabase()}. - * @param precision The precision to use for the timestamp of points. + * @param precision The precision to use for the timestamp. * If it is not specified then use {@link ClientConfig#getWritePrecision()}. * This setting is ignored when writing {@link com.influxdb.v3.client.Point}; * for those writes, the client always sends {@link WritePrecision#NS}