tempoiq 1.0.2 → 1.0.3

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,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: cfdc25fdc88fdd73576dd4e68649facbf463be7d
4
- data.tar.gz: 00605f70755dae0ff641342fe726104d446ca4d6
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ OGVkZjI1ZjdiM2QxOTQyMjI2ODUxOWFhM2VmNjRhNTQwZmM4ODY1YQ==
5
+ data.tar.gz: !binary |-
6
+ YjI0NzM1OWQ0NDljYzRjODkxZDcwNGM4YWY4MTNiYTdiZWZkMmM2MA==
5
7
  SHA512:
6
- metadata.gz: 8a52391dfe9959ea2c258baceb688e5e65171cc46a4e1d77f36b0d4d3ba05632cdae3e9feb1ca61e81010febbc8ce6267248aa407a532107eb131f415f208d9f
7
- data.tar.gz: 892f02d33742ed6a08fedcf3f03576c6abe114198778430dc6154818aa995f1a9925287b1f9804a4238b7fc8c6a8258a33af6b19abb9dee1bfd403f32c5500df
8
+ metadata.gz: !binary |-
9
+ OGQzZDg4Mzc3ZDA0NDU5YTJjNzIxOThjOGIzZWVmZThkNDI5NTQzOTFjY2Rh
10
+ M2Y2NDI4OTlkMjM1N2YzOTI2YTFjMWU4OTdkNzFmOWFmZmI4ZTdiYTc0Njc4
11
+ YjEyZjBlMTc4ZDA4MGNhNDQxM2E1NTNiMzk5YjVlYzY3NTJkZjE=
12
+ data.tar.gz: !binary |-
13
+ M2Q0NmQxMDI4ZGNjMzJhYzY1NmI0ZTU1ZGE0MzNhZmRmZjY1ZDYyM2YxNzlm
14
+ NzIxZTIyNWI2NzAwM2JlY2I4MDhjZDE4ZDhiMDc0MDFhMzI4YWIyMzIwOTEy
15
+ YWZmMjMzZmJhMzU3ZGE4YjBkZTk1MzlhZDNjMjIxMmRmNzY2OWE=
@@ -8,7 +8,7 @@ require 'tempoiq/models/datapoint'
8
8
  require 'tempoiq/models/delete_summary'
9
9
  require 'tempoiq/models/device'
10
10
  require 'tempoiq/models/find'
11
- require 'tempoiq/models/multi_status'
11
+ require 'tempoiq/models/write_response'
12
12
  require 'tempoiq/models/pipeline'
13
13
  require 'tempoiq/models/query'
14
14
  require 'tempoiq/models/read'
@@ -148,7 +148,7 @@ module TempoIQ
148
148
  query = Query.new(Search.new("devices", selection),
149
149
  Find.new(opts[:limit]),
150
150
  nil)
151
- Cursor.new(Device, remoter, "/v2/devices", query, media_types(:accept => [media_type("error", "v1"), media_type("device-collection", "v2")],
151
+ Cursor.new(Device, remoter, "/v2/devices", query, media_types(:accept => [media_type("device-collection", "v2"), media_type("error", "v1")],
152
152
  :content => media_type("query", "v1")))
153
153
  end
154
154
 
@@ -233,9 +233,9 @@ module TempoIQ
233
233
  # * +bulk_write+ - The write request to send to the backend. Yielded to the block.
234
234
  #
235
235
  # On success:
236
- # - Returns MultiStatus
236
+ # - Returns WriteResponse
237
237
  # On partial success:
238
- # - Returns MultiStatus
238
+ # - Returns WriteResponse
239
239
  # On failure:
240
240
  # - Raises HttpException
241
241
  #
@@ -263,11 +263,10 @@ module TempoIQ
263
263
  end
264
264
 
265
265
  result = remoter.post("/v2/write", JSON.dump(bulk.to_hash))
266
- if result.code == HttpResult::OK
267
- MultiStatus.new
268
- elsif result.code == HttpResult::MULTI
269
- json = JSON.parse(result.body)
270
- MultiStatus.new(json)
266
+ if result.code == HttpResult::OK || result.code == HttpResult::MULTI
267
+ body = result.body.empty? ? "{}" : result.body
268
+ json = JSON.parse(body)
269
+ WriteResponse.new(json)
271
270
  else
272
271
  raise HttpException.new(result)
273
272
  end
@@ -342,7 +341,7 @@ module TempoIQ
342
341
  Read.new(start, stop, opts[:limit]),
343
342
  pipeline)
344
343
 
345
- Cursor.new(Row, remoter, "/v2/read", query, media_types(:accept => [media_type("error", "v1"), media_type("datapoint-collection", "v2")],
344
+ Cursor.new(Row, remoter, "/v2/read", query, media_types(:accept => [media_type("datapoint-collection", "v2"), media_type("error", "v1")],
346
345
  :content => media_type("query", "v1")))
347
346
  end
348
347
 
@@ -409,7 +408,7 @@ module TempoIQ
409
408
  Single.new(function, timestamp),
410
409
  pipeline)
411
410
 
412
- Cursor.new(Row, remoter, "/v2/single", query, media_types(:accept => [media_type("error", "v1"), media_type("datapoint-collection", "v1")],
411
+ Cursor.new(Row, remoter, "/v2/single", query, media_types(:accept => [media_type("datapoint-collection", "v1"), media_type("error", "v1")],
413
412
  :content => media_type("query", "v1")))
414
413
  end
415
414
 
@@ -1,6 +1,6 @@
1
1
  module TempoIQ
2
2
  module Constants
3
- VERSION = "1.0.2"
3
+ VERSION = "1.0.3"
4
4
  TRUSTED_CERT_FILE = File.join(File.dirname(__FILE__), "..", "trusted-certs.crt")
5
5
  end
6
6
  end
@@ -0,0 +1,58 @@
1
+ module TempoIQ
2
+ # WriteResponse is used to track the status of a write. Because writes
3
+ # are bulk in nature (writing to multiple devices and sensors at once),
4
+ # there are instances where some writes device writes may succeed and
5
+ # some might fail in the same write call.
6
+ #
7
+ # [High level introspection]
8
+ # - #success?
9
+ # - #partial_success?
10
+ #
11
+ # [Device level introspection]
12
+ # - #failures
13
+ # - #created
14
+ # - #existing
15
+ # - #modified
16
+ class WriteResponse
17
+ attr_reader :status
18
+
19
+ def initialize(status = nil)
20
+ @status = status
21
+ end
22
+
23
+ # Was the write a total success?
24
+ def success?
25
+ status.each do |key,device_status|
26
+ if device_status['successful'] == false
27
+ return false
28
+ end
29
+ end
30
+ true
31
+ end
32
+
33
+ # Did the write have partial failures?
34
+ def partial_success?
35
+ !success?
36
+ end
37
+
38
+ # Retrieve the failures, key => message [Hash]
39
+ def failures
40
+ status.select { |device_key, v| v["successful"] == false }
41
+ end
42
+
43
+ # Devices that already existed before the write
44
+ def existing
45
+ status.select { |device_key, v| v["device_state"] == "existing" }
46
+ end
47
+
48
+ # Devices that were created during the write
49
+ def created
50
+ status.select { |device_key, v| v["device_state"] == "created" }
51
+ end
52
+
53
+ # Devices that were modified (eg - sensors added) during the write
54
+ def modified
55
+ status.select { |device_key, v| v["device_state"] == "modified" }
56
+ end
57
+ end
58
+ end
@@ -140,7 +140,14 @@ module ClientTest
140
140
  device_key = device.key
141
141
  sensor_key = device.sensors.first.key
142
142
 
143
- client.remoter.stub(:post, "/v2/write", 200)
143
+ stubbed_body = {"device1" =>
144
+ {"success" => true,
145
+ "message" => nil,
146
+ "device_state" => "existing"
147
+ }
148
+ }
149
+
150
+ client.remoter.stub(:post, "/v2/write", 207, JSON.dump(stubbed_body))
144
151
 
145
152
  status = client.write_bulk do |write|
146
153
  write.add(device_key, sensor_key, TempoIQ::DataPoint.new(ts, 1.23))
@@ -158,25 +165,48 @@ module ClientTest
158
165
  end
159
166
  end
160
167
 
161
- def test_write_with_partial_failure
162
- device = create_device
168
+ def test_write_with_upsert
169
+ device1 = create_device
170
+ device2 = create_device(key="device2")
163
171
  client = get_client
164
172
  ts = Time.utc(2012, 1, 1)
165
173
 
166
- device_key = device.key
167
- sensor_key = device.sensors.first.key
174
+ device_key1 = device1.key
175
+ sensor_key = device1.sensors.first.key
176
+ device_key2 = device2.key
177
+ device_key3 = "device3"
168
178
 
169
- stubbed_body = {"device1" => {"success" => false, "message" => "error writing to storage: FERR_NO_SENSOR: No sensor with key found in device."}}
179
+ stubbed_body = {"device1" =>
180
+ {"success" => true,
181
+ "message" => nil,
182
+ "device_state" => "existing"
183
+ },
184
+ "device2" =>
185
+ {"success" => true,
186
+ "message" => nil,
187
+ "device_state" => "modified"
188
+ },
189
+ "device3" =>
190
+ {"success" => true,
191
+ "message" => nil,
192
+ "device_state" => "created"
193
+ }
194
+ }
170
195
  client.remoter.stub(:post, "/v2/write", 207, JSON.dump(stubbed_body))
171
196
 
172
197
  status = client.write_bulk do |write|
173
- write.add(device_key, sensor_key, TempoIQ::DataPoint.new(ts, 1.23))
174
- write.add(device_key, "not_here", TempoIQ::DataPoint.new(ts, 2.34))
198
+ write.add(device_key1, sensor_key, TempoIQ::DataPoint.new(ts, 1.23))
199
+ write.add(device_key2, "not_here", TempoIQ::DataPoint.new(ts, 2.34))
200
+ write.add(device_key3, "not_here", TempoIQ::DataPoint.new(ts, 2.34))
175
201
  end
176
202
 
177
- assert(!status.success?)
178
- assert(status.partial_success?)
179
- assert_equal(1, status.failures.size)
203
+ assert(status.success?)
204
+ assert_equal(1, status.existing.size)
205
+ assert_equal("device1", status.existing.keys.first)
206
+ assert_equal(1, status.modified.size)
207
+ assert_equal("device2", status.modified.keys.first)
208
+ assert_equal(1, status.created.size)
209
+ assert_equal("device3", status.created.keys.first)
180
210
  end
181
211
 
182
212
  def test_write_device
@@ -187,7 +217,14 @@ module ClientTest
187
217
  device_key = device.key
188
218
  sensor_key = device.sensors.first.key
189
219
 
190
- client.remoter.stub(:post, "/v2/write", 200)
220
+ stubbed_body = {"device1" =>
221
+ {"success" => true,
222
+ "message" => nil,
223
+ "device_state" => "existing"
224
+ }
225
+ }
226
+
227
+ client.remoter.stub(:post, "/v2/write", 207, JSON.dump(stubbed_body))
191
228
 
192
229
  written = client.write_device(device_key, ts, sensor_key => 1.23)
193
230
 
@@ -204,9 +241,16 @@ module ClientTest
204
241
  device_key = device.key
205
242
  sensor_key1 = device.sensors[0].key
206
243
  sensor_key2 = device.sensors[1].key
207
-
208
- client.remoter.stub(:post, "/v2/write", 200)
209
244
 
245
+ stubbed_body = {"device1" =>
246
+ {"success" => true,
247
+ "message" => nil,
248
+ "device_state" => "existing"
249
+ }
250
+ }
251
+
252
+ client.remoter.stub(:post, "/v2/write", 207, JSON.dump(stubbed_body))
253
+
210
254
  write_result = client.write_device(device_key, Time.utc(2012, 1, 1, 1), sensor_key1 => 4.0, sensor_key2 => 2.0)
211
255
  assert_equal(true, write_result)
212
256
  write_result = client.write_device(device_key, Time.utc(2012, 1, 1, 2), sensor_key1 => 4.0, sensor_key2 => 2.0)
@@ -248,7 +292,14 @@ module ClientTest
248
292
  device_key = device.key
249
293
  sensor_key = device.sensors[0].key
250
294
 
251
- client.remoter.stub(:post, "/v2/write", 200)
295
+ stubbed_body = {"device1" =>
296
+ {"success" => true,
297
+ "message" => nil,
298
+ "device_state" => "existing"
299
+ }
300
+ }
301
+
302
+ client.remoter.stub(:post, "/v2/write", 207, JSON.dump(stubbed_body))
252
303
 
253
304
  write_result = client.write_device(device_key, Time.utc(2012, 1, 1, 1, 0, 5, 0), sensor_key => 4.0)
254
305
  assert_equal(true, write_result)
@@ -330,8 +381,14 @@ module ClientTest
330
381
 
331
382
  device_key = device.key
332
383
  sensor_key = device.sensors[0].key
384
+ stubbed_body = {"device1" =>
385
+ {"success" => true,
386
+ "message" => nil,
387
+ "device_state" => "existing"
388
+ }
389
+ }
333
390
 
334
- client.remoter.stub(:post, "/v2/write", 200)
391
+ client.remoter.stub(:post, "/v2/write", 207, JSON.dump(stubbed_body))
335
392
 
336
393
  write_result = client.write_device(device_key, ts, sensor_key => 4.0)
337
394
  assert_equal(true, write_result)
@@ -372,7 +429,14 @@ module ClientTest
372
429
  sensor_key1 = device.sensors[0].key
373
430
  sensor_key2 = device.sensors[1].key
374
431
 
375
- client.remoter.stub(:post, "/v2/write", 200)
432
+ stubbed_body = {"device1" =>
433
+ {"success" => true,
434
+ "message" => nil,
435
+ "device_state" => "existing"
436
+ }
437
+ }
438
+
439
+ client.remoter.stub(:post, "/v2/write", 207, JSON.dump(stubbed_body))
376
440
 
377
441
  write_result = client.write_device(device_key, ts, sensor_key1 => 4.0, sensor_key2 => 2.0)
378
442
  assert_equal(true, write_result)
@@ -416,8 +480,15 @@ module ClientTest
416
480
  sensor_key1 = device.sensors[0].key
417
481
  sensor_key2 = device.sensors[1].key
418
482
 
419
- client.remoter.stub(:post, "/v2/write", 200)
420
- client.remoter.stub(:post, "/v2/write", 200)
483
+ stubbed_body = {"device1" =>
484
+ {"success" => true,
485
+ "message" => nil,
486
+ "device_state" => "existing"
487
+ }
488
+ }
489
+
490
+ client.remoter.stub(:post, "/v2/write", 207, JSON.dump(stubbed_body))
491
+ client.remoter.stub(:post, "/v2/write", 207, JSON.dump(stubbed_body))
421
492
 
422
493
  assert_equal(true, client.write_device(device_key, ts, sensor_key1 => 4.0, sensor_key2 => 2.0))
423
494
  assert_equal(true, client.write_device(device_key, ts2, sensor_key1 => 4.0, sensor_key2 => 2.0))
@@ -510,7 +581,14 @@ module ClientTest
510
581
  }
511
582
 
512
583
  client.remoter.stub(:get, "/v2/single", 200, JSON.dump(stubbed_single))
513
- client.remoter.stub(:post, "/v2/write", 200)
584
+ stubbed_body = {"device1" =>
585
+ {"success" => true,
586
+ "message" => nil,
587
+ "device_state" => "existing"
588
+ }
589
+ }
590
+
591
+ client.remoter.stub(:post, "/v2/write", 207, JSON.dump(stubbed_body))
514
592
 
515
593
  client.write_bulk do |write|
516
594
  write.add(device_key, sensor_key1, TempoIQ::DataPoint.new(ts, 4.0))
@@ -553,7 +631,14 @@ module ClientTest
553
631
  }
554
632
 
555
633
  client.remoter.stub(:get, "/v2/single", 200, JSON.dump(stubbed_single))
556
- client.remoter.stub(:post, "/v2/write", 200)
634
+ stubbed_body = {"device1" =>
635
+ {"success" => true,
636
+ "message" => nil,
637
+ "device_state" => "existing"
638
+ }
639
+ }
640
+
641
+ client.remoter.stub(:post, "/v2/write", 207, JSON.dump(stubbed_body))
557
642
 
558
643
  client.write_bulk do |write|
559
644
  write.add(device_key, sensor_key1, TempoIQ::DataPoint.new(ts, 4.0))
@@ -598,7 +683,14 @@ module ClientTest
598
683
  }
599
684
 
600
685
  client.remoter.stub(:get, "/v2/single", 200, JSON.dump(stubbed_single))
601
- client.remoter.stub(:post, "/v2/write", 200)
686
+ stubbed_body = {"device1" =>
687
+ {"success" => true,
688
+ "message" => nil,
689
+ "device_state" => "existing"
690
+ }
691
+ }
692
+
693
+ client.remoter.stub(:post, "/v2/write", 207, JSON.dump(stubbed_body))
602
694
 
603
695
  client.write_bulk do |write|
604
696
  write.add(device_key, sensor_key1, TempoIQ::DataPoint.new(ts_before, 4.0))
@@ -643,7 +735,14 @@ module ClientTest
643
735
  }
644
736
 
645
737
  client.remoter.stub(:get, "/v2/single", 200, JSON.dump(stubbed_single))
646
- client.remoter.stub(:post, "/v2/write", 200)
738
+ stubbed_body = {"device1" =>
739
+ {"success" => true,
740
+ "message" => nil,
741
+ "device_state" => "existing"
742
+ }
743
+ }
744
+
745
+ client.remoter.stub(:post, "/v2/write", 207, JSON.dump(stubbed_body))
647
746
 
648
747
  client.write_bulk do |write|
649
748
  write.add(device_key, sensor_key1, TempoIQ::DataPoint.new(ts, 4.0))
@@ -686,7 +785,14 @@ module ClientTest
686
785
  }
687
786
 
688
787
  client.remoter.stub(:get, "/v2/single", 200, JSON.dump(stubbed_single))
689
- client.remoter.stub(:post, "/v2/write", 200)
788
+ stubbed_body = {"device1" =>
789
+ {"success" => true,
790
+ "message" => nil,
791
+ "device_state" => "existing"
792
+ }
793
+ }
794
+
795
+ client.remoter.stub(:post, "/v2/write", 207, JSON.dump(stubbed_body))
690
796
 
691
797
  client.write_bulk do |write|
692
798
  write.add(device_key, sensor_key1, TempoIQ::DataPoint.new(ts, 4.0))
@@ -729,7 +835,14 @@ module ClientTest
729
835
  }
730
836
 
731
837
  client.remoter.stub(:get, "/v2/single", 200, JSON.dump(stubbed_single))
732
- client.remoter.stub(:post, "/v2/write", 200)
838
+ stubbed_body = {"device1" =>
839
+ {"success" => true,
840
+ "message" => nil,
841
+ "device_state" => "existing"
842
+ }
843
+ }
844
+
845
+ client.remoter.stub(:post, "/v2/write", 207, JSON.dump(stubbed_body))
733
846
 
734
847
  client.write_bulk do |write|
735
848
  write.add(device_key, sensor_key1, TempoIQ::DataPoint.new(ts, 4.0))
@@ -757,7 +870,14 @@ module ClientTest
757
870
 
758
871
  ts = Time.utc(2012, 1, 1)
759
872
 
760
- client.remoter.stub(:post, "/v2/write", 200)
873
+ stubbed_body = {"device1" =>
874
+ {"success" => true,
875
+ "message" => nil,
876
+ "device_state" => "existing"
877
+ }
878
+ }
879
+
880
+ client.remoter.stub(:post, "/v2/write", 207, JSON.dump(stubbed_body))
761
881
 
762
882
  client.write_bulk do |write|
763
883
  write.add(device_key, sensor_key1, TempoIQ::DataPoint.new(ts, 4.0))
@@ -847,6 +967,7 @@ module ClientTest
847
967
  }
848
968
 
849
969
  client.remoter.stub(:delete, "/v2/devices", 200, JSON.dump(stubbed_body))
850
- summary = client.delete_devices(:devices => {:attribute_key => TEMPO_TEST_ATTR})
970
+ summary1 = client.delete_devices(:devices => {:attribute_key => TEMPO_TEST_ATTR})
971
+ summary2 = client.delete_devices(:devices => {:key => "device3"})
851
972
  end
852
973
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tempoiq
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - TempoIQ Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-07 00:00:00.000000000 Z
11
+ date: 2015-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: test-unit
@@ -59,7 +59,7 @@ dependencies:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
61
  version: '2.4'
62
- - - '>='
62
+ - - ! '>='
63
63
  - !ruby/object:Gem::Version
64
64
  version: 2.4.0
65
65
  type: :runtime
@@ -69,7 +69,7 @@ dependencies:
69
69
  - - ~>
70
70
  - !ruby/object:Gem::Version
71
71
  version: '2.4'
72
- - - '>='
72
+ - - ! '>='
73
73
  - !ruby/object:Gem::Version
74
74
  version: 2.4.0
75
75
  - !ruby/object:Gem::Dependency
@@ -105,7 +105,6 @@ files:
105
105
  - lib/tempoiq/models/delete_summary.rb
106
106
  - lib/tempoiq/models/device.rb
107
107
  - lib/tempoiq/models/find.rb
108
- - lib/tempoiq/models/multi_status.rb
109
108
  - lib/tempoiq/models/pipeline.rb
110
109
  - lib/tempoiq/models/query.rb
111
110
  - lib/tempoiq/models/read.rb
@@ -114,6 +113,7 @@ files:
114
113
  - lib/tempoiq/models/selection.rb
115
114
  - lib/tempoiq/models/sensor.rb
116
115
  - lib/tempoiq/models/single.rb
116
+ - lib/tempoiq/models/write_response.rb
117
117
  - lib/tempoiq/remoter/http_result.rb
118
118
  - lib/tempoiq/remoter/live_remoter.rb
119
119
  - lib/tempoiq/remoter/stubbed_remoter.rb
@@ -134,12 +134,12 @@ require_paths:
134
134
  - lib
135
135
  required_ruby_version: !ruby/object:Gem::Requirement
136
136
  requirements:
137
- - - '>='
137
+ - - ! '>='
138
138
  - !ruby/object:Gem::Version
139
139
  version: '0'
140
140
  required_rubygems_version: !ruby/object:Gem::Requirement
141
141
  requirements:
142
- - - '>='
142
+ - - ! '>='
143
143
  - !ruby/object:Gem::Version
144
144
  version: '0'
145
145
  requirements: []
@@ -1,27 +0,0 @@
1
- module TempoIQ
2
- # MultiStatus is used in cases where an operation might partially succeed
3
- # and partially fail. It provides several helper functions to introspect the
4
- # failure and take appropriate action. (Log failure, resend DataPoints, etc.)
5
- class MultiStatus
6
- attr_reader :status
7
-
8
- def initialize(status = nil)
9
- @status = status
10
- end
11
-
12
- # Was the request a total success?
13
- def success?
14
- status.nil?
15
- end
16
-
17
- # Did the request have partial failures?
18
- def partial_success?
19
- !success?
20
- end
21
-
22
- # Retrieve the failures, key => message [Hash]
23
- def failures
24
- Hash[status.map { |device_key, v| [device_key, v["message"]] } ]
25
- end
26
- end
27
- end