rhoconnect 3.0.2 → 3.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.
@@ -181,10 +181,23 @@ module Rhoconnect
181
181
 
182
182
  # Deletes all keys matching a given mask
183
183
  def flash_data(keymask)
184
- @@db.keys(keymask).each do |key|
185
- @@db.del(key)
184
+ if keymask[/[*\[\]?]/]
185
+ # If the keymask contains any pattern matching characters
186
+ # Use keys command to find all keys matching pattern (this is extremely expensive)
187
+ # Then delete matches
188
+ @@db.keys(keymask).each do |key|
189
+ @@db.del(key)
190
+ end
191
+ else
192
+ # The keymask doesn't contain pattern matching characters
193
+ # A delete call is all that is needed
194
+ @@db.del(keymask)
186
195
  end
187
196
  end
197
+
198
+ def exists?(key)
199
+ @@db.exists(key)
200
+ end
188
201
 
189
202
  # Returns array of keys matching a given keymask
190
203
  def get_keys(keymask)
@@ -210,19 +223,27 @@ module Rhoconnect
210
223
  ts = current_time+(Rhoconnect.lock_duration || timeout)+1
211
224
  loop do
212
225
  if not @@db.setnx(lock_key,ts)
213
- if raise_on_expire or Rhoconnect.raise_on_expired_lock
214
- if @@db.get(lock_key).to_i <= current_time
215
- # lock expired before operation which set it up completed
216
- # this process cannot continue without corrupting locked data
217
- raise StoreLockException, "Lock \"#{lock_key}\" expired before it was released"
218
- end
219
- else
220
- if @@db.get(lock_key).to_i <= current_time and
221
- @@db.getset(lock_key,ts).to_i <= current_time
222
- # previous lock expired and we replaced it with our own
223
- break
224
- end
225
- end
226
+ current_lock = @@db.get(lock_key)
227
+ # ensure lock wasn't released between the setnx and get calls
228
+ if current_lock
229
+ current_lock_timeout = current_lock.to_i
230
+ if raise_on_expire or Rhoconnect.raise_on_expired_lock
231
+ if current_lock_timeout <= current_time
232
+ # lock expired before operation which set it up completed
233
+ # this process cannot continue without corrupting locked data
234
+ raise StoreLockException, "Lock \"#{lock_key}\" expired before it was released"
235
+ end
236
+ else
237
+ if current_lock_timeout <= current_time and
238
+ @@db.getset(lock_key,ts).to_i <= current_time
239
+ # previous lock expired and we replaced it with our own
240
+ break
241
+ end
242
+ end
243
+ # lock was released between setnx and get - try to acquire it again
244
+ elsif @@db.setnx(lock_key,ts)
245
+ break
246
+ end
226
247
  sleep(1)
227
248
  current_time = Time.now.to_i
228
249
  else
@@ -1,3 +1,3 @@
1
1
  module Rhoconnect
2
- VERSION = '3.0.2'
2
+ VERSION = '3.0.3'
3
3
  end
data/rhoconnect.gemspec CHANGED
@@ -43,7 +43,7 @@ Gem::Specification.new do |s|
43
43
  s.add_dependency('rubyzip', '~> 0.9.4')
44
44
  s.add_dependency('uuidtools', '>= 2.1.1')
45
45
  s.add_dependency('redis', '>= 2.2.0')
46
- s.add_dependency('resque', '~> 1.18.0')
46
+ s.add_dependency('resque', '~> 1.19.0')
47
47
  s.add_dependency('rest-client', '~> 1.6.1')
48
48
  s.add_dependency('templater', '~> 1.0.0')
49
49
  end
@@ -231,25 +231,97 @@ describe "SourceSync" do
231
231
  verify_read_operation_with_error('query')
232
232
  end
233
233
 
234
+ it "should do query with exception raised and update refresh time only after retries limit is exceeded" do
235
+ @s.retry_limit = 1
236
+ msg = "Error during query"
237
+ set_test_data('test_db_storage',{},msg,"query error")
238
+ res = @ss.do_query
239
+ verify_result(@s.docname(:md) => {},
240
+ @s.docname(:errors) => {'query-error'=>{'message'=>msg}})
241
+ # 1) if retry_limit is set to N - then, first N retries should not update refresh_time
242
+ @s.read_state.retry_counter.should == 1
243
+ @s.read_state.refresh_time.should <= Time.now.to_i
244
+
245
+ # try once more and fail again
246
+ set_test_data('test_db_storage',{},msg,"query error")
247
+ res = @ss.do_query
248
+ verify_result(@s.docname(:md) => {},
249
+ @s.docname(:errors) => {'query-error'=>{'message'=>msg}})
250
+
251
+ # 2) if retry_limit is set to N and number of retries exceeded it - update refresh_time
252
+ @s.read_state.retry_counter.should == 0
253
+ @s.read_state.refresh_time.should > Time.now.to_i
254
+ end
255
+
256
+ it "should do query with exception raised and restore state with succesfull retry" do
257
+ @s.retry_limit = 1
258
+ msg = "Error during query"
259
+ set_test_data('test_db_storage',{},msg,"query error")
260
+ res = @ss.do_query
261
+ verify_result(@s.docname(:md) => {},
262
+ @s.docname(:errors) => {'query-error'=>{'message'=>msg}})
263
+ # 1) if retry_limit is set to N - then, first N retries should not update refresh_time
264
+ @s.read_state.retry_counter.should == 1
265
+ @s.read_state.refresh_time.should <= Time.now.to_i
266
+
267
+ # try once more (with success)
268
+ expected = {'1'=>@product1,'2'=>@product2}
269
+ set_test_data('test_db_storage',expected)
270
+ @ss.do_query
271
+ verify_result(@s.docname(:md) => expected,
272
+ @s.docname(:errors) => {})
273
+ @s.read_state.retry_counter.should == 0
274
+ @s.read_state.refresh_time.should > Time.now.to_i
275
+ end
276
+
277
+ it "should reset the retry counter if prev_refresh_time was set more than poll_interval secs ago" do
278
+ @s.retry_limit = 3
279
+ @s.poll_interval = 2
280
+ msg = "Error during query"
281
+ set_test_data('test_db_storage',{},msg,"query error")
282
+ res = @ss.do_query
283
+ verify_result(@s.docname(:md) => {},
284
+ @s.docname(:errors) => {'query-error'=>{'message'=>msg}})
285
+ # 1) if retry_limit is set to N - then, first N retries should not update refresh_time
286
+ @s.read_state.retry_counter.should == 1
287
+ @s.read_state.refresh_time.should <= Time.now.to_i
288
+
289
+ # 2) Make another error - results are the same
290
+ set_test_data('test_db_storage',{},msg,"query error")
291
+ res = @ss.do_query
292
+ verify_result(@s.docname(:md) => {},
293
+ @s.docname(:errors) => {'query-error'=>{'message'=>msg}})
294
+ @s.read_state.retry_counter.should == 2
295
+ @s.read_state.refresh_time.should <= Time.now.to_i
296
+
297
+ # wait until time interval exprires and prev_refresh_time is too old -
298
+ # this should reset the counter on next request with error
299
+ # and do not update refresh_time
300
+ sleep(3)
301
+ set_test_data('test_db_storage',{},msg,"query error")
302
+ res = @ss.do_query
303
+ verify_result(@s.docname(:md) => {},
304
+ @s.docname(:errors) => {'query-error'=>{'message'=>msg}})
305
+ @s.read_state.retry_counter.should == 1
306
+ @s.read_state.refresh_time.should <= Time.now.to_i
307
+ end
308
+
234
309
  it "should do query with exception raised and update refresh time if retry_limit is 0" do
235
310
  @s.retry_limit = 0
236
311
  msg = "Error during query"
237
- @ss.should_receive(:log).with("SourceAdapter raised query exception: #{msg}")
238
- @ss.should_receive(:log).with(anything)
239
312
  set_test_data('test_db_storage',{},msg,"query error")
240
313
  res = @ss.do_query
241
314
  verify_result(@s.docname(:md) => {},
242
315
  @s.docname(:errors) => {'query-error'=>{'message'=>msg}})
316
+ # if poll_interval is set to 0 - refresh time should be updated
243
317
  @s.read_state.retry_counter.should == 0
244
318
  @s.read_state.refresh_time.should > Time.now.to_i
245
319
  end
246
-
320
+
247
321
  it "should do query with exception raised and update refresh time if poll_interval == 0" do
248
322
  @s.retry_limit = 1
249
323
  @s.poll_interval = 0
250
324
  msg = "Error during query"
251
- @ss.should_receive(:log).with("SourceAdapter raised query exception: #{msg}")
252
- @ss.should_receive(:log).with(anything)
253
325
  set_test_data('test_db_storage',{},msg,"query error")
254
326
  prev_refresh_time = @s.read_state.refresh_time
255
327
  # make sure refresh time is expired
@@ -288,6 +360,7 @@ describe "SourceSync" do
288
360
  verify_result("source:#{test_app_name}:__shared__:#{@s_fields[:name]}:md" => expected)
289
361
  Store.db.keys("read_state:#{test_app_name}:__shared__*").sort.should ==
290
362
  [ "read_state:#{test_app_name}:__shared__:SampleAdapter:refresh_time",
363
+ "read_state:#{test_app_name}:__shared__:SampleAdapter:prev_refresh_time",
291
364
  "read_state:#{test_app_name}:__shared__:SampleAdapter:rho__id",
292
365
  "read_state:#{test_app_name}:__shared__:SampleAdapter:retry_counter"].sort
293
366
  end
data/spec/store_spec.rb CHANGED
@@ -164,6 +164,29 @@ describe "Store" do
164
164
  Store.flash_data(@s.docname(:md))
165
165
  Store.get_data(@s.docname(:md)).should == {}
166
166
  end
167
+
168
+ it "should flash_data for all keys matching pattern" do
169
+ keys = ['test_flash_data1','test_flash_data2']
170
+ keys.each {|key| Store.put_data(key,@data)}
171
+ Store.flash_data('test_flash_data*')
172
+ keys.each {|key| Store.get_data(key).should == {} }
173
+ end
174
+
175
+ it "should flash_data without calling KEYS when there aren't pattern matching characters in the provided keymask" do
176
+ key = 'test_flash_data'
177
+ Store.put_data(key,@data)
178
+ Store.db.should_not_receive(:keys)
179
+ Store.db.should_receive(:del).once.with(key).and_return(true)
180
+ Store.flash_data(key)
181
+ end
182
+
183
+ it "should flash_data and call KEYS when there are pattern matching characters in the provided keymask" do
184
+ keys = ['test_flash_data1','test_flash_data2']
185
+ keys.each {|key| Store.put_data(key,@data)}
186
+ Store.db.should_receive(:keys).exactly(1).times.with("test_flash_data*").and_return(keys)
187
+ Store.db.should_receive(:del).exactly(2).times.with(/^test_flash_data[12]$/).and_return(true)
188
+ Store.flash_data("test_flash_data*")
189
+ end
167
190
 
168
191
  it "should get_keys" do
169
192
  expected = ["doc1:1:1:1:source1", "doc1:1:1:1:source2"]
metadata CHANGED
@@ -1,190 +1,135 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: rhoconnect
3
- version: !ruby/object:Gem::Version
4
- hash: 3
3
+ version: !ruby/object:Gem::Version
4
+ version: 3.0.3
5
5
  prerelease:
6
- segments:
7
- - 3
8
- - 0
9
- - 2
10
- version: 3.0.2
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Rhomobile
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-10-05 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- type: :runtime
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
12
+ date: 2011-10-13 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: &2160601560 !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
18
+ requirements:
26
19
  - - ~>
27
- - !ruby/object:Gem::Version
28
- hash: 15
29
- segments:
30
- - 1
31
- - 0
32
- version: "1.0"
33
- version_requirements: *id001
34
- name: bundler
35
- - !ruby/object:Gem::Dependency
20
+ - !ruby/object:Gem::Version
21
+ version: '1.0'
36
22
  type: :runtime
37
23
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: *2160601560
25
+ - !ruby/object:Gem::Dependency
26
+ name: sinatra
27
+ requirement: &2160591620 !ruby/object:Gem::Requirement
39
28
  none: false
40
- requirements:
29
+ requirements:
41
30
  - - ~>
42
- - !ruby/object:Gem::Version
43
- hash: 9
44
- segments:
45
- - 1
46
- - 3
47
- version: "1.3"
48
- version_requirements: *id002
49
- name: sinatra
50
- - !ruby/object:Gem::Dependency
31
+ - !ruby/object:Gem::Version
32
+ version: '1.3'
51
33
  type: :runtime
52
34
  prerelease: false
53
- requirement: &id003 !ruby/object:Gem::Requirement
35
+ version_requirements: *2160591620
36
+ - !ruby/object:Gem::Dependency
37
+ name: rake
38
+ requirement: &2160590320 !ruby/object:Gem::Requirement
54
39
  none: false
55
- requirements:
56
- - - "="
57
- - !ruby/object:Gem::Version
58
- hash: 63
59
- segments:
60
- - 0
61
- - 9
62
- - 2
40
+ requirements:
41
+ - - =
42
+ - !ruby/object:Gem::Version
63
43
  version: 0.9.2
64
- version_requirements: *id003
65
- name: rake
66
- - !ruby/object:Gem::Dependency
67
44
  type: :runtime
68
45
  prerelease: false
69
- requirement: &id004 !ruby/object:Gem::Requirement
46
+ version_requirements: *2160590320
47
+ - !ruby/object:Gem::Dependency
48
+ name: json
49
+ requirement: &2160588440 !ruby/object:Gem::Requirement
70
50
  none: false
71
- requirements:
51
+ requirements:
72
52
  - - ~>
73
- - !ruby/object:Gem::Version
74
- hash: 3
75
- segments:
76
- - 1
77
- - 5
78
- - 0
53
+ - !ruby/object:Gem::Version
79
54
  version: 1.5.0
80
- version_requirements: *id004
81
- name: json
82
- - !ruby/object:Gem::Dependency
83
55
  type: :runtime
84
56
  prerelease: false
85
- requirement: &id005 !ruby/object:Gem::Requirement
57
+ version_requirements: *2160588440
58
+ - !ruby/object:Gem::Dependency
59
+ name: rubyzip
60
+ requirement: &2160586960 !ruby/object:Gem::Requirement
86
61
  none: false
87
- requirements:
62
+ requirements:
88
63
  - - ~>
89
- - !ruby/object:Gem::Version
90
- hash: 51
91
- segments:
92
- - 0
93
- - 9
94
- - 4
64
+ - !ruby/object:Gem::Version
95
65
  version: 0.9.4
96
- version_requirements: *id005
97
- name: rubyzip
98
- - !ruby/object:Gem::Dependency
99
66
  type: :runtime
100
67
  prerelease: false
101
- requirement: &id006 !ruby/object:Gem::Requirement
68
+ version_requirements: *2160586960
69
+ - !ruby/object:Gem::Dependency
70
+ name: uuidtools
71
+ requirement: &2160585460 !ruby/object:Gem::Requirement
102
72
  none: false
103
- requirements:
104
- - - ">="
105
- - !ruby/object:Gem::Version
106
- hash: 9
107
- segments:
108
- - 2
109
- - 1
110
- - 1
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
111
76
  version: 2.1.1
112
- version_requirements: *id006
113
- name: uuidtools
114
- - !ruby/object:Gem::Dependency
115
77
  type: :runtime
116
78
  prerelease: false
117
- requirement: &id007 !ruby/object:Gem::Requirement
79
+ version_requirements: *2160585460
80
+ - !ruby/object:Gem::Dependency
81
+ name: redis
82
+ requirement: &2160556320 !ruby/object:Gem::Requirement
118
83
  none: false
119
- requirements:
120
- - - ">="
121
- - !ruby/object:Gem::Version
122
- hash: 7
123
- segments:
124
- - 2
125
- - 2
126
- - 0
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
127
87
  version: 2.2.0
128
- version_requirements: *id007
129
- name: redis
130
- - !ruby/object:Gem::Dependency
131
88
  type: :runtime
132
89
  prerelease: false
133
- requirement: &id008 !ruby/object:Gem::Requirement
90
+ version_requirements: *2160556320
91
+ - !ruby/object:Gem::Dependency
92
+ name: resque
93
+ requirement: &2160555260 !ruby/object:Gem::Requirement
134
94
  none: false
135
- requirements:
95
+ requirements:
136
96
  - - ~>
137
- - !ruby/object:Gem::Version
138
- hash: 95
139
- segments:
140
- - 1
141
- - 18
142
- - 0
143
- version: 1.18.0
144
- version_requirements: *id008
145
- name: resque
146
- - !ruby/object:Gem::Dependency
97
+ - !ruby/object:Gem::Version
98
+ version: 1.19.0
147
99
  type: :runtime
148
100
  prerelease: false
149
- requirement: &id009 !ruby/object:Gem::Requirement
101
+ version_requirements: *2160555260
102
+ - !ruby/object:Gem::Dependency
103
+ name: rest-client
104
+ requirement: &2160553000 !ruby/object:Gem::Requirement
150
105
  none: false
151
- requirements:
106
+ requirements:
152
107
  - - ~>
153
- - !ruby/object:Gem::Version
154
- hash: 13
155
- segments:
156
- - 1
157
- - 6
158
- - 1
108
+ - !ruby/object:Gem::Version
159
109
  version: 1.6.1
160
- version_requirements: *id009
161
- name: rest-client
162
- - !ruby/object:Gem::Dependency
163
110
  type: :runtime
164
111
  prerelease: false
165
- requirement: &id010 !ruby/object:Gem::Requirement
112
+ version_requirements: *2160553000
113
+ - !ruby/object:Gem::Dependency
114
+ name: templater
115
+ requirement: &2160551640 !ruby/object:Gem::Requirement
166
116
  none: false
167
- requirements:
117
+ requirements:
168
118
  - - ~>
169
- - !ruby/object:Gem::Version
170
- hash: 23
171
- segments:
172
- - 1
173
- - 0
174
- - 0
119
+ - !ruby/object:Gem::Version
175
120
  version: 1.0.0
176
- version_requirements: *id010
177
- name: templater
121
+ type: :runtime
122
+ prerelease: false
123
+ version_requirements: *2160551640
178
124
  description: RhoConnect App Integration Server and related command-line utilities
179
125
  email: dev@rhomobile.com
180
- executables:
126
+ executables:
181
127
  - rhoconnect
182
128
  extensions: []
183
-
184
- extra_rdoc_files:
129
+ extra_rdoc_files:
185
130
  - LICENSE
186
131
  - README.md
187
- files:
132
+ files:
188
133
  - CHANGELOG.md
189
134
  - CREDITS
190
135
  - Gemfile
@@ -265,6 +210,7 @@ files:
265
210
  - doc/benchmarks.txt
266
211
  - doc/blob-sync.txt
267
212
  - doc/bulk-sync.txt
213
+ - doc/client-objc.txt
268
214
  - doc/client.txt
269
215
  - doc/command-line.txt
270
216
  - doc/contributing.txt
@@ -292,7 +238,6 @@ files:
292
238
  - doc/web-console.txt
293
239
  - examples/simple/application.rb
294
240
  - examples/simple/config.ru
295
- - examples/simple/dump.rdb
296
241
  - examples/simple/Rakefile
297
242
  - examples/simple/settings/license.key
298
243
  - examples/simple/settings/settings.yml
@@ -561,38 +506,32 @@ files:
561
506
  - bin/rhoconnect
562
507
  homepage: http://rhomobile.com/products/rhoconnect
563
508
  licenses: []
564
-
565
509
  post_install_message:
566
510
  rdoc_options: []
567
-
568
- require_paths:
511
+ require_paths:
569
512
  - lib
570
- required_ruby_version: !ruby/object:Gem::Requirement
513
+ required_ruby_version: !ruby/object:Gem::Requirement
571
514
  none: false
572
- requirements:
573
- - - ">="
574
- - !ruby/object:Gem::Version
575
- hash: 3
576
- segments:
515
+ requirements:
516
+ - - ! '>='
517
+ - !ruby/object:Gem::Version
518
+ version: '0'
519
+ segments:
577
520
  - 0
578
- version: "0"
579
- required_rubygems_version: !ruby/object:Gem::Requirement
521
+ hash: -2200436175486104004
522
+ required_rubygems_version: !ruby/object:Gem::Requirement
580
523
  none: false
581
- requirements:
582
- - - ">="
583
- - !ruby/object:Gem::Version
584
- hash: 3
585
- segments:
586
- - 0
587
- version: "0"
524
+ requirements:
525
+ - - ! '>='
526
+ - !ruby/object:Gem::Version
527
+ version: '0'
588
528
  requirements: []
589
-
590
529
  rubyforge_project:
591
530
  rubygems_version: 1.8.10
592
531
  signing_key:
593
532
  specification_version: 3
594
533
  summary: RhoConnect App Integration Server
595
- test_files:
534
+ test_files:
596
535
  - spec/api/admin/api_token_spec.rb
597
536
  - spec/api/admin/get_api_token_spec.rb
598
537
  - spec/api/admin/get_license_info_spec.rb
Binary file