using System; using System.Collections.Generic; using System.Net.Http; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using InfluxDB.Client.Api.Domain; using InfluxDB.Client.Api.Service; using InfluxDB.Client.Core; using InfluxDB.Client.Core.Flux.Domain; using InfluxDB.Client.Core.Flux.Internal; using InfluxDB.Client.Core.Internal; using RestSharp; namespace InfluxDB.Client { public interface IQueryApi { /// /// Executes the Flux query against the InfluxDB 2.x and synchronously map whole response /// to s. /// /// /// NOTE: This method is not intended for large query results. /// Use /// for large data streaming. /// /// /// the flux query to execute /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// FluxTables that are matched the query Task> QueryAsync(string query, string org = null, CancellationToken cancellationToken = default); /// /// Executes the Flux query against the InfluxDB 2.x and synchronously map whole response /// to s. /// /// /// NOTE: This method is not intended for large query results. /// Use /// for large data streaming. /// /// /// the flux query to execute /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// FluxTables that are matched the query Task> QueryAsync(Query query, string org = null, CancellationToken cancellationToken = default); /// /// Executes the Flux query against the InfluxDB 2.x and synchronously map whole response /// to list of object with given type. /// /// /// NOTE: This method is not intended for large query results. /// Use /// for large data streaming. /// /// /// the flux query to execute /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// the type of measurement /// Measurements which are matched the query Task> QueryAsync(string query, string org = null, CancellationToken cancellationToken = default); /// /// Executes the Flux query against the InfluxDB 2.x and synchronously map whole response /// to list of object with given type. /// /// /// NOTE: This method is not intended for large query results. /// Use /// for large data streaming. /// /// /// the flux query to execute /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// the type of measurement /// Measurements which are matched the query Task> QueryAsync(Query query, string org = null, CancellationToken cancellationToken = default); /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously stream /// to consumer. /// /// the flux query to execute /// the callback to consume the FluxRecord result /// the callback to consume any error notification /// the callback to consume a notification about successfully end of stream /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// async task Task QueryAsync(string query, Action onNext, Action onError = null, Action onComplete = null, string org = null, CancellationToken cancellationToken = default); /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously stream /// to consumer. /// /// the flux query to execute /// the callback to consume the FluxRecord result /// the callback to consume any error notification /// the callback to consume a notification about successfully end of stream /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// async task Task QueryAsync(Query query, Action onNext, Action onError = null, Action onComplete = null, string org = null, CancellationToken cancellationToken = default); /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously stream Measurements /// to a consumer. /// /// the flux query to execute /// the callback to consume the mapped Measurements /// the callback to consume any error notification /// the callback to consume a notification about successfully end of stream /// specifies the source organization /// Token that enables callers to cancel the request. /// the type of measurement /// async task Task QueryAsync(string query, Action onNext, Action onError = null, Action onComplete = null, string org = null, CancellationToken cancellationToken = default); /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously stream Measurements /// to a consumer. /// /// the flux query to execute /// the callback to consume the mapped Measurements /// the callback to consume any error notification /// the callback to consume a notification about successfully end of stream /// specifies the source organization /// Token that enables callers to cancel the request. /// the type of measurement /// async task Task QueryAsync(Query query, Action onNext, Action onError = null, Action onComplete = null, string org = null, CancellationToken cancellationToken = default); /// /// Executes the Flux query against the InfluxDB 2.x and synchronously map whole response /// to list of object with given type. /// /// /// NOTE: This method is not intended for large query results. /// Use /// for large data streaming. /// /// /// the flux query to execute /// the type of measurement /// the organization /// Token that enables callers to cancel the request. /// Measurements which are matched the query Task> QueryAsync(string query, Type pocoType, string org = null, CancellationToken cancellationToken = default); /// /// Executes the Flux query against the InfluxDB 2.x and synchronously map whole response /// to list of object with given type. /// /// /// NOTE: This method is not intended for large query results. /// Use /// for large data streaming. /// /// /// the flux query to execute /// the type of measurement /// the organization /// Token that enables callers to cancel the request. /// Measurements which are matched the query Task> QueryAsync(Query query, Type pocoType, string org = null, CancellationToken cancellationToken = default); /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously stream Measurements /// to a consumer. /// /// the flux query to execute /// the type of measurement /// the callback to consume the mapped Measurements /// the callback to consume any error notification /// the callback to consume a notification about successfully end of stream /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// async task Task QueryAsync(string query, Type pocoType, Action onNext, Action onError = null, Action onComplete = null, string org = null, CancellationToken cancellationToken = default); /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously stream Measurements /// to a consumer. /// /// the flux query to execute /// the type of measurement /// the callback to consume the mapped Measurements /// the callback to consume any error notification /// the callback to consume a notification about successfully end of stream /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// async task Task QueryAsync(Query query, Type pocoType, Action onNext, Action onError = null, Action onComplete = null, string org = null, CancellationToken cancellationToken = default); /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously maps /// response to enumerable of objects of type . /// /// the flux query to execute /// specifies the source organization. If the org is not specified then is used config from . /// cancellation token /// the type of measurement /// Measurements which are matched the query IAsyncEnumerable QueryAsyncEnumerable(string query, string org = null, CancellationToken cancellationToken = default); /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously maps /// response to enumerable of objects of type . /// /// the flux query to execute /// specifies the source organization. If the org is not specified then is used config from . /// cancellation token /// the type of measurement /// Measurements which are matched the query IAsyncEnumerable QueryAsyncEnumerable(Query query, string org = null, CancellationToken cancellationToken = default); /// /// Executes the Flux query against the InfluxDB and synchronously map whole response to result. /// /// /// NOTE: This method is not intended for large query results. /// Use /// for large data streaming. /// /// /// /// the flux query to execute /// Dialect is an object defining the options to use when encoding the response. See dialect SPEC. /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// the raw response that matched the query Task QueryRawAsync(string query, Dialect dialect = null, string org = null, CancellationToken cancellationToken = default); /// /// Executes the Flux query against the InfluxDB and synchronously map whole response to result. /// /// /// NOTE: This method is not intended for large query results. /// Use /// for large data streaming. /// /// /// /// the flux query to execute /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// the raw response that matched the query Task QueryRawAsync(Query query, string org = null, CancellationToken cancellationToken = default); /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously stream response /// (line by line) to . /// /// the flux query to execute /// the callback to consume the response line by line /// Dialect is an object defining the options to use when encoding the response. See dialect SPEC. /// callback to consume any error notification /// callback to consume a notification about successfully end of stream /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// Task QueryRawAsync(string query, Action onResponse, Dialect dialect = null, Action onError = null, Action onComplete = null, string org = null, CancellationToken cancellationToken = default); /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously stream response /// (line by line) to . /// /// the flux query to execute /// the callback to consume the response line by line /// callback to consume any error notification /// callback to consume a notification about successfully end of stream /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// Task QueryRawAsync(Query query, Action onResponse, Action onError = null, Action onComplete = null, string org = null, CancellationToken cancellationToken = default); } public class QueryApi : AbstractQueryClient, IQueryApi { public static readonly Dialect Dialect = new Dialect { Header = true, Delimiter = ",", CommentPrefix = "#", Annotations = new List { Dialect.AnnotationsEnum.Datatype, Dialect.AnnotationsEnum.Group, Dialect.AnnotationsEnum.Default } }; private readonly InfluxDBClientOptions _options; private readonly QueryService _service; protected internal QueryApi(InfluxDBClientOptions options, QueryService service, IFluxResultMapper mapper) : base(mapper) { Arguments.CheckNotNull(options, nameof(options)); Arguments.CheckNotNull(service, nameof(service)); _options = options; _service = service; RestClient = service.Configuration.ApiClient.RestClient; } /// /// Executes the Flux query against the InfluxDB 2.x and synchronously map whole response /// to s. /// /// /// NOTE: This method is not intended for large query results. /// Use /// for large data streaming. /// /// /// the flux query to execute /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// FluxTables that are matched the query public Task> QueryAsync(string query, string org = null, CancellationToken cancellationToken = default) { Arguments.CheckNonEmptyString(query, nameof(query)); return QueryAsync(CreateQuery(query, Dialect), org, cancellationToken); } /// /// Executes the Flux query against the InfluxDB 2.x and synchronously map whole response /// to s. /// /// /// NOTE: This method is not intended for large query results. /// Use /// for large data streaming. /// /// /// the flux query to execute /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// FluxTables that are matched the query public async Task> QueryAsync(Query query, string org = null, CancellationToken cancellationToken = default) { Arguments.CheckNotNull(query, nameof(query)); var consumer = new FluxCsvParser.FluxResponseConsumerTable(); await QueryAsync(query, consumer, ErrorConsumer, EmptyAction, org, cancellationToken) .ConfigureAwait(false); return consumer.Tables; } /// /// Executes the Flux query against the InfluxDB 2.x and synchronously map whole response /// to list of object with given type. /// /// /// NOTE: This method is not intended for large query results. /// Use /// for large data streaming. /// /// /// the flux query to execute /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// the type of measurement /// Measurements which are matched the query public Task> QueryAsync(string query, string org = null, CancellationToken cancellationToken = default) { Arguments.CheckNonEmptyString(query, nameof(query)); return QueryAsync(CreateQuery(query), org, cancellationToken); } /// /// Executes the Flux query against the InfluxDB 2.x and synchronously map whole response /// to list of object with given type. /// /// /// NOTE: This method is not intended for large query results. /// Use /// for large data streaming. /// /// /// the flux query to execute /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// the type of measurement /// Measurements which are matched the query public async Task> QueryAsync(Query query, string org = null, CancellationToken cancellationToken = default) { Arguments.CheckNotNull(query, nameof(query)); var measurements = new List(); var consumer = new FluxResponseConsumerPoco(poco => { measurements.Add(poco); }, Mapper); await QueryAsync(query, consumer, ErrorConsumer, EmptyAction, org, cancellationToken) .ConfigureAwait(false); return measurements; } /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously maps /// response to enumerable of objects of type . /// /// the flux query to execute /// specifies the source organization. If the org is not specified then is used config from . /// cancellation token /// the type of measurement /// Measurements which are matched the query public async IAsyncEnumerable QueryAsyncEnumerable(string query, string org = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) { Arguments.CheckNonEmptyString(query, nameof(query)); var requestMessage = CreateRequest(CreateQuery(query), org); await foreach (var record in QueryEnumerable(requestMessage, it => Mapper.ConvertToEntity(it), cancellationToken).ConfigureAwait(false)) yield return record; } /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously maps /// response to enumerable of objects of type . /// /// the flux query to execute /// specifies the source organization. If the org is not specified then is used config from . /// cancellation token /// the type of measurement /// Measurements which are matched the query public async IAsyncEnumerable QueryAsyncEnumerable(Query query, string org = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) { Arguments.CheckNotNull(query, nameof(query)); var requestMessage = CreateRequest(query, org); await foreach (var record in QueryEnumerable(requestMessage, it => Mapper.ConvertToEntity(it), cancellationToken).ConfigureAwait(false)) yield return record; } /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously stream /// to consumer. /// /// the flux query to execute /// the callback to consume the FluxRecord result /// the callback to consume any error notification /// the callback to consume a notification about successfully end of stream /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// async task public Task QueryAsync(string query, Action onNext, Action onError = null, Action onComplete = null, string org = null, CancellationToken cancellationToken = default) { Arguments.CheckNonEmptyString(query, nameof(query)); Arguments.CheckNotNull(onNext, nameof(onNext)); var consumer = new FluxResponseConsumerRecord(onNext); return QueryAsync(CreateQuery(query, Dialect), consumer, onError, onComplete, org, cancellationToken); } /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously stream /// to consumer. /// /// the flux query to execute /// the callback to consume the FluxRecord result /// the callback to consume any error notification /// the callback to consume a notification about successfully end of stream /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// async task public Task QueryAsync(Query query, Action onNext, Action onError = null, Action onComplete = null, string org = null, CancellationToken cancellationToken = default) { Arguments.CheckNotNull(query, nameof(query)); Arguments.CheckNotNull(onNext, nameof(onNext)); var consumer = new FluxResponseConsumerRecord(onNext); return QueryAsync(query, consumer, onError, onComplete, org, cancellationToken); } /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously stream Measurements /// to a consumer. /// /// the flux query to execute /// the callback to consume the mapped Measurements /// the callback to consume any error notification /// the callback to consume a notification about successfully end of stream /// specifies the source organization /// Token that enables callers to cancel the request. /// the type of measurement /// async task public Task QueryAsync(string query, Action onNext, Action onError = null, Action onComplete = null, string org = null, CancellationToken cancellationToken = default) { Arguments.CheckNonEmptyString(query, nameof(query)); Arguments.CheckNotNull(onNext, nameof(onNext)); var consumer = new FluxResponseConsumerPoco(onNext, Mapper); return QueryAsync(CreateQuery(query, Dialect), consumer, onError, onComplete, org, cancellationToken); } /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously stream Measurements /// to a consumer. /// /// the flux query to execute /// the callback to consume the mapped Measurements /// the callback to consume any error notification /// the callback to consume a notification about successfully end of stream /// specifies the source organization /// Token that enables callers to cancel the request. /// the type of measurement /// async task public Task QueryAsync(Query query, Action onNext, Action onError = null, Action onComplete = null, string org = null, CancellationToken cancellationToken = default) { Arguments.CheckNotNull(query, nameof(query)); Arguments.CheckNotNull(onNext, nameof(onNext)); var consumer = new FluxResponseConsumerPoco(onNext, Mapper); return QueryAsync(query, consumer, onError, onComplete, org, cancellationToken); } /// /// Executes the Flux query against the InfluxDB 2.x and synchronously map whole response /// to list of object with given type. /// /// /// NOTE: This method is not intended for large query results. /// Use /// for large data streaming. /// /// /// the flux query to execute /// the type of measurement /// the organization /// Token that enables callers to cancel the request. /// Measurements which are matched the query public Task> QueryAsync(string query, Type pocoType, string org = null, CancellationToken cancellationToken = default) { return QueryAsync(CreateQuery(query), pocoType, org, cancellationToken); } /// /// Executes the Flux query against the InfluxDB 2.x and synchronously map whole response /// to list of object with given type. /// /// /// NOTE: This method is not intended for large query results. /// Use /// for large data streaming. /// /// /// the flux query to execute /// the type of measurement /// the organization /// Token that enables callers to cancel the request. /// Measurements which are matched the query public async Task> QueryAsync(Query query, Type pocoType, string org = null, CancellationToken cancellationToken = default) { var measurements = new List(); var consumer = new FluxResponseConsumerPoco(poco => { measurements.Add(poco); }, Mapper, pocoType); await QueryAsync(query, consumer, ErrorConsumer, EmptyAction, org, cancellationToken) .ConfigureAwait(false); return measurements; } /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously stream Measurements /// to a consumer. /// /// the flux query to execute /// the type of measurement /// the callback to consume the mapped Measurements /// the callback to consume any error notification /// the callback to consume a notification about successfully end of stream /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// async task public Task QueryAsync(string query, Type pocoType, Action onNext, Action onError = null, Action onComplete = null, string org = null, CancellationToken cancellationToken = default) { return QueryAsync(CreateQuery(query, Dialect), pocoType, onNext, onError, onComplete, org, cancellationToken); } /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously stream Measurements /// to a consumer. /// /// the flux query to execute /// the type of measurement /// the callback to consume the mapped Measurements /// the callback to consume any error notification /// the callback to consume a notification about successfully end of stream /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// async task public Task QueryAsync(Query query, Type pocoType, Action onNext, Action onError = null, Action onComplete = null, string org = null, CancellationToken cancellationToken = default) { Arguments.CheckNotNull(query, nameof(query)); Arguments.CheckNotNull(onNext, nameof(onNext)); Arguments.CheckNotNull(onError, nameof(onError)); Arguments.CheckNotNull(onComplete, nameof(onComplete)); var consumer = new FluxResponseConsumerPoco(onNext, Mapper, pocoType); return QueryAsync(query, consumer, onError, onComplete, org, cancellationToken); } /// /// Executes the Flux query against the InfluxDB and synchronously map whole response to result. /// /// /// NOTE: This method is not intended for large query results. /// Use /// for large data streaming. /// /// /// /// the flux query to execute /// Dialect is an object defining the options to use when encoding the response. See dialect SPEC. /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// the raw response that matched the query public Task QueryRawAsync(string query, Dialect dialect = null, string org = null, CancellationToken cancellationToken = default) { Arguments.CheckNonEmptyString(query, nameof(query)); return QueryRawAsync(CreateQuery(query, dialect), org, cancellationToken); } /// /// Executes the Flux query against the InfluxDB and synchronously map whole response to result. /// /// /// NOTE: This method is not intended for large query results. /// Use /// for large data streaming. /// /// /// /// the flux query to execute /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// the raw response that matched the query public async Task QueryRawAsync(Query query, string org = null, CancellationToken cancellationToken = default) { Arguments.CheckNotNull(query, nameof(query)); var rows = new List(); void Consumer(string row) { rows.Add(row); } await QueryRawAsync(query, Consumer, ErrorConsumer, EmptyAction, org, cancellationToken) .ConfigureAwait(false); return string.Join("\n", rows); } /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously stream response /// (line by line) to . /// /// the flux query to execute /// the callback to consume the response line by line /// Dialect is an object defining the options to use when encoding the response. See dialect SPEC. /// callback to consume any error notification /// callback to consume a notification about successfully end of stream /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// public Task QueryRawAsync(string query, Action onResponse, Dialect dialect = null, Action onError = null, Action onComplete = null, string org = null, CancellationToken cancellationToken = default) { Arguments.CheckNonEmptyString(query, nameof(query)); Arguments.CheckNotNull(onResponse, nameof(onResponse)); return QueryRawAsync(CreateQuery(query, dialect), onResponse, onError, onComplete, org, cancellationToken); } /// /// Executes the Flux query against the InfluxDB 2.x and asynchronously stream response /// (line by line) to . /// /// the flux query to execute /// the callback to consume the response line by line /// callback to consume any error notification /// callback to consume a notification about successfully end of stream /// specifies the source organization. If the org is not specified then is used config from . /// Token that enables callers to cancel the request. /// public Task QueryRawAsync(Query query, Action onResponse, Action onError = null, Action onComplete = null, string org = null, CancellationToken cancellationToken = default) { Arguments.CheckNotNull(query, nameof(query)); Arguments.CheckNotNull(onResponse, nameof(onResponse)); var requestMessage = CreateRequest(query, org); return QueryRaw(requestMessage, onResponse, onError, onComplete, cancellationToken); } protected override void BeforeIntercept(RestRequest request) { _service.Configuration.ApiClient.BeforeIntercept(request); } protected override T AfterIntercept(int statusCode, Func> headers, T body) { return _service.Configuration.ApiClient.AfterIntercept(statusCode, headers, body); } private Task QueryAsync(Query query, FluxCsvParser.IFluxResponseConsumer consumer, Action onError = null, Action onComplete = null, string org = null, CancellationToken cancellationToken = default) { Arguments.CheckNotNull(query, nameof(query)); Arguments.CheckNotNull(consumer, nameof(consumer)); var requestMessage = CreateRequest(query, org); return Query(requestMessage, consumer, onError ?? ErrorConsumer, onComplete ?? EmptyAction, cancellationToken); } private Func, RestRequest> CreateRequest(Query query, string org = null) { Arguments.CheckNotNull(query, nameof(query)); var optionsOrg = org ?? _options.Org; Arguments.CheckNonEmptyString(optionsOrg, OrgArgumentValidation); return advancedResponseWriter => _service .PostQueryWithRestRequest(null, "application/json", null, optionsOrg, null, query) .AddAdvancedResponseHandler(advancedResponseWriter); } internal static Query CreateQuery(string query, Dialect dialect = null) { Arguments.CheckNonEmptyString(query, nameof(query)); var created = new Query(query: query, dialect: dialect ?? Dialect); return created; } } }