Skip to content

Commit 8221ebe

Browse files
fix: send correct time unit when writing Points (#384)
1 parent a0b6dbf commit 8221ebe

6 files changed

Lines changed: 146 additions & 17 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
See [Partial writes](https://docs.influxdata.com/influxdb3/core/write-data/http-api/v3-write-lp/#partial-writes) for more.
77
For InfluxDB Clustered version, set `useV2Api=true` for writing.
88

9+
### Bug Fixes
10+
11+
1. [#384](https://github.com/InfluxCommunity/influxdb3-java/pull/384): Always set `precision` to `nanosecond` when
12+
writing Points.
13+
914
## 1.9.0 [2026-04-23]
1015

1116
### Features

src/main/java/com/influxdb/v3/client/config/ClientConfig.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@
5353
* <li><code>authScheme</code> - authentication scheme</li>
5454
* <li><code>organization</code> - organization to be used for operations</li>
5555
* <li><code>database</code> - database to be used for InfluxDB operations</li>
56-
* <li><code>writePrecision</code> - precision to use when writing points to InfluxDB</li>
56+
* <li><code>writePrecision</code> - precision to use when writing to InfluxDB.
57+
* This setting is ignored when writing {@link com.influxdb.v3.client.Point};
58+
* for those writes, the client always sends {@link WritePrecision#NS}
59+
* precision to the server.</li>
5760
* <li><code>defaultTags</code> - defaultTags added when writing points to InfluxDB</li>
5861
* <li><code>gzipThreshold</code> - threshold when gzip compression is used for writing points to InfluxDB</li>
5962
* <li><code>writeNoSync</code> - skip waiting for WAL persistence on write</li>
@@ -547,8 +550,11 @@ public Builder database(@Nullable final String database) {
547550
* Sets the default precision to use for the timestamp of points
548551
* if no precision is specified in the write API call.
549552
*
550-
* @param writePrecision default precision to use for the timestamp of points
551-
* if no precision is specified in the write API call
553+
* @param writePrecision default precision to use for the timestamp
554+
* if no precision is specified in the write API call.
555+
* This setting is ignored when writing {@link com.influxdb.v3.client.Point};
556+
* for those writes, the client always sends {@link WritePrecision#NS}
557+
* precision to the server.
552558
* @return this
553559
*/
554560
@Nonnull

src/main/java/com/influxdb/v3/client/internal/InfluxDBClientImpl.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,14 @@ private <T> void writeData(@Nonnull final List<T> data, @Nonnull final WriteOpti
304304
+ "or use default configuration at 'ClientConfig.database'.");
305305
}
306306

307-
WritePrecision precision = options.precisionSafe(config);
307+
WritePrecision precision;
308+
309+
if (isWritePoint(data)) {
310+
// When writing Point(s), the timestamp is always converted to nanoseconds.
311+
precision = WritePrecision.NS;
312+
} else {
313+
precision = options.precisionSafe(config);
314+
}
308315
options.validate(config);
309316

310317
String path;
@@ -472,4 +479,13 @@ private byte[] gzipData(@Nonnull final byte[] data) throws IOException {
472479

473480
return out.toByteArray();
474481
}
482+
483+
private <T> boolean isWritePoint(@Nonnull final List<T> data) {
484+
for (T writeAble : data) {
485+
if (writeAble instanceof Point) {
486+
return true;
487+
}
488+
}
489+
return false;
490+
}
475491
}

src/main/java/com/influxdb/v3/client/write/WriteOptions.java

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@
4040
* <ul>
4141
* <li><code>database</code> - specifies the database to be used for InfluxDB operations</li>
4242
* <li><code>organization</code> - specifies the organization to be used for InfluxDB operations</li>
43-
* <li><code>precision</code> - specifies the precision to use for the timestamp of points</li>
43+
* <li><code>precision</code> - specifies the precision to use for timestamps in line protocol records.
44+
* This setting is ignored when writing {@link com.influxdb.v3.client.Point}; for those writes, the client
45+
* always sends {@link WritePrecision#NS} precision to the server.</li>
4446
* <li><code>defaultTags</code> - specifies tags to be added by default to all write operations using points.</li>
4547
* <li><code>tagOrder</code> - specifies preferred tag order for point serialization.</li>
4648
* <li><code>noSync</code> - skip waiting for WAL persistence on write</li>
@@ -122,8 +124,11 @@ public static WriteOptions defaultWriteOptions() {
122124
*
123125
* @param database The database to be used for InfluxDB operations.
124126
* If it is not specified then use {@link ClientConfig#getDatabase()}.
125-
* @param precision The precision to use for the timestamp of points.
127+
* @param precision The precision to use for the timestamp.
126128
* If it is not specified then use {@link ClientConfig#getWritePrecision()}.
129+
* This setting is ignored when writing {@link com.influxdb.v3.client.Point};
130+
* for those writes, the client always sends {@link WritePrecision#NS}
131+
* precision to the server.
127132
* @param gzipThreshold The threshold for compressing request body.
128133
* If it is not specified then use {@link WriteOptions#DEFAULT_GZIP_THRESHOLD}.
129134
*/
@@ -138,8 +143,11 @@ public WriteOptions(@Nullable final String database,
138143
*
139144
* @param database The database to be used for InfluxDB operations.
140145
* If it is not specified then use {@link ClientConfig#getDatabase()}.
141-
* @param precision The precision to use for the timestamp of points.
146+
* @param precision The precision to use for the timestamp.
142147
* If it is not specified then use {@link ClientConfig#getWritePrecision()}.
148+
* This setting is ignored when writing {@link com.influxdb.v3.client.Point};
149+
* for those writes, the client always sends {@link WritePrecision#NS}
150+
* precision to the server.
143151
* @param gzipThreshold The threshold for compressing request body.
144152
* If it is not specified then use {@link WriteOptions#DEFAULT_GZIP_THRESHOLD}.
145153
* @param defaultTags Default tags to be added when writing points.
@@ -156,8 +164,11 @@ public WriteOptions(@Nullable final String database,
156164
*
157165
* @param database The database to be used for InfluxDB operations.
158166
* If it is not specified then use {@link ClientConfig#getDatabase()}.
159-
* @param precision The precision to use for the timestamp of points.
167+
* @param precision The precision to use for the timestamp.
160168
* If it is not specified then use {@link ClientConfig#getWritePrecision()}.
169+
* This setting is ignored when writing {@link com.influxdb.v3.client.Point};
170+
* for those writes, the client always sends {@link WritePrecision#NS}
171+
* precision to the server.
161172
* @param gzipThreshold The threshold for compressing request body.
162173
* If it is not specified then use {@link WriteOptions#DEFAULT_GZIP_THRESHOLD}.
163174
* @param noSync Skip waiting for WAL persistence on write.
@@ -185,8 +196,11 @@ public WriteOptions(@Nullable final Map<String, String> headers) {
185196
*
186197
* @param database The database to be used for InfluxDB operations.
187198
* If it is not specified then use {@link ClientConfig#getDatabase()}.
188-
* @param precision The precision to use for the timestamp of points.
199+
* @param precision The precision to use for the timestamp.
189200
* If it is not specified then use {@link ClientConfig#getWritePrecision()}.
201+
* This setting is ignored when writing {@link com.influxdb.v3.client.Point};
202+
* for those writes, the client always sends {@link WritePrecision#NS}
203+
* precision to the server.
190204
* @param gzipThreshold The threshold for compressing request body.
191205
* If it is not specified then use {@link WriteOptions#DEFAULT_GZIP_THRESHOLD}.
192206
* @param defaultTags Default tags to be added when writing points.
@@ -207,8 +221,11 @@ public WriteOptions(@Nullable final String database,
207221
*
208222
* @param database The database to be used for InfluxDB operations.
209223
* If it is not specified then use {@link ClientConfig#getDatabase()}.
210-
* @param precision The precision to use for the timestamp of points.
224+
* @param precision The precision to use for the timestamp.
211225
* If it is not specified then use {@link ClientConfig#getWritePrecision()}.
226+
* This setting is ignored when writing {@link com.influxdb.v3.client.Point};
227+
* for those writes, the client always sends {@link WritePrecision#NS}
228+
* precision to the server.
212229
* @param gzipThreshold The threshold for compressing request body.
213230
* If it is not specified then use {@link WriteOptions#DEFAULT_GZIP_THRESHOLD}.
214231
* @param noSync Skip waiting for WAL persistence on write.
@@ -232,8 +249,11 @@ public WriteOptions(@Nullable final String database,
232249
*
233250
* @param database The database to be used for InfluxDB operations.
234251
* If it is not specified then use {@link ClientConfig#getDatabase()}.
235-
* @param precision The precision to use for the timestamp of points.
252+
* @param precision The precision to use for the timestamp.
236253
* If it is not specified then use {@link ClientConfig#getWritePrecision()}.
254+
* This setting is ignored when writing {@link com.influxdb.v3.client.Point};
255+
* for those writes, the client always sends {@link WritePrecision#NS}
256+
* precision to the server.
237257
* @param gzipThreshold The threshold for compressing request body.
238258
* If it is not specified then use {@link WriteOptions#DEFAULT_GZIP_THRESHOLD}.
239259
* @param noSync Skip waiting for WAL persistence on write.
@@ -263,8 +283,11 @@ public WriteOptions(@Nullable final String database,
263283
*
264284
* @param database The database to be used for InfluxDB operations.
265285
* If it is not specified then use {@link ClientConfig#getDatabase()}.
266-
* @param precision The precision to use for the timestamp of points.
286+
* @param precision The precision to use for the timestamp.
267287
* If it is not specified then use {@link ClientConfig#getWritePrecision()}.
288+
* This setting is ignored when writing {@link com.influxdb.v3.client.Point};
289+
* for those writes, the client always sends {@link WritePrecision#NS}
290+
* precision to the server.
268291
* @param gzipThreshold The threshold for compressing request body.
269292
* If it is not specified then use {@link WriteOptions#DEFAULT_GZIP_THRESHOLD}.
270293
* @param noSync Skip waiting for WAL persistence on write.
@@ -305,8 +328,11 @@ public WriteOptions(@Nullable final String database,
305328
*
306329
* @param database The database to be used for InfluxDB operations.
307330
* If it is not specified then use {@link ClientConfig#getDatabase()}.
308-
* @param precision The precision to use for the timestamp of points.
331+
* @param precision The precision to use for the timestamp.
309332
* If it is not specified then use {@link ClientConfig#getWritePrecision()}.
333+
* This setting is ignored when writing {@link com.influxdb.v3.client.Point};
334+
* for those writes, the client always sends {@link WritePrecision#NS}
335+
* precision to the server.
310336
* @param gzipThreshold The threshold for compressing request body.
311337
* If it is not specified then use {@link WriteOptions#DEFAULT_GZIP_THRESHOLD}.
312338
* @param noSync Skip waiting for WAL persistence on write.

src/test/java/com/influxdb/v3/client/InfluxDBClientWriteTest.java

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,10 @@ void writePointWithDefaultWriteOptionsCustomConfig() throws Exception {
412412
client.writePoint(point);
413413
}
414414

415-
checkWriteCalled("/api/v3/write_lp", "DB", "second", true, "true", null, true);
415+
// When writing Point, precision sent to the server is always nanosecond
416+
var expectedPrecision = "nanosecond";
417+
418+
checkWriteCalled("/api/v3/write_lp", "DB", expectedPrecision, true, "true", null, true);
416419
}
417420

418421
@Test
@@ -447,7 +450,47 @@ void writePointsWithDefaultWriteOptionsCustomConfig() throws Exception {
447450
client.writePoints(List.of(point));
448451
}
449452

450-
checkWriteCalled("/api/v3/write_lp", "DB", "second", true, "true", null, true);
453+
// When writing Point, precision sent to the server is always nanosecond
454+
var expectedPrecision = "nanosecond";
455+
456+
checkWriteCalled("/api/v3/write_lp", "DB", expectedPrecision, true, "true", null, true);
457+
}
458+
459+
@ParameterizedTest(name = "{0}")
460+
@MethodSource("pointPrecisionIgnoredCases")
461+
void pointWritesIgnoreWriteOptionsPrecision(
462+
@Nonnull final String name,
463+
@Nonnull final WritePrecision configuredPrecision,
464+
final boolean manyPoints) throws Exception {
465+
mockServer.enqueue(createResponse(200));
466+
ClientConfig cfg = new ClientConfig.Builder()
467+
.host(baseURL)
468+
.token("TOKEN".toCharArray())
469+
.database("DB")
470+
.build();
471+
try (InfluxDBClient client = InfluxDBClient.getInstance(cfg)) {
472+
Point point = new Point("mem");
473+
point.setTag("tag", "one");
474+
point.setField("value", 1.0);
475+
WriteOptions options = new WriteOptions.Builder()
476+
.precision(configuredPrecision)
477+
.build();
478+
if (manyPoints) {
479+
client.writePoints(List.of(point), options);
480+
} else {
481+
client.writePoint(point, options);
482+
}
483+
}
484+
checkWriteCalled("/api/v3/write_lp", "DB", "nanosecond", true, null, null, false);
485+
}
486+
487+
private static Stream<Arguments> pointPrecisionIgnoredCases() {
488+
return Stream.of(
489+
Arguments.of("writePoint precision=S", WritePrecision.S, false),
490+
Arguments.of("writePoint precision=MS", WritePrecision.MS, false),
491+
Arguments.of("writePoints precision=S", WritePrecision.S, true),
492+
Arguments.of("writePoints precision=US", WritePrecision.US, true)
493+
);
451494
}
452495

453496
private void checkWriteCalled(final String expectedPath, final String expectedDB,

src/test/java/com/influxdb/v3/client/integration/E2ETest.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -595,10 +595,43 @@ public void testMultipleQueries() throws Exception {
595595
}
596596
}
597597
}
598-
599-
600598
}
601599

600+
@EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_URL", matches = ".*")
601+
@EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_TOKEN", matches = ".*")
602+
@EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*")
603+
@Test
604+
public void testWriteWithDifferentTimeUnit() throws Exception {
605+
try (InfluxDBClient client = InfluxDBClient.getInstance(
606+
System.getenv("TESTING_INFLUXDB_URL"),
607+
System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray(),
608+
System.getenv("TESTING_INFLUXDB_DATABASE"),
609+
null)) {
610+
var writeOptions = new WriteOptions.Builder().precision(WritePrecision.MS).build();
611+
String measurement = "test_" + UUID.randomUUID();
612+
List<Point> points = List.of(
613+
Point.measurement(measurement)
614+
.setTag("type", "test")
615+
.setFloatField("rads", 3.14)
616+
.setIntegerField("life", 42)
617+
.setTimestamp(Instant.now().toEpochMilli(), WritePrecision.MS),
618+
Point.measurement(measurement)
619+
.setTag("type", "test")
620+
.setFloatField("rads", 3.14)
621+
.setIntegerField("life", 12)
622+
.setTimestamp(Instant.now().plusSeconds(1).getEpochSecond(), WritePrecision.S),
623+
Point.measurement(measurement)
624+
.setTag("type", "test")
625+
.setFloatField("rads", 3.14)
626+
.setIntegerField("life", 432)
627+
.setTimestamp(Instant.now().plusSeconds(2).toEpochMilli() * 1000, WritePrecision.US)
628+
);
629+
client.writePoints(points, writeOptions);
630+
var results = client.queryPoints(String.format("select * from \"%s\"", measurement))
631+
.collect(Collectors.toList());
632+
Assertions.assertThat(results).hasSize(3);
633+
}
634+
}
602635

603636
private void assertGetDataSuccess(@Nonnull final InfluxDBClient influxDBClient) {
604637
influxDBClient.writePoint(

0 commit comments

Comments
 (0)