influxdb 0.5.3 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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