influxdb 0.5.3 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8d85c5412cee2eed247a9dc36cdd93063dab1006
4
- data.tar.gz: fb4ea80422af475ec2af1d94918e7682a424537d
2
+ SHA256:
3
+ metadata.gz: c280c4f839a7d00e2c716226f06987df217edebbf7149bf309906b8b34ea2e26
4
+ data.tar.gz: 3dc453ebb5a914de3e364da388255d7d38e266a468dce14dc9a7e5f9e7a2b273
5
5
  SHA512:
6
- metadata.gz: 738b8b9a2ce516b1957c4afcdf7a4ab2ef710ddb088bd711ef55f815f11d57a1422bbc67db1d83574fb81ae98441c70d12c4c8a8cfe7bbc3029724d5c3156dae
7
- data.tar.gz: d70c7129fc4e0f4a7a3b5732826128f168dedd3dcabfe7affdc5816c6c2718fea289368d3d3749aa6956deec7d899ebf9e5334af93293eed38e22635a5ff4e4b
6
+ metadata.gz: b4b0f7d6475d31e3506e4c3979548c56cd70bd9c632ba77b6d3a8fae26cc3b2885c34662848ed1096a456b2156347c8f6b8b7746ca5b68cd170f877d6b5409c4
7
+ data.tar.gz: 72a5903843c25150e2daf01c31f57f3636a3f7730183704c111a6c6be5c42ed84cd42970087087292328f6ecce7ffa20313a87e09644b8199eadcd639f5c6733
data/.gitignore CHANGED
@@ -21,3 +21,5 @@ Gemfile.lock
21
21
  _yardoc
22
22
  doc/
23
23
  *.local
24
+
25
+ /noaa.txt
@@ -40,6 +40,9 @@ Metrics/ModuleLength:
40
40
  Metrics/ParameterLists:
41
41
  Max: 6
42
42
 
43
+ Naming/UncommunicativeMethodParamName:
44
+ AllowedNames: [io, id, db]
45
+
43
46
  Style/FormatStringToken:
44
47
  Enabled: false
45
48
 
@@ -55,8 +58,12 @@ Style/RescueModifier:
55
58
  Style/StringLiterals:
56
59
  Enabled: false
57
60
 
58
- Style/TrailingCommaInLiteral:
61
+ Style/TrailingCommaInArrayLiteral:
59
62
  EnforcedStyleForMultiline: comma
60
63
  Exclude:
61
64
  - "spec/**/*.rb"
62
65
 
66
+ Style/TrailingCommaInHashLiteral:
67
+ EnforcedStyleForMultiline: comma
68
+ Exclude:
69
+ - "spec/**/*.rb"
@@ -7,9 +7,10 @@ before_install:
7
7
  - gem update bundler --no-doc
8
8
  - bin/provision.sh
9
9
  rvm:
10
- - 2.2.8
11
- - 2.3.5
12
- - 2.4.2
10
+ - 2.2.9
11
+ - 2.3.7
12
+ - 2.4.4
13
+ - 2.5.1
13
14
  - ruby-head
14
15
  env:
15
16
  - TEST_TASK=spec
@@ -19,25 +20,27 @@ matrix:
19
20
  - rvm: jruby-head
20
21
  - rvm: ruby-head
21
22
  - rvm: jruby-9.1.5.0
22
- - rvm: 2.4.2
23
+ - rvm: 2.5.1
23
24
  env: influx_version=nightly channel=nightlies
24
25
  include:
25
- - rvm: 2.4.2
26
+ - rvm: 2.5.1
26
27
  env: TEST_TASK=rubocop
27
28
  - rvm: jruby-9.1.5.0
28
29
  - rvm: jruby-head
29
30
  env: JRUBY_OPTS='--client -J-XX:+TieredCompilation -J-XX:TieredStopAtLevel=1 -J-Xss2m -J-Xmx256M'
30
- - rvm: 2.4.2
31
+ - rvm: 2.5.1
31
32
  env: influx_version=1.0.2 pkghash=3e4c349cb57507913d9abda1459bdbed
32
- - rvm: 2.4.2
33
+ - rvm: 2.5.1
33
34
  env: influx_version=1.1.0 pkghash=682904c350ecfc2a60ec9c6c08453ef2
34
- - rvm: 2.4.2
35
+ - rvm: 2.5.1
35
36
  env: influx_version=1.2.4 pkghash=0545d67217393282188e5d5cdedfdc85
36
- - rvm: 2.4.2
37
+ - rvm: 2.5.1
37
38
  env: influx_version=1.3.6 pkghash256=6406cdd21466bcb832b967078adaa9f07cb6ae524a6579c15141692031f5f840
38
- - rvm: 2.4.2
39
- env: influx_version=1.4.2 pkghash256=96ced90cfc436da7833721fd635b9942f9175cff2f897c113ef068f224cf8605
40
- - rvm: 2.4.2
39
+ - rvm: 2.5.1
40
+ env: influx_version=1.4.3 pkghash256=0477080f1d1cf8e1242dc7318280b9010c4c45cf6a415a2a5de607ae17fa0359
41
+ - rvm: 2.5.1
42
+ env: influx_version=1.5.2 pkghash256=42fede7b497bdf30d4eb5138db218d1add986fca4fce4a8bcd9c7d6dabaf572a
43
+ - rvm: 2.5.1
41
44
  env: influx_version=nightly channel=nightlies
42
45
  fail_fast: true
43
46
  addons:
@@ -2,9 +2,14 @@
2
2
 
3
3
  For the full commit log, [see here](https://github.com/influxdata/influxdb-ruby/commits/master).
4
4
 
5
- ## Unreleased changes
5
+ ## v0.6.0, released 2018-07-10
6
6
 
7
- - None.
7
+ - Add batch query support via `InfluxDB::Client#batch` (and using
8
+ `InfluxDB::Query::Batch`). Using multiple queries joined with `;`
9
+ will cause issues with `Client#query` in combination with either
10
+ `GROUP BY` clauses or empty results, as discussed in #217.
11
+
12
+ Initial code and PR#218 from @satyanash.
8
13
 
9
14
  ## v0.5.3, released 2018-01-19
10
15
 
data/README.md CHANGED
@@ -161,9 +161,7 @@ this, your points will be squashed!**
161
161
  > field set and the new field set, where any ties go to the new field set. This
162
162
  > is the intended behavior.
163
163
 
164
- See [How does InfluxDB handle duplicate
165
- points?](https://docs.influxdata.com/influxdb/v1.3/troubleshooting/frequently-asked-questions/#how-does-influxdb-handle-duplicate-points)
166
- for details.
164
+ See [How does InfluxDB handle duplicate points?][docs-faq] for details.
167
165
 
168
166
  For example, this is how to specify millisecond precision (which moves the
169
167
  pitfall from the second- to the millisecond barrier):
@@ -172,7 +170,7 @@ pitfall from the second- to the millisecond barrier):
172
170
  influxdb = InfluxDB::Client.new(time_precision: "ms")
173
171
  time = (Time.now.to_r * 1000).to_i
174
172
  # A faster, albeit less readable alternative:
175
- # time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
173
+ # time = Process.clock_gettime(Process::CLOCK_REALTIME, :millisecond)
176
174
  influxdb.write_point("foobar", { values: { n: 42 }, timestamp: time })
177
175
  ```
178
176
 
@@ -682,8 +680,7 @@ influxdb = InfluxDB::Client.new database,
682
680
  chunk_size: 10000
683
681
  ```
684
682
 
685
- See the [official documentation](http://docs.influxdata.com/influxdb/v0.13/guides/querying_data/#chunking)
686
- for more details.
683
+ See the [official documentation][docs-chunking] for more details.
687
684
 
688
685
 
689
686
  #### Retry
data/Rakefile CHANGED
@@ -21,7 +21,7 @@ else
21
21
  end
22
22
 
23
23
  task :console do
24
- lib = File.expand_path("../lib", __FILE__)
24
+ lib = File.expand_path("lib", __dir__)
25
25
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
26
26
  require "influxdb"
27
27
 
@@ -1,4 +1,4 @@
1
- lib = File.expand_path('../lib', __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
  require 'influxdb/version'
4
4
 
@@ -8,13 +8,16 @@ require "influxdb/config"
8
8
  require "influxdb/writer/async"
9
9
  require "influxdb/writer/udp"
10
10
 
11
- require "influxdb/query/core"
11
+ require "influxdb/query/batch"
12
+ require "influxdb/query/builder"
12
13
  require "influxdb/query/cluster"
13
- require "influxdb/query/database"
14
- require "influxdb/query/user"
15
14
  require "influxdb/query/continuous_query"
15
+ require "influxdb/query/core"
16
+ require "influxdb/query/core"
17
+ require "influxdb/query/database"
16
18
  require "influxdb/query/retention_policy"
17
19
  require "influxdb/query/series"
20
+ require "influxdb/query/user"
18
21
 
19
22
  require "influxdb/client/http"
20
23
  require "influxdb/client"
@@ -30,18 +30,18 @@ module InfluxDB
30
30
 
31
31
  private_constant :ESCAPES
32
32
 
33
- def escape(s, type)
33
+ def escape(str, type)
34
34
  # rubocop:disable Layout/AlignParameters
35
- s = s.encode "UTF-8".freeze, "UTF-8".freeze,
35
+ str = str.encode "UTF-8".freeze, "UTF-8".freeze,
36
36
  invalid: :replace,
37
37
  undef: :replace,
38
38
  replace: "".freeze
39
39
  # rubocop:enable Layout/AlignParameters
40
40
 
41
41
  ESCAPES[type].each do |ch|
42
- s = s.gsub(ch) { "\\#{ch}" }
42
+ str = str.gsub(ch) { "\\#{ch}" }
43
43
  end
44
- s
44
+ str
45
45
  end
46
46
 
47
47
  def escape_values(values)
@@ -0,0 +1,91 @@
1
+ module InfluxDB
2
+ module Query
3
+ # Batch collects multiple queries and executes them together.
4
+ #
5
+ # You shouldn't use Batch directly, instead call Client.batch, which
6
+ # constructs a new batch for you.
7
+ class Batch
8
+ attr_reader :client, :statements
9
+
10
+ def initialize(client)
11
+ @client = client
12
+ @statements = []
13
+
14
+ yield self if block_given?
15
+ end
16
+
17
+ def add(query, params: nil)
18
+ statements << client.builder.build(query.chomp(";"), params)
19
+ statements.size - 1
20
+ end
21
+
22
+ def execute(
23
+ denormalize: config.denormalize,
24
+ chunk_size: config.chunk_size,
25
+ **opts,
26
+ &block
27
+ )
28
+ return [] if statements.empty?
29
+
30
+ url = full_url "/query".freeze, query_params(statements.join(";"), opts)
31
+ series = fetch_series get(url, parse: true, json_streaming: !chunk_size.nil?)
32
+
33
+ if denormalize
34
+ build_denormalized_result(series, &block)
35
+ else
36
+ build_result(series, &block)
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def build_result(series)
43
+ return series.values unless block_given?
44
+
45
+ series.each do |id, statement_results|
46
+ statement_results.each do |s|
47
+ yield id, s["name".freeze], s["tags".freeze], raw_values(s)
48
+ end
49
+
50
+ # indicate empty result: yield useful amount of "nothing"
51
+ yield id, nil, {}, [] if statement_results.empty?
52
+ end
53
+ end
54
+
55
+ def build_denormalized_result(series)
56
+ return series.map { |_, s| denormalized_series_list(s) } unless block_given?
57
+
58
+ series.each do |id, statement_results|
59
+ statement_results.each do |s|
60
+ yield id, s["name".freeze], s["tags".freeze], denormalize_series(s)
61
+ end
62
+
63
+ # indicate empty result: yield useful amount of "nothing"
64
+ yield id, nil, {}, [] if statement_results.empty?
65
+ end
66
+ end
67
+
68
+ def fetch_series(response)
69
+ response.fetch("results".freeze).each_with_object({}) do |result, list|
70
+ sid = result["statement_id".freeze]
71
+ list[sid] = result.fetch("series".freeze, [])
72
+ end
73
+ end
74
+
75
+ # build simple method delegators
76
+ %i[
77
+ config
78
+ full_url
79
+ query_params
80
+ get
81
+ raw_values
82
+ denormalize_series
83
+ denormalized_series_list
84
+ ].each do |method_name|
85
+ define_method(method_name) do |*args|
86
+ client.send method_name, *args
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -1,3 +1,4 @@
1
+ require_relative 'batch'
1
2
  require_relative 'builder'
2
3
 
3
4
  module InfluxDB
@@ -37,7 +38,10 @@ module InfluxDB
37
38
  denormalize ? denormalized_series_list(series) : series
38
39
  end
39
40
  end
40
- # rubocop:enable Metrics/MethodLength
41
+
42
+ def batch(&block)
43
+ Batch.new self, &block
44
+ end
41
45
 
42
46
  # Example:
43
47
  # write_points([
@@ -82,11 +86,11 @@ module InfluxDB
82
86
  private
83
87
 
84
88
  def query_params(
85
- query,
86
- precision: config.time_precision,
87
- epoch: config.epoch,
88
- chunk_size: config.chunk_size,
89
- database: config.database
89
+ query,
90
+ precision: config.time_precision,
91
+ epoch: config.epoch,
92
+ chunk_size: config.chunk_size,
93
+ database: config.database
90
94
  )
91
95
  params = { q: query, db: database }
92
96
  params[:precision] = precision if precision
@@ -1,3 +1,3 @@
1
1
  module InfluxDB # :nodoc:
2
- VERSION = "0.5.3".freeze
2
+ VERSION = "0.6.0".freeze
3
3
  end
@@ -0,0 +1,150 @@
1
+ require "spec_helper"
2
+
3
+ describe InfluxDB::Client do
4
+ let :client do
5
+ described_class.new \
6
+ database: "database",
7
+ host: "influxdb.test",
8
+ port: 9999,
9
+ username: "username",
10
+ password: "password",
11
+ time_precision: "s"
12
+ end
13
+
14
+ describe "#batch" do
15
+ it { expect(client.batch).to be_a InfluxDB::Query::Batch }
16
+
17
+ describe "#execute" do
18
+ # it also doesn't perform a network request
19
+ it { expect(client.batch.execute).to eq [] }
20
+ end
21
+
22
+ describe "#add" do
23
+ let :queries do
24
+ [
25
+ "select * from foo",
26
+ "create user bar",
27
+ "drop measurement grok",
28
+ ]
29
+ end
30
+
31
+ it "returns statement id" do
32
+ batch = client.batch
33
+ ids = queries.map { |q| batch.add(q) }
34
+ expect(ids).to eq [0, 1, 2]
35
+ expect(batch.statements.size).to be 3
36
+ end
37
+
38
+ context "block form" do
39
+ it "returns statement id" do
40
+ batch = client.batch do |b|
41
+ ids = queries.map { |q| b.add(q) }
42
+ expect(ids).to eq [0, 1, 2]
43
+ end
44
+ expect(batch.statements.size).to be 3
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ describe "#batch.execute" do
51
+ context "with multiple queries when there is no data for a query" do
52
+ let :queries do
53
+ [
54
+ "SELECT value FROM requests_per_minute WHERE time > 1437019900",
55
+ "SELECT value FROM requests_per_minute WHERE time > now()",
56
+ "SELECT value FROM requests_per_minute WHERE time > 1437019900",
57
+ ]
58
+ end
59
+
60
+ subject do
61
+ client.batch do |b|
62
+ queries.each { |q| b.add(q) }
63
+ end
64
+ end
65
+
66
+ let :response do
67
+ { "results" => [{ "statement_id" => 0,
68
+ "series" => [{ "name" => "requests_per_minute",
69
+ "columns" => %w[time value],
70
+ "values" => [%w[2018-04-02T00:00:00Z 204]] }] },
71
+ { "statement_id" => 1 },
72
+ { "statement_id" => 2,
73
+ "series" => [{ "name" => "requests_per_minute",
74
+ "columns" => %w[time value],
75
+ "values" => [%w[2018-04-02T00:00:00Z 204]] }] }] }
76
+ end
77
+
78
+ let :expected_result do
79
+ [
80
+ [{ "name" => "requests_per_minute",
81
+ "tags" => nil,
82
+ "values" => [{ "time" => "2018-04-02T00:00:00Z",
83
+ "value" => "204" }] }],
84
+ [],
85
+ [{ "name" => "requests_per_minute",
86
+ "tags" => nil,
87
+ "values" => [{ "time" => "2018-04-02T00:00:00Z",
88
+ "value" => "204" }] }],
89
+ ]
90
+ end
91
+
92
+ before do
93
+ stub_request(:get, "http://influxdb.test:9999/query")
94
+ .with(query: hash_including(db: "database", precision: "s", u: "username", p: "password"))
95
+ .to_return(body: JSON.generate(response), status: 200)
96
+ end
97
+
98
+ it "should return responses for all statements" do
99
+ result = subject.execute
100
+ expect(result.length).to eq(response["results"].length)
101
+ expect(result).to eq expected_result
102
+ end
103
+ end
104
+
105
+ context "with a group by tag query" do
106
+ let :queries do
107
+ ["SELECT value FROM requests_per_minute WHERE time > now() - 1d GROUP BY status_code"]
108
+ end
109
+
110
+ subject do
111
+ client.batch { |b| queries.each { |q| b.add q } }
112
+ end
113
+
114
+ let :response do
115
+ { "results" => [{ "statement_id" => 0,
116
+ "series" => [{ "name" => "requests_per_minute",
117
+ "tags" => { "status_code" => "200" },
118
+ "columns" => %w[time value],
119
+ "values" => [%w[2018-04-02T00:00:00Z 204]] },
120
+ { "name" => "requests_per_minute",
121
+ "tags" => { "status_code" => "500" },
122
+ "columns" => %w[time value],
123
+ "values" => [%w[2018-04-02T00:00:00Z 204]] }] }] }
124
+ end
125
+
126
+ let :expected_result do
127
+ [[{ "name" => "requests_per_minute",
128
+ "tags" => { "status_code" => "200" },
129
+ "values" => [{ "time" => "2018-04-02T00:00:00Z",
130
+ "value" => "204" }] },
131
+ { "name" => "requests_per_minute",
132
+ "tags" => { "status_code" => "500" },
133
+ "values" => [{ "time" => "2018-04-02T00:00:00Z",
134
+ "value" => "204" }] }]]
135
+ end
136
+
137
+ before do
138
+ stub_request(:get, "http://influxdb.test:9999/query")
139
+ .with(query: hash_including(db: "database", precision: "s", u: "username", p: "password"))
140
+ .to_return(body: JSON.generate(response), status: 200)
141
+ end
142
+
143
+ it "should return a single result" do
144
+ result = subject.execute
145
+ expect(result.length).to eq(response["results"].length)
146
+ expect(result).to eq expected_result
147
+ end
148
+ end
149
+ end
150
+ end
@@ -3,16 +3,13 @@ require "json"
3
3
 
4
4
  describe InfluxDB::Client do
5
5
  let(:subject) do
6
- described_class.new(
7
- "database",
8
- {
9
- host: "influxdb.test",
10
- port: 9999,
11
- username: "username",
12
- password: "password",
13
- time_precision: "s"
14
- }.merge(args)
15
- )
6
+ described_class.new "database", {
7
+ host: "influxdb.test",
8
+ port: 9999,
9
+ username: "username",
10
+ password: "password",
11
+ time_precision: "s",
12
+ }.merge(args)
16
13
  end
17
14
 
18
15
  let(:args) { {} }
@@ -3,20 +3,15 @@ require "json"
3
3
 
4
4
  describe InfluxDB::Client do
5
5
  let(:subject) do
6
- described_class.new(
7
- "database",
8
- {
9
- host: "influxdb.test",
10
- port: 9999,
11
- username: "username",
12
- password: "password",
13
- time_precision: "s"
14
- }.merge(args)
15
- )
6
+ described_class.new \
7
+ database: "database",
8
+ host: "influxdb.test",
9
+ port: 9999,
10
+ username: "username",
11
+ password: "password",
12
+ time_precision: "s"
16
13
  end
17
14
 
18
- let(:args) { {} }
19
-
20
15
  describe "#list_continuous_queries" do
21
16
  let(:query) { "SHOW CONTINUOUS QUERIES" }
22
17
  let(:database) { "testdb" }
@@ -108,10 +103,10 @@ describe InfluxDB::Client do
108
103
  let(:name) { "event_counts_per_10m_by_type" }
109
104
  let(:database) { "testdb" }
110
105
  let(:query) { "DROP CONTINUOUS QUERY #{name} ON #{database}" }
106
+
111
107
  before do
112
- stub_request(:get, "http://influxdb.test:9999/query").with(
113
- query: { u: "username", p: "password", q: query }
114
- )
108
+ stub_request(:get, "http://influxdb.test:9999/query")
109
+ .with(query: { u: "username", p: "password", q: query })
115
110
  end
116
111
 
117
112
  it "should GET to remove continuous query" do
@@ -2,20 +2,19 @@ require "spec_helper"
2
2
 
3
3
  describe InfluxDB::Client do
4
4
  let(:subject) do
5
- described_class.new "database", {
6
- host: "influxdb.test",
7
- port: 9999,
8
- username: "username",
9
- password: "password",
5
+ described_class.new \
6
+ database: "database",
7
+ host: "influxdb.test",
8
+ port: 9999,
9
+ username: "username",
10
+ password: "password",
10
11
  time_precision: "s"
11
- }.merge(args)
12
12
  end
13
13
 
14
- let(:args) { {} }
15
-
16
14
  describe "#query" do
17
15
  let(:query) { "SELECT value FROM requests_per_minute WHERE time > 1437019900" }
18
- let(:response) do
16
+
17
+ let :response do
19
18
  { "results" => [{ "statement_id" => 0,
20
19
  "series" => [{ "name" => "requests_per_minute",
21
20
  "columns" => %w[time value] }] }] }
@@ -3,26 +3,22 @@ require "json"
3
3
 
4
4
  describe InfluxDB::Client do
5
5
  let(:subject) do
6
- described_class.new(
7
- "database",
8
- {
9
- host: "influxdb.test",
10
- port: 9999,
11
- username: "username",
12
- password: "password",
13
- time_precision: "s"
14
- }.merge(args)
15
- )
6
+ described_class.new \
7
+ database: "database",
8
+ host: "influxdb.test",
9
+ port: 9999,
10
+ username: "username",
11
+ password: "password",
12
+ time_precision: "s"
16
13
  end
17
14
 
18
- let(:args) { {} }
19
15
  let(:query) { nil }
20
16
  let(:response) { { "results" => [{ "statement_id" => 0 }] } }
21
17
 
22
18
  before do
23
- stub_request(:get, "http://influxdb.test:9999/query").with(
24
- query: { u: "username", p: "password", q: query }
25
- ).to_return(body: JSON.generate(response))
19
+ stub_request(:get, "http://influxdb.test:9999/query")
20
+ .with(query: { u: "username", p: "password", q: query })
21
+ .to_return(body: JSON.generate(response))
26
22
  end
27
23
 
28
24
  describe "#create_database" do
@@ -3,26 +3,22 @@ require "json"
3
3
 
4
4
  describe InfluxDB::Client do
5
5
  let(:subject) do
6
- described_class.new(
7
- "database",
8
- {
9
- host: "influxdb.test",
10
- port: 9999,
11
- username: "username",
12
- password: "password",
13
- time_precision: "s"
14
- }.merge(args)
15
- )
6
+ described_class.new \
7
+ database: "database",
8
+ host: "influxdb.test",
9
+ port: 9999,
10
+ username: "username",
11
+ password: "password",
12
+ time_precision: "s"
16
13
  end
17
14
 
18
- let(:args) { {} }
19
15
  let(:query) { nil }
20
16
  let(:response) { { "results" => [{ "statement_id" => 0 }] } }
21
17
 
22
18
  before do
23
- stub_request(:get, "http://influxdb.test:9999/query").with(
24
- query: { u: "username", p: "password", q: query }
25
- ).to_return(body: JSON.generate(response))
19
+ stub_request(:get, "http://influxdb.test:9999/query")
20
+ .with(query: { u: "username", p: "password", q: query })
21
+ .to_return(body: JSON.generate(response))
26
22
  end
27
23
 
28
24
  describe "#list_retention_policies" do
@@ -23,11 +23,9 @@ describe InfluxDB::Client do
23
23
  let(:query) { "SHOW SERIES" }
24
24
 
25
25
  before do
26
- stub_request(:get, "http://influxdb.test:9999/query").with(
27
- query: { u: "username", p: "password", q: query, db: "database" }
28
- ).to_return(
29
- body: JSON.generate(response)
30
- )
26
+ stub_request(:get, "http://influxdb.test:9999/query")
27
+ .with(query: { u: "username", p: "password", q: query, db: "database" })
28
+ .to_return(body: JSON.generate(response))
31
29
  end
32
30
 
33
31
  it "returns a list of all series names" do
@@ -40,11 +38,9 @@ describe InfluxDB::Client do
40
38
  let(:query) { "SHOW SERIES" }
41
39
 
42
40
  before do
43
- stub_request(:get, "http://influxdb.test:9999/query").with(
44
- query: { u: "username", p: "password", q: query, db: "database" }
45
- ).to_return(
46
- body: JSON.generate(response)
47
- )
41
+ stub_request(:get, "http://influxdb.test:9999/query")
42
+ .with(query: { u: "username", p: "password", q: query, db: "database" })
43
+ .to_return(body: JSON.generate(response))
48
44
  end
49
45
 
50
46
  it "returns a empty list" do
@@ -57,9 +53,8 @@ describe InfluxDB::Client do
57
53
  let(:query) { "DROP SERIES FROM #{name}" }
58
54
 
59
55
  before do
60
- stub_request(:get, "http://influxdb.test:9999/query").with(
61
- query: { u: "username", p: "password", q: query, db: "database" }
62
- )
56
+ stub_request(:get, "http://influxdb.test:9999/query")
57
+ .with(query: { u: "username", p: "password", q: query, db: "database" })
63
58
  end
64
59
 
65
60
  it "should GET to remove a database" do
@@ -3,20 +3,15 @@ require "json"
3
3
 
4
4
  describe InfluxDB::Client do
5
5
  let(:subject) do
6
- described_class.new(
7
- "database",
8
- {
9
- host: "influxdb.test",
10
- port: 9999,
11
- username: "username",
12
- password: "password",
13
- time_precision: "s"
14
- }.merge(args)
15
- )
6
+ described_class.new \
7
+ database: "database",
8
+ host: "influxdb.test",
9
+ port: 9999,
10
+ username: "username",
11
+ password: "password",
12
+ time_precision: "s"
16
13
  end
17
14
 
18
- let(:args) { {} }
19
-
20
15
  ### TODO ###
21
16
 
22
17
  # describe "GET #list_shards" do
@@ -3,26 +3,22 @@ require "json"
3
3
 
4
4
  describe InfluxDB::Client do
5
5
  let(:subject) do
6
- described_class.new(
7
- "database",
8
- {
9
- host: "influxdb.test",
10
- port: 9999,
11
- username: "username",
12
- password: "password",
13
- time_precision: "s"
14
- }.merge(args)
15
- )
6
+ described_class.new \
7
+ databse: "database",
8
+ host: "influxdb.test",
9
+ port: 9999,
10
+ username: "username",
11
+ password: "password",
12
+ time_precision: "s"
16
13
  end
17
14
 
18
- let(:args) { {} }
19
15
  let(:query) { nil }
20
16
  let(:response) { { "results" => [{ "statement_id" => 0 }] } }
21
17
 
22
18
  before do
23
- stub_request(:get, "http://influxdb.test:9999/query").with(
24
- query: { u: "username", p: "password", q: query }
25
- ).to_return(body: JSON.generate(response))
19
+ stub_request(:get, "http://influxdb.test:9999/query")
20
+ .with(query: { u: "username", p: "password", q: query })
21
+ .to_return(body: JSON.generate(response))
26
22
  end
27
23
 
28
24
  describe "#update user password" do
@@ -2,17 +2,15 @@ require "spec_helper"
2
2
 
3
3
  describe InfluxDB::Client do
4
4
  let(:subject) do
5
- described_class.new "database", {
6
- host: "influxdb.test",
7
- port: 9999,
8
- username: "username",
9
- password: "password",
5
+ described_class.new \
6
+ database: "database",
7
+ host: "influxdb.test",
8
+ port: 9999,
9
+ username: "username",
10
+ password: "password",
10
11
  time_precision: "s"
11
- }.merge(args)
12
12
  end
13
13
 
14
- let(:args) { {} }
15
-
16
14
  describe "#query with parameters" do
17
15
  let(:query) { "SELECT value FROM requests_per_minute WHERE time > %{start}" }
18
16
  let(:query_params) { { start: 1_437_019_900 } }
@@ -3,20 +3,21 @@ require "json"
3
3
 
4
4
  describe InfluxDB::Client do
5
5
  let(:subject) do
6
- described_class.new "database",
7
- host: "influxdb.test",
8
- port: 9999,
9
- username: "username",
10
- password: "password"
6
+ described_class.new \
7
+ database: "database",
8
+ host: "influxdb.test",
9
+ port: 9999,
10
+ username: "username",
11
+ password: "password"
11
12
  end
12
13
 
13
14
  let(:query) { nil }
14
15
  let(:response) { { "results" => [{ "statement_id" => 0 }] } }
15
16
 
16
17
  before do
17
- stub_request(:get, "http://influxdb.test:9999/query").with(
18
- query: { u: "username", p: "password", q: query, db: "database" }
19
- ).to_return(body: JSON.generate(response))
18
+ stub_request(:get, "http://influxdb.test:9999/query")
19
+ .with(query: { u: "username", p: "password", q: query, db: "database" })
20
+ .to_return(body: JSON.generate(response))
20
21
  end
21
22
 
22
23
  describe "#show_field_keys" do
@@ -3,17 +3,15 @@ require "json"
3
3
 
4
4
  describe InfluxDB::Client do
5
5
  let(:subject) do
6
- described_class.new "database", {
7
- host: "influxdb.test",
8
- port: 9999,
9
- username: "username",
10
- password: "password",
6
+ described_class.new \
7
+ database: "database",
8
+ host: "influxdb.test",
9
+ port: 9999,
10
+ username: "username",
11
+ password: "password",
11
12
  time_precision: "s"
12
- }.merge(args)
13
13
  end
14
14
 
15
- let(:args) { {} }
16
-
17
15
  let(:database) { subject.config.database }
18
16
 
19
17
  describe "#write_point" do
@@ -0,0 +1,114 @@
1
+ require "spec_helper"
2
+
3
+ describe InfluxDB::Client, smoke: true, if: min_influx_version("1.2.0") do
4
+ before do
5
+ WebMock.allow_net_connect!
6
+ end
7
+
8
+ after do
9
+ WebMock.disable_net_connect!
10
+ end
11
+
12
+ let(:client) do
13
+ InfluxDB::Client.new \
14
+ database: "NOAA_water_database",
15
+ username: "test_user",
16
+ password: "resu_tset",
17
+ retry: 4
18
+ end
19
+
20
+ let :queries do
21
+ [
22
+ "select count(water_level) from h2o_feet where location = 'santa_monica'",
23
+ "select * from h2o_feet where time > now()", # empty result
24
+ "select count(water_level) from h2o_feet where location = 'coyote_creek'",
25
+ ]
26
+ end
27
+
28
+ it "#query filters empty results incorrect result" do
29
+ results = client.query(queries.join(";"))
30
+ expect(results.size).to be 2 # but should be 3!
31
+ expect(results[0]["values"][0]["count"]).to be 7654
32
+ expect(results[1]["values"][0]["count"]).to be 7604
33
+ end
34
+
35
+ context "#batch.execute" do
36
+ it "returns expected results" do
37
+ results = client.batch do |b|
38
+ queries.each { |q| b.add(q) }
39
+ end.execute
40
+
41
+ expect(results.size).to be 3
42
+ expect(results[0][0]["values"][0]["count"]).to be 7654
43
+ expect(results[1]).to eq []
44
+ expect(results[2][0]["values"][0]["count"]).to be 7604
45
+ end
46
+
47
+ it "with block yields statement id" do
48
+ batch = client.batch do |b|
49
+ queries.each { |q| b.add(q) }
50
+ end
51
+
52
+ batch.execute do |sid, _, _, values|
53
+ case sid
54
+ when 0
55
+ expect(values[0]["count"]).to be 7654
56
+ when 1
57
+ expect(values).to eq []
58
+ when 2
59
+ expect(values[0]["count"]).to be 7604
60
+ end
61
+ end
62
+ end
63
+
64
+ context "with tags" do
65
+ let :queries do
66
+ [
67
+ "select count(water_level) from h2o_feet group by location",
68
+ "select * from h2o_feet where time > now()", # empty result
69
+ ]
70
+ end
71
+
72
+ it "returns expected results" do
73
+ results = client.batch do |b|
74
+ queries.each { |q| b.add(q) }
75
+ end.execute
76
+
77
+ expect(results.size).to be 2
78
+ results[0].each do |res|
79
+ location = res["tags"]["location"]
80
+ expect(%w[coyote_creek santa_monica]).to include location
81
+
82
+ value = location == "santa_monica" ? 7654 : 7604
83
+ expect(res["values"][0]["count"]).to be value
84
+ end
85
+ end
86
+
87
+ it "with block yields statement id" do
88
+ batch = client.batch do |b|
89
+ queries.each { |q| b.add(q) }
90
+ end
91
+
92
+ got_santa_monica = got_coyote_creek = got_empty_result = false
93
+
94
+ batch.execute do |sid, _, tags, values|
95
+ case [sid, tags["location"]]
96
+ when [0, "santa_monica"]
97
+ expect(values[0]["count"]).to be 7654
98
+ got_santa_monica = true
99
+ when [0, "coyote_creek"]
100
+ expect(values[0]["count"]).to be 7604
101
+ got_coyote_creek = true
102
+ when [1, nil]
103
+ expect(values).to eq []
104
+ got_empty_result = true
105
+ end
106
+ end
107
+
108
+ expect(got_coyote_creek).to be true
109
+ expect(got_santa_monica).to be true
110
+ expect(got_empty_result).to be true
111
+ end
112
+ end
113
+ end
114
+ end
@@ -10,10 +10,11 @@ describe InfluxDB::Client, smoke: true do
10
10
  end
11
11
 
12
12
  let(:client) do
13
- InfluxDB::Client.new(database: "NOAA_water_database",
14
- username: "test_user",
15
- password: "resu_tset",
16
- retry: 4)
13
+ InfluxDB::Client.new \
14
+ database: "NOAA_water_database",
15
+ username: "test_user",
16
+ password: "resu_tset",
17
+ retry: 4
17
18
  end
18
19
 
19
20
  context "connects to the database" do
@@ -56,4 +57,21 @@ describe InfluxDB::Client, smoke: true do
56
57
  expect(result).to include(sample_data2)
57
58
  end
58
59
  end
60
+
61
+ context "batch query" do
62
+ let :queries do
63
+ [
64
+ "select count(water_level) from h2o_feet where location = 'santa_monica'",
65
+ "select * from h2o_feet where time > now()", # empty result
66
+ "select count(water_level) from h2o_feet where location = 'coyote_creek'",
67
+ ]
68
+ end
69
+
70
+ it "#query filters empty results incorrect result" do
71
+ results = client.query(queries.join(";"))
72
+ expect(results.size).to be 2 # but should be 3!
73
+ expect(results[0]["values"][0]["count"]).to be 7654
74
+ expect(results[1]["values"][0]["count"]).to be 7604
75
+ end
76
+ end
59
77
  end
@@ -8,10 +8,16 @@ rescue LoadError
8
8
  end
9
9
  # rubocop:enable Lint/HandleExceptions
10
10
 
11
+ def min_influx_version(version)
12
+ current = Gem::Version.new ENV.fetch("influx_version", "0")
13
+ current >= Gem::Version.new(version)
14
+ end
15
+
11
16
  RSpec.configure do |config|
12
17
  config.color = ENV["TRAVIS"] != "true"
13
18
  config.filter_run_excluding smoke: ENV["TRAVIS"] != "true" || !ENV.key?("influx_version")
14
19
  puts "SMOKE TESTS ARE NOT CURRENTLY RUNNING" if ENV["TRAVIS"] != "true"
20
+
15
21
  # rubocop:disable Style/ConditionalAssignment
16
22
  if config.files_to_run.one? || ENV["TRAVIS"] == "true"
17
23
  config.formatter = :documentation
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: influxdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Todd Persen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-19 00:00:00.000000000 Z
11
+ date: 2018-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -105,6 +105,7 @@ files:
105
105
  - lib/influxdb/logging.rb
106
106
  - lib/influxdb/max_queue.rb
107
107
  - lib/influxdb/point_value.rb
108
+ - lib/influxdb/query/batch.rb
108
109
  - lib/influxdb/query/builder.rb
109
110
  - lib/influxdb/query/cluster.rb
110
111
  - lib/influxdb/query/continuous_query.rb
@@ -117,13 +118,13 @@ files:
117
118
  - lib/influxdb/writer/async.rb
118
119
  - lib/influxdb/writer/udp.rb
119
120
  - spec/influxdb/cases/async_client_spec.rb
121
+ - spec/influxdb/cases/query_batch_spec.rb
120
122
  - spec/influxdb/cases/query_cluster_spec.rb
121
123
  - spec/influxdb/cases/query_continuous_query_spec.rb
122
124
  - spec/influxdb/cases/query_core_spec.rb
123
125
  - spec/influxdb/cases/query_database_spec.rb
124
126
  - spec/influxdb/cases/query_retention_policy_spec.rb
125
127
  - spec/influxdb/cases/query_series_spec.rb
126
- - spec/influxdb/cases/query_shard_space_spec.rb
127
128
  - spec/influxdb/cases/query_shard_spec.rb
128
129
  - spec/influxdb/cases/query_user_spec.rb
129
130
  - spec/influxdb/cases/query_with_params_spec.rb
@@ -140,6 +141,7 @@ files:
140
141
  - spec/influxdb/point_value_spec.rb
141
142
  - spec/influxdb/query_builder_spec.rb
142
143
  - spec/influxdb/worker_spec.rb
144
+ - spec/smoke/smoke_batch_spec.rb
143
145
  - spec/smoke/smoke_spec.rb
144
146
  - spec/spec_helper.rb
145
147
  homepage: http://influxdb.org
@@ -162,19 +164,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
162
164
  version: '0'
163
165
  requirements: []
164
166
  rubyforge_project:
165
- rubygems_version: 2.6.13
167
+ rubygems_version: 2.7.7
166
168
  signing_key:
167
169
  specification_version: 4
168
170
  summary: Ruby library for InfluxDB.
169
171
  test_files:
170
172
  - spec/influxdb/cases/async_client_spec.rb
173
+ - spec/influxdb/cases/query_batch_spec.rb
171
174
  - spec/influxdb/cases/query_cluster_spec.rb
172
175
  - spec/influxdb/cases/query_continuous_query_spec.rb
173
176
  - spec/influxdb/cases/query_core_spec.rb
174
177
  - spec/influxdb/cases/query_database_spec.rb
175
178
  - spec/influxdb/cases/query_retention_policy_spec.rb
176
179
  - spec/influxdb/cases/query_series_spec.rb
177
- - spec/influxdb/cases/query_shard_space_spec.rb
178
180
  - spec/influxdb/cases/query_shard_spec.rb
179
181
  - spec/influxdb/cases/query_user_spec.rb
180
182
  - spec/influxdb/cases/query_with_params_spec.rb
@@ -191,5 +193,6 @@ test_files:
191
193
  - spec/influxdb/point_value_spec.rb
192
194
  - spec/influxdb/query_builder_spec.rb
193
195
  - spec/influxdb/worker_spec.rb
196
+ - spec/smoke/smoke_batch_spec.rb
194
197
  - spec/smoke/smoke_spec.rb
195
198
  - spec/spec_helper.rb
@@ -1,105 +0,0 @@
1
- # TODO: support 0.9.x
2
-
3
- # require "spec_helper"
4
- # require "json"
5
-
6
- # describe InfluxDB::Client do
7
- # let(:subject) do
8
- # described_class.new(
9
- # "database",
10
- # {
11
- # host: "influxdb.test",
12
- # port: 9999,
13
- # username: "username",
14
- # password: "password",
15
- # time_precision: "s"
16
- # }.merge(args)
17
- # )
18
- # end
19
-
20
- # let(:args) { {} }
21
-
22
- # let(:url) { "http://influxdb.test:9999/cluster/shard_spaces" }
23
- # let(:req_query) { { u: "username", p: "password" } }
24
- # let(:req_body) { nil }
25
- # let(:request_params) { { query: req_query, body: req_body } }
26
- # let(:response) { { body: JSON.generate(shard_spaces), status: 200 } }
27
- # let(:shard_spaces) { [subject.default_shard_space_options.merge("database" => "foo")] }
28
-
29
- # context "GET methods" do
30
- # before { stub_request(:get, url).with(request_params).to_return(response) }
31
-
32
- # describe "GET #list_shard_spaces" do
33
- # it 'returns OK' do
34
- # expect(subject.list_shard_spaces).to eq shard_spaces
35
- # end
36
- # end
37
-
38
- # describe "GET #shard_space_info" do
39
- # context "non-empty list" do
40
- # it "returns shard space info" do
41
- # expect(subject.shard_space_info('foo', 'default')).to eq shard_spaces.first
42
- # end
43
- # end
44
-
45
- # context "returns an empty list" do
46
- # let(:shard_spaces) { [] }
47
-
48
- # it "returns no shard space" do
49
- # expect(subject.shard_space_info('foo', 'default')).to be_nil
50
- # end
51
- # end
52
- # end
53
- # end
54
-
55
- # describe "POST #create_shard_space" do
56
- # let(:url) { "http://influxdb.test:9999/cluster/shard_spaces/foo" }
57
- # let(:req_body) { subject.default_shard_space_options }
58
- # let(:response) { { status: 200 } }
59
-
60
- # before { stub_request(:post, url).with(request_params).to_return(response) }
61
-
62
- # it 'returns OK' do
63
- # expect(subject.create_shard_space("foo", subject.default_shard_space_options))
64
- # .to be_a(Net::HTTPOK)
65
- # end
66
- # end
67
-
68
- # describe "DELETE #delete_shard_space" do
69
- # let(:url) { "http://influxdb.test:9999/cluster/shard_spaces/foo/default" }
70
- # let(:response) { { status: 200 } }
71
- # before { stub_request(:delete, url).with(request_params).to_return(response) }
72
-
73
- # it 'returns OK' do
74
- # expect(subject.delete_shard_space("foo", "default")).to be_a(Net::HTTPOK)
75
- # end
76
- # end
77
-
78
- # describe "#update_shard_space" do
79
- # let(:post_url) { "http://influxdb.test:9999/cluster/shard_spaces/foo/default" }
80
- # let(:post_request_params) do
81
- # {
82
- # query: req_query,
83
- # body: subject.default_shard_space_options.merge("shardDuration" => "30d")
84
- # }
85
- # end
86
-
87
- # it 'gets the shard space and updates the shard space' do
88
- # stub_request(:get, url).with(request_params).to_return(response)
89
- # stub_request(:post, post_url).with(post_request_params)
90
-
91
- # expect(subject.update_shard_space("foo", "default", "shardDuration" => "30d")).to be_a(Net::HTTPOK)
92
- # end
93
- # end
94
-
95
- # describe "POST #configure_database" do
96
- # let(:url) { "http://influxdb.test:9999/cluster/database_configs/foo" }
97
- # let(:req_body) { subject.default_database_configuration }
98
-
99
- # before { stub_request(:post, url).with(request_params) }
100
-
101
- # it "returns OK" do
102
- # expect(subject.configure_database("foo")).to be_a(Net::HTTPOK)
103
- # end
104
- # end
105
- # end