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: updates service accept header to application/json #733

Merged
merged 16 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
## 7.2.0 [unreleased]

### Features

- [#719](https://github.com/influxdata/influxdb-client-java/issues/719): `InfluxQLQueryService` header changes.
- `Accept` header can now be defined when making `InfluxQLQuery` calls. Supoorted MIME types:
- `application/csv`
- `application/json`
- The value `application/csv` remains the default.
- :warning: Side effects of these changes:
- When using `application/json`, timestamp fields are returned in the [RFC3339](https://www.rfc-editor.org/rfc/rfc3339) format unless `InfluxQLQuery.setPrecision()` has been previously called, in which case they are returned in the POSIX epoch format.
- When using `application/csv`, timestamp fields are returned in the POSIX epoch format.
- Convenience methods have been added to `InfluxQLQueryAPI` to simplify expressly specifying JSON or CSV calls.
- Epoch timestamps can also be ensured by calling `InfluxQLQuery.setPrecision()` before executing a query call.
- An `AcceptHeader` field has also been added to the `InfluxQLQuery` class and can be set with `InfluxQLQuery.setAcceptHeader()`.
- More information from the server side:
- [Generated REST API Documentation](https://docs.influxdata.com/influxdb/v2/api/v1-compatibility/#operation/PostQueryV1)
- [Influx 1.1 query compatibility](https://docs.influxdata.com/influxdb/latest/reference/api/influxdb-1x/query/)
- See the updated InfluxQLExample

### Bug Fixes

1. [#744](https://github.com/influxdata/influxdb-client-java/issues/744) following an `InfluxQLQueryAPI.query()` call, empty results from the server no longer result in a `null` result value.

### Dependencies

Update dependencies:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,21 @@ protected void query(@Nonnull final Call<ResponseBody> query,
Consumer<ResponseBody> bodyConsumer = body -> {
try {
BufferedSource source = body.source();

//
// Source has data => parse
//
while (source.isOpen() && !source.exhausted() && !cancellable.wasCancelled) {

// already exhausted - empty or very short response
if (source.exhausted()) {
LOG.log(Level.WARNING, String.format("Query %s already exhausted.",
query.request().tag(retrofit2.Invocation.class)
.toString().split(" \\[")[1]
.replace("]", "")));
consumer.accept(cancellable, source);
} else {

//
// Source has data => parse
//
while (source.isOpen() && !source.exhausted() && !cancellable.wasCancelled) {
consumer.accept(cancellable, source);
}
}

if (!cancellable.wasCancelled) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,6 @@ public Object[] getValues() {
return values;
}
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ public interface InfluxQLQueryService {
* @param zapTraceSpan OpenTracing span context (optional)
* @return response in csv format
*/
@Headers({"Accept:application/csv", "Content-Type:application/x-www-form-urlencoded"})
@Headers({"Content-Type:application/x-www-form-urlencoded"})
@FormUrlEncoded
@POST("query")
Call<ResponseBody> query(
@Field("q") String query,
@Nonnull @Query("db") String db,
@Query("rp") String retentionPolicy,
@Query("epoch") String epoch,
@Header("Zap-Trace-Span") String zapTraceSpan
@Header("Zap-Trace-Span") String zapTraceSpan,
@Header("Accept") String accept
);
}
76 changes: 75 additions & 1 deletion client/src/main/java/com/influxdb/client/InfluxQLQueryApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,34 @@
import com.influxdb.query.InfluxQLQueryResult;

/**
* The <code>InfluxQL</code> can be used with <code>/query compatibility</code> endpoint which uses the
* The <code>InfluxQL</code> API can be used with the <code>/query compatibility</code> endpoint which uses the
* <strong>{@link InfluxQLQuery#getDatabase() database}</strong> and
* <strong>{@link InfluxQLQuery#getRetentionPolicy() retention policy}</strong> specified in the query request to
* map the request to an InfluxDB bucket.
*
* <p>Note that as of release 7.2 queries using the legacy <code>InfluxQL</code> compatible endpoint can specify
* the <code>Accept</code> header MIME type. Two MIME types are supported. </p>
* <ul>
* <li><code>application/csv</code> - client default and legacy value.</li>
* <li><code>application/json</code></li>
* </ul>
*
* <p>The selected <code>Accept</code> header mime type impacts the timestamp format returned from the server.</p>
* <ul>
* <li><code>application/csv</code> returns timestamps in the POSIX epoch format.</li>
* <li><code>application/json</code> returns timestamps as RFC3339 strings.
* <ul>
* <li>Caveat. If <code>InfluxQLQuery.setPrecision()</code> is called before the query is sent, then
* the timestamp will be returned as a POSIX epoch reflecting the desired precision, even when using the
* <code>application/json</code> MIME type.</li>
* </ul>
* </li>
* </ul>
*
* <p>To explicitly choose one or the other MIME type new convenience methods are povided: <code>queryCSV</code>
* and <code>queryJSON</code>. Note that the <code>Accept</code> header MIME type can now also be specified
* when instantiating the {@link com.influxdb.client.domain.InfluxQLQuery} class.</p>
*
* <br>
* For more information, see:
* <ul>
Expand All @@ -46,6 +70,11 @@
* Database and retention policy mapping
* </a>
* </li>
* <li>
* <a href="https://docs.influxdata.com/influxdb/v2/api/v1-compatibility/#operation/PostQueryV1">
* OpenApi generated definitions
* </a>
* </li>
* </ul>
**/
@ThreadSafe
Expand Down Expand Up @@ -92,4 +121,49 @@ InfluxQLQueryResult query(
@Nonnull InfluxQLQuery influxQlQuery,
@Nullable InfluxQLQueryResult.Series.ValueExtractor valueExtractor
);

/**
* Convenience method to specify use of the mime type <code>application/csv</code>
* in the <code>Accept</code> header. Result timestamps will be in the Epoch format.
*
* @param influxQLQuery the query
* @return the result
*/
@Nonnull
InfluxQLQueryResult queryCSV(@Nonnull final InfluxQLQuery influxQLQuery);

/**
* Convenience method to specify use of the mime type <code>application/csv</code>
* in the <code>Accept</code> header. Result timestamps will be in the Epoch format.
*
* @param influxQLQuery the query
* @param valueExtractor a callback, to convert column values
* @return the result
*/
InfluxQLQueryResult queryCSV(@Nonnull final InfluxQLQuery influxQLQuery,
@Nullable InfluxQLQueryResult.Series.ValueExtractor valueExtractor);

/**
* Convenience method to specify use of the mime type <code>application/json</code>
* in the <code>Accept</code> header. Result timestamps will be in the RFC3339 format.
*
* @param influxQLQuery the query
* @return the result
*/
@Nonnull
InfluxQLQueryResult queryJSON(@Nonnull final InfluxQLQuery influxQLQuery);

/**
* Convenience method to specify use of the mime type <code>application/json</code>
* in the <code>Accept</code> header. Result timestamps will be in the RFC3339 format.
*
* @param influxQLQuery the query
* @param valueExtractor a callback, to convert column values
* @return the result
*/
@Nonnull
InfluxQLQueryResult queryJSON(@Nonnull final InfluxQLQuery influxQLQuery,
@Nullable InfluxQLQueryResult.Series.ValueExtractor valueExtractor);


}
57 changes: 57 additions & 0 deletions client/src/main/java/com/influxdb/client/domain/InfluxQLQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@
* A InfluxQL query.
*/
public class InfluxQLQuery {

private final String command;
private final String database;
private String retentionPolicy;
private InfluxQLPrecision precision;
private AcceptHeader acceptHeader;

/**
* @param command the InfluxQL command to execute
Expand All @@ -42,6 +44,20 @@ public class InfluxQLQuery {
public InfluxQLQuery(@Nonnull final String command, @Nonnull final String database) {
this.command = command;
this.database = database;
this.acceptHeader = AcceptHeader.CSV;
}

/**
* @param command the InfluxQL command to execute
* @param database the database to run this query against
* @param acceptHeader the <code>Accept</code> header to use in the request
*/
public InfluxQLQuery(@Nonnull final String command,
@Nonnull final String database,
@Nonnull final AcceptHeader acceptHeader) {
this.command = command;
this.database = database;
this.acceptHeader = acceptHeader;
}

/**
Expand Down Expand Up @@ -97,6 +113,29 @@ public InfluxQLQuery setPrecision(@Nullable final InfluxQLPrecision precision) {
return this;
}

/**
* @return the current AcceptHeader used when making queries.
*/
public AcceptHeader getAcceptHeader() {
return acceptHeader;
}

/***
* @param acceptHeader the AcceptHeader to be used when making queries.
* @return this
*/
public InfluxQLQuery setAcceptHeader(final AcceptHeader acceptHeader) {
this.acceptHeader = acceptHeader;
return this;
}

/**
* @return the string value of the AcceptHeader used when making queries.
*/
public String getAcceptHeaderVal() {
return acceptHeader != null ? acceptHeader.getVal() : AcceptHeader.CSV.getVal();
}

/**
* The precision used for the timestamps returned by InfluxQL queries.
*/
Expand Down Expand Up @@ -143,4 +182,22 @@ public static InfluxQLPrecision toTimePrecision(final TimeUnit t) {
}
}
}

/**
* The possible values to be used in the header <code>Accept</code>, when making queries.
*/
public enum AcceptHeader {
JSON("application/json"),
CSV("application/csv");

private final String val;

AcceptHeader(final String val) {
this.val = val;
}

public String getVal() {
return val;
}
}
}
Loading