rhoconnect 3.3.6 → 3.4.2

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.
Files changed (152) hide show
  1. data/CHANGELOG.md +40 -4
  2. data/Gemfile +2 -2
  3. data/Gemfile.lock +27 -25
  4. data/bench/benchapp/Gemfile +7 -27
  5. data/bench/benchapp/config.ru +9 -31
  6. data/bench/blobapp/Gemfile +7 -27
  7. data/bench/blobapp/config.ru +9 -29
  8. data/bench/lib/bench.rb +8 -1
  9. data/bench/lib/bench/test_data.rb +4 -1
  10. data/bench/scripts/blob_cud_script.rb +4 -0
  11. data/bench/scripts/cud_script.rb +7 -1
  12. data/bench/scripts/helpers.rb +1 -1
  13. data/bench/scripts/test_query_script.rb +20 -7
  14. data/bench/spec/bench_spec_helper.rb +3 -1
  15. data/bin/rhoconnect +22 -12
  16. data/commands/{commands/dtach_commands → dtach}/dtach_about.rb +0 -0
  17. data/commands/{commands/dtach_commands → dtach}/dtach_install.rb +0 -0
  18. data/commands/{commands/redis_commands → dtach}/redis_attach.rb +0 -0
  19. data/commands/execute.rb +14 -15
  20. data/commands/generators/update.rb +26 -0
  21. data/commands/{commands/redis_commands → redis}/redis_about.rb +0 -0
  22. data/commands/redis/redis_download.rb +13 -0
  23. data/commands/redis/redis_install.rb +26 -0
  24. data/commands/{commands/redis_commands → redis}/redis_make.rb +0 -0
  25. data/commands/{commands/redis_commands → redis}/redis_restart.rb +3 -2
  26. data/commands/{commands/redis_commands → redis}/redis_start.rb +0 -0
  27. data/commands/{commands/redis_commands → redis}/redis_startbg.rb +0 -0
  28. data/commands/{commands/redis_commands → redis}/redis_stop.rb +3 -2
  29. data/commands/{commands/rhoconnect → rhoconnect}/clean_start.rb +0 -0
  30. data/commands/{commands/rhoconnect → rhoconnect}/config.rb +7 -2
  31. data/commands/{commands/rhoconnect → rhoconnect}/create_user.rb +0 -0
  32. data/commands/{commands/rhoconnect → rhoconnect}/delete_device.rb +0 -0
  33. data/commands/{commands/rhoconnect → rhoconnect}/delete_user.rb +0 -0
  34. data/commands/{commands/rhoconnect → rhoconnect}/flushdb.rb +4 -4
  35. data/commands/{commands/rhoconnect → rhoconnect}/get_token.rb +0 -0
  36. data/commands/{commands/rhoconnect → rhoconnect}/reset.rb +0 -0
  37. data/commands/{commands/rhoconnect → rhoconnect}/reset_refresh.rb +0 -0
  38. data/commands/{commands/rhoconnect → rhoconnect}/restart.rb +0 -0
  39. data/commands/{commands/rhoconnect → rhoconnect}/secret.rb +0 -0
  40. data/commands/{commands/rhoconnect → rhoconnect}/set_admin_password.rb +0 -0
  41. data/commands/{commands/rhoconnect → rhoconnect}/spec.rb +0 -0
  42. data/commands/rhoconnect/start.rb +27 -0
  43. data/commands/{commands/rhoconnect → rhoconnect}/startbg.rb +0 -0
  44. data/commands/{commands/rhoconnect → rhoconnect}/startdebug.rb +2 -2
  45. data/commands/{commands/rhoconnect → rhoconnect}/stop.rb +3 -4
  46. data/commands/{commands/rhoconnect → rhoconnect}/version.rb +0 -0
  47. data/commands/{commands/rhoconnect → rhoconnect}/web.rb +0 -0
  48. data/commands/rhoconnect_attach/attach.rb +10 -0
  49. data/commands/rhoconnect_console/console.rb +16 -0
  50. data/commands/{commands/rhoconnect → rhoconnect_console}/console_helper.rb +0 -0
  51. data/commands/{commands/rhoconnect → rhoconnect_war}/war.rb +0 -0
  52. data/commands/{commands/redis_commands → utilities}/redis_runner.rb +22 -19
  53. data/commands/utilities/utilities.rb +6 -0
  54. data/doc/benchmarks.txt +2 -2
  55. data/doc/bulk-sync.txt +12 -1
  56. data/doc/client-java.txt +3 -3
  57. data/doc/client-objc.txt +1 -1
  58. data/doc/client.txt +5 -5
  59. data/doc/command-line.txt +80 -135
  60. data/doc/deploying.txt +119 -12
  61. data/doc/extending-rhoconnect-server.txt +1 -1
  62. data/doc/heroku-addon.txt +119 -23
  63. data/doc/install.txt +101 -39
  64. data/doc/java-plugin.txt +2 -2
  65. data/doc/licensing.txt +1 -1
  66. data/doc/plugin-intro.txt +3 -1
  67. data/doc/preparing-production.txt +4 -4
  68. data/doc/public/cli.txt +2 -2
  69. data/doc/push-backend-setup.txt +11 -1
  70. data/doc/push-client-setup.txt +72 -2
  71. data/doc/push-server-setup.txt +129 -8
  72. data/doc/rails-plugin.txt +245 -40
  73. data/doc/rest-api.txt +10 -6
  74. data/doc/rhoconnect-calculator.txt +237 -0
  75. data/doc/rhoconnect-redis-stack.txt +35 -0
  76. data/doc/session-and-configuration.txt +24 -0
  77. data/doc/settings.txt +51 -41
  78. data/doc/source-adapters.txt +45 -45
  79. data/doc/stats-middleware.txt +2 -2
  80. data/doc/supported-platforms.txt +6 -6
  81. data/doc/testing.txt +2 -2
  82. data/doc/tutorial.txt +63 -63
  83. data/examples/simple/Gemfile +7 -35
  84. data/examples/simple/config.ru +8 -26
  85. data/examples/simple/sources/product.rb +6 -6
  86. data/generators/rhoconnect.rb +5 -0
  87. data/generators/templates/application/Gemfile +7 -37
  88. data/generators/templates/application/Rakefile +8 -0
  89. data/generators/templates/application/config.ru +12 -31
  90. data/generators/templates/application/rcgemfile +44 -0
  91. data/generators/templates/application/settings/settings.yml +7 -5
  92. data/install.sh +4 -4
  93. data/installer/unix-like/create_texts.rb +7 -2
  94. data/installer/unix-like/rho_connect_install_constants.rb +2 -2
  95. data/installer/unix-like/rho_connect_install_installers.rb +1 -16
  96. data/lib/rhoconnect.rb +51 -38
  97. data/lib/rhoconnect/api/app/query.rb +4 -1
  98. data/lib/rhoconnect/api/app/search.rb +4 -1
  99. data/lib/rhoconnect/api/client/list_client_docs.rb +3 -1
  100. data/lib/rhoconnect/api/user/ping.rb +1 -5
  101. data/lib/rhoconnect/application/init.rb +43 -0
  102. data/lib/rhoconnect/async.rb +11 -6
  103. data/lib/rhoconnect/client_sync.rb +30 -37
  104. data/lib/rhoconnect/document.rb +4 -0
  105. data/lib/rhoconnect/graph_helper.rb +74 -56
  106. data/lib/rhoconnect/middleware/helpers.rb +4 -0
  107. data/lib/rhoconnect/ping.rb +1 -0
  108. data/lib/rhoconnect/ping/gcm.rb +58 -0
  109. data/lib/rhoconnect/predefined_adapters/bench_adapter.rb +7 -1
  110. data/lib/rhoconnect/source.rb +70 -56
  111. data/lib/rhoconnect/source_sync.rb +33 -5
  112. data/lib/rhoconnect/store.rb +358 -110
  113. data/lib/rhoconnect/user.rb +8 -0
  114. data/lib/rhoconnect/utilities.rb +16 -14
  115. data/lib/rhoconnect/version.rb +1 -1
  116. data/lib/rhoconnect/web-console/models/client.js +1 -1
  117. data/lib/rhoconnect/web-console/public/UNVR67bold.ttf +0 -0
  118. data/lib/rhoconnect/web-console/public/bootstrap.css +6 -0
  119. data/lib/rhoconnect/web-console/public/logo.png +0 -0
  120. data/lib/rhoconnect/web-console/server.rb +13 -11
  121. data/lib/rhoconnect/web-console/templates/index.erb +5 -5
  122. data/lib/rhoconnect/web-console/templates/jqplot.erb +1 -0
  123. data/lib/rhoconnect/web-console/views/doc.js +0 -4
  124. data/lib/rhoconnect/web-console/views/home.js +2 -1
  125. data/lib/rhoconnect/web-console/views/new_ping.js +11 -6
  126. data/lib/rhoconnect/web-console/views/stats.js +9 -5
  127. data/rhoconnect.gemspec +6 -4
  128. data/spec/api/app/fast_update_spec.rb +2 -2
  129. data/spec/api/source/get_source_params_spec.rb +1 -0
  130. data/spec/apps/rhotestapp/settings/settings.yml +5 -5
  131. data/spec/client_sync_spec.rb +3 -14
  132. data/spec/perf/perf_spec_helper.rb +11 -7
  133. data/spec/perf/store_perf_spec.rb +88 -11
  134. data/spec/ping/gcm_spec.rb +99 -0
  135. data/spec/server/server_spec.rb +7 -0
  136. data/spec/server/stats_spec.rb +9 -2
  137. data/spec/source_sync_spec.rb +29 -0
  138. data/spec/spec_helper.rb +40 -38
  139. data/spec/stats/record_spec.rb +18 -9
  140. data/spec/store_spec.rb +128 -19
  141. data/spec/testdata/10000-data.txt +0 -0
  142. data/spec/testdata/5-data.txt +0 -0
  143. data/spec/testdata/5000-data.txt +0 -0
  144. data/tasks/jasmine.rake +1 -0
  145. data/tasks/redis.rake +16 -13
  146. metadata +71 -39
  147. data/commands/commands/redis_commands/redis_download.rb +0 -33
  148. data/commands/commands/redis_commands/redis_install.rb +0 -26
  149. data/commands/commands/rhoconnect/attach.rb +0 -8
  150. data/commands/commands/rhoconnect/console.rb +0 -15
  151. data/commands/commands/rhoconnect/start.rb +0 -18
  152. data/commands/utilities/dtach_installed.rb +0 -10
@@ -2,3 +2,4 @@ require 'rhoconnect/ping/android'
2
2
  require 'rhoconnect/ping/apple'
3
3
  require 'rhoconnect/ping/blackberry'
4
4
  require 'rhoconnect/ping/rhoconnect_push'
5
+ require 'rhoconnect/ping/gcm'
@@ -0,0 +1,58 @@
1
+ require 'rest_client'
2
+
3
+ module Rhoconnect
4
+ class Gcm
5
+ class InvalidApiKey < Exception; end
6
+ class GCMPingError < Exception; end
7
+
8
+ def self.ping(params)
9
+ begin
10
+ gcm_api_key = Rhoconnect.settings[:gcm_api_key]
11
+ raise InvalidApiKey.new("Missing `:gcm_api_key:` option in settings/settings.yml") unless gcm_api_key
12
+
13
+ send_ping_to_device(gcm_api_key, params)
14
+ rescue InvalidApiKey => error
15
+ log error
16
+ log error.backtrace.join("\n")
17
+ raise error
18
+ rescue Exception => error
19
+ log error
20
+ log error.backtrace.join("\n")
21
+ raise error
22
+ end
23
+ end
24
+
25
+ def self.send_ping_to_device(api_key,params)
26
+ RestClient.post(
27
+ 'https://android.googleapis.com/gcm/send', gcm_message(params).to_json,
28
+ :authorization => "key=#{api_key}",
29
+ :content_type => :json
30
+ ) do |response, request, result, &block|
31
+ # return exceptions based on response code & body
32
+ case response.code
33
+ when 200
34
+ if response.body =~ /^Error=(.*)$/
35
+ raise GCMPingError.new("GCM ping error: #{$1 || ''}")
36
+ end
37
+ response.return!(request, result, &block)
38
+ when 401, 403
39
+ raise InvalidApiKey.new("Invalid GCM api key. Obtain new api key from GCM service.")
40
+ end
41
+ end
42
+ end
43
+
44
+ def self.gcm_message(params)
45
+ params.reject! {|k,v| v.nil? || v.length == 0}
46
+ data = {}
47
+ data['registration_ids'] = [params['device_pin'].to_s]
48
+ data['collapse_key'] = (rand * 100000000).to_i.to_s
49
+ data['data'] = {}
50
+ data['data']['do_sync'] = params['sources'] ? params['sources'].join(',') : ''
51
+ data['data']['alert'] = params['message'] if params['message']
52
+ data['data']['vibrate'] = params['vibrate'] if params['vibrate']
53
+ data['data']['sound'] = params['sound'] if params['sound']
54
+ data['data']['phone_id'] = params['phone_id'] if params['phone_id']
55
+ data
56
+ end
57
+ end
58
+ end
@@ -57,7 +57,13 @@ module Rhoconnect
57
57
  end
58
58
 
59
59
  def db_name
60
- "test_db_storage:#{@source.app_id}:#{@source.user_id}"
60
+ res = ''
61
+ if @source.user_id[0..1] == 'nq'
62
+ res = "test_db_storage:#{@source.app_id}:nquser"
63
+ else
64
+ res = "test_db_storage:#{@source.app_id}:benchuser"
65
+ end
66
+ res
61
67
  end
62
68
 
63
69
  def lock_name
@@ -4,10 +4,10 @@ module Rhoconnect
4
4
  @@string_fields = []
5
5
  @@integer_fields = []
6
6
  attr_accessor :id
7
-
7
+
8
8
  class << self
9
9
  attr_accessor :validates_presence
10
-
10
+
11
11
  def create(fields,params)
12
12
  if self.validates_presence
13
13
  self.validates_presence.each do |field|
@@ -15,12 +15,12 @@ module Rhoconnect
15
15
  end
16
16
  end
17
17
  end
18
-
18
+
19
19
  def define_fields(string_fields = [], integer_fields = [])
20
20
  @@string_fields,@@integer_fields = string_fields,integer_fields
21
21
  integer_fields.each do |attrib|
22
22
  define_method("#{attrib}=") do |value|
23
- value = (value.nil?) ? nil : value.to_i
23
+ value = (value.nil?) ? nil : value.to_i
24
24
  @@model_data[self.name.to_sym][attrib.to_sym] = value
25
25
  end
26
26
  define_method("#{attrib}") do
@@ -34,7 +34,7 @@ module Rhoconnect
34
34
  if attrib == :name
35
35
  instance_variable_set(:@name, value)
36
36
  name = value
37
- else
37
+ else
38
38
  name = self.name
39
39
  end
40
40
  @@model_data[name.to_sym] ||= {} # TODO: shouldn't be nil here
@@ -47,14 +47,14 @@ module Rhoconnect
47
47
  @@integer_fields << :poll_interval unless @@integer_fields.include?(:poll_interval)
48
48
  end
49
49
  end
50
-
50
+
51
51
  def validates_presence_of(*names)
52
52
  self.validates_presence ||= []
53
53
  names.each do |name|
54
54
  self.validates_presence << name
55
55
  end
56
56
  end
57
-
57
+
58
58
  def is_exist?(id)
59
59
  !@@model_data[id.to_sym].nil?
60
60
  end
@@ -67,14 +67,14 @@ module Rhoconnect
67
67
  downcase
68
68
  end
69
69
  end
70
-
70
+
71
71
  def update_fields(fields)
72
72
  fields.each do |name,value|
73
- arg = "#{name}=".to_sym
73
+ arg = "#{name}=".to_sym
74
74
  self.send(arg, value)
75
75
  end
76
76
  end
77
-
77
+
78
78
  def to_array
79
79
  res = []
80
80
  @@string_fields.each do |field|
@@ -86,24 +86,24 @@ module Rhoconnect
86
86
  res
87
87
  end
88
88
  end
89
-
89
+
90
90
  class Source < MemoryModel
91
91
  attr_accessor :app_id, :user_id
92
-
92
+
93
93
  validates_presence_of :name
94
-
94
+
95
95
  include Document
96
96
  include LockOps
97
-
97
+
98
98
  # source fields
99
- define_fields([:id, :rho__id, :name, :url, :login, :password, :callback_url, :partition_type, :sync_type,
100
- :queue, :query_queue, :cud_queue, :belongs_to, :has_many, :pass_through], [:source_id, :priority, :retry_limit, :simulate_time])
101
-
99
+ define_fields([:id, :rho__id, :name, :url, :login, :password, :callback_url, :partition_type, :sync_type,
100
+ :queue, :query_queue, :cud_queue, :belongs_to, :has_many, :pass_through, :push_notify], [:source_id, :priority, :retry_limit, :simulate_time])
101
+
102
102
  def initialize(fields)
103
103
  self.name = fields['name'] || fields[:name]
104
104
  update_fields(fields)
105
105
  end
106
-
106
+
107
107
  def self.set_defaults(fields)
108
108
  fields[:url] ||= ''
109
109
  fields[:login] ||= ''
@@ -118,8 +118,9 @@ module Rhoconnect
118
118
  fields[:schema] = fields[:schema].to_json if fields[:schema]
119
119
  fields[:retry_limit] = fields[:retry_limit] ? fields[:retry_limit] : 0
120
120
  fields[:simulate_time] = fields[:simulate_time] ? fields[:simulate_time] : 0
121
+ fields[:push_notify] = fields[:push_notify] ? fields[:push_notify] : 'false'
121
122
  end
122
-
123
+
123
124
  def self.create(fields,params)
124
125
  fields = fields.with_indifferent_access # so we can access hash keys as symbols
125
126
  super(fields,params)
@@ -129,23 +130,23 @@ module Rhoconnect
129
130
  obj.assign_args(params)
130
131
  obj
131
132
  end
132
-
133
+
133
134
  def self.load(obj_id,params)
134
135
  validate_attributes(params)
135
-
136
- # if source is pre-defined
136
+
137
+ # if source is pre-defined
137
138
  # create it dynamically here
138
139
  Rhoconnect.create_predefined_source(obj_id,params)
139
-
140
+
140
141
  model_hash = @@model_data[obj_id.to_sym]
141
142
  obj = new(model_hash) if model_hash
142
143
  if obj
143
144
  obj = obj.dup
144
- obj.assign_args(params)
145
+ obj.assign_args(params)
145
146
  end
146
147
  obj
147
148
  end
148
-
149
+
149
150
  def self.update_associations(sources)
150
151
  params = {:app_id => APP_NAME,:user_id => '*'}
151
152
  sources.each { |source| Source.load(source, params).has_many = nil }
@@ -168,7 +169,7 @@ module Rhoconnect
168
169
  end
169
170
  end
170
171
  end
171
-
172
+
172
173
  def self.delete_all
173
174
  params = {:app_id => APP_NAME,:user_id => '*'}
174
175
  @@model_data.each { |k,v| Source.load(k,params).flash_store_data }
@@ -177,9 +178,9 @@ module Rhoconnect
177
178
 
178
179
  def assign_args(params)
179
180
  self.user_id = params[:user_id]
180
- self.app_id = params[:app_id]
181
+ self.app_id = params[:app_id]
181
182
  end
182
-
183
+
183
184
  def blob_attribs
184
185
  return '' unless self.schema
185
186
  schema = JSON.parse(self.schema)
@@ -189,62 +190,62 @@ module Rhoconnect
189
190
  if values.include?('blob')
190
191
  attrib = key.dup
191
192
  attrib << "," + (values.include?('overwrite') ? '1' : '0')
192
- blob_attribs << attrib
193
+ blob_attribs << attrib
193
194
  end
194
195
  end
195
196
  blob_attribs.sort.join(',')
196
197
  end
197
-
198
+
198
199
  def update(fields)
199
200
  fields = fields.with_indifferent_access # so we can access hash keys as symbols
200
201
  self.class.set_defaults(fields)
201
202
  end
202
-
203
+
203
204
  def clone(src_doctype,dst_doctype)
204
205
  Store.clone(docname(src_doctype),docname(dst_doctype))
205
206
  end
206
-
207
+
207
208
  def poll_interval
208
209
  value = Store.get_value(poll_interval_key)
209
210
  value ? value.to_i : nil
210
211
  end
211
-
212
+
212
213
  def poll_interval=(interval)
213
214
  Store.put_value(poll_interval_key, interval)
214
215
  end
215
-
216
+
216
217
  # Return the user associated with a source
217
218
  def user
218
219
  User.load(self.user_id)
219
220
  end
220
-
221
+
221
222
  # Return the app the source belongs to
222
223
  def app
223
224
  App.load(self.app_id)
224
225
  end
225
-
226
+
226
227
  def schema
227
228
  self.get_value(:schema)
228
229
  end
229
-
230
+
230
231
  def read_state
231
232
  id = {:app_id => self.app_id,:user_id => user_by_partition,
232
233
  :source_name => self.name}
233
234
  load_read_state || ReadState.create(id)
234
235
  end
235
-
236
+
236
237
  def load_read_state
237
238
  id = {:app_id => self.app_id,:user_id => user_by_partition,
238
239
  :source_name => self.name}
239
240
  ReadState.load(id)
240
241
  end
241
-
242
+
242
243
  def delete_user_read_state
243
244
  id = {:app_id => self.app_id,:user_id => user_by_partition,
244
245
  :source_name => self.name}
245
246
  ReadState.delete_user(id)
246
247
  end
247
-
248
+
248
249
  def doc_suffix(doctype)
249
250
  "#{user_by_partition}:#{self.name}:#{doctype.to_s}"
250
251
  end
@@ -259,24 +260,24 @@ module Rhoconnect
259
260
  flash_store_data
260
261
  @@model_data.delete(rho__id.to_sym) if rho__id
261
262
  end
262
-
263
+
263
264
  def partition
264
265
  self.partition_type.to_sym
265
266
  end
266
-
267
+
267
268
  def partition=(value)
268
269
  self.partition_type = value
269
270
  end
270
-
271
+
271
272
  def user_by_partition
272
273
  self.partition.to_sym == :user ? self.user_id : '__shared__'
273
274
  end
274
-
275
+
275
276
  def check_refresh_time
276
- self.poll_interval == 0 or
277
+ self.poll_interval == 0 or
277
278
  (self.poll_interval != -1 and self.read_state.refresh_time <= Time.now.to_i)
278
279
  end
279
-
280
+
280
281
  def if_need_refresh(client_id=nil,params=nil)
281
282
  need_refresh = lock(:md) do |s|
282
283
  check = check_refresh_time
@@ -286,23 +287,23 @@ module Rhoconnect
286
287
  end
287
288
  yield client_id,params if need_refresh
288
289
  end
289
-
290
+
290
291
  def rewind_refresh_time(query_failure)
291
292
  return if self.poll_interval == 0
292
293
  lock(:md) do |s|
293
294
  rewind_time = false
294
- # reset number of retries
295
+ # reset number of retries
295
296
  # and prev_refresh_time on succesfull query
296
297
  # or if last refresh was more than 'poll_interval' time ago
297
298
  if not query_failure or ((Time.now.to_i - self.read_state.prev_refresh_time) >= self.poll_interval)
298
299
  # we need to reset the prev_refresh_time here
299
300
  # otherwise in case of expired poll interval
300
- # and repeating failures - it will reset the counter
301
+ # and repeating failures - it will reset the counter
301
302
  # on every error
302
303
  self.read_state.prev_refresh_time = Time.now.to_i
303
304
  self.read_state.retry_counter = 0
304
305
  end
305
-
306
+
306
307
  # rewind the refresh time on failure
307
308
  # if retry limit is not reached
308
309
  if query_failure
@@ -315,22 +316,35 @@ module Rhoconnect
315
316
  self.read_state.retry_counter = 0
316
317
  end
317
318
  end
318
-
319
+
319
320
  if rewind_time
320
321
  self.read_state.refresh_time = self.read_state.prev_refresh_time
321
322
  end
322
- end
323
+ end
323
324
  end
324
-
325
+
325
326
  def is_pass_through?
326
- self.pass_through and self.pass_through == 'true'
327
+ self.pass_through and self.pass_through.to_s == 'true'
328
+ end
329
+
330
+ def push_notify?
331
+ self.push_notify and self.push_notify.to_s == 'true'
332
+ end
333
+
334
+ def announce_changes
335
+ return unless push_notify?
336
+ # TODO: currently we're not allowing 'Broadcast' push to all users for :app partitioned sources
337
+ return if self.partition.to_sym == :app
338
+
339
+ users = [self.user_id]
340
+ User.ping({'user_id' => users, 'sources' => [self.name]})
327
341
  end
328
-
342
+
329
343
  private
330
344
  def poll_interval_key
331
345
  "source:#{self.name}:poll_interval"
332
346
  end
333
-
347
+
334
348
  def self.validate_attributes(params)
335
349
  raise ArgumentError.new('Missing required attribute user_id') unless params[:user_id]
336
350
  raise ArgumentError.new('Missing required attribute app_id') unless params[:app_id]
@@ -117,13 +117,38 @@ module Rhoconnect
117
117
  @source.put_data(:md, new_objs, true)
118
118
  @source.update_count(:md_size,diff_count)
119
119
  end
120
+ @source.announce_changes
120
121
  end
121
122
 
122
- def fast_update(orig_hash, new_hash, timeout=10,raise_on_expire=false)
123
+ def fast_update(remove_hash, new_hash, timeout=10,raise_on_expire=false)
124
+ return unless ((remove_hash and remove_hash.size > 0) or (new_hash and new_hash.size > 0))
123
125
  @source.lock(:md,timeout,raise_on_expire) do |s|
124
- @source.delete_data(:md, orig_hash)
125
- @source.put_data(:md, new_hash, true)
126
+ # get the objects from DB, remove prev attr data, add new attr data
127
+ update_keys = Set.new
128
+ update_keys += Set.new(remove_hash.keys) if remove_hash
129
+ update_keys += Set.new(new_hash.keys) if new_hash
130
+ objs_to_update = @source.get_objects(:md, update_keys.to_a) || {}
131
+ diff_count = -objs_to_update.size
132
+ # remove old values from DB
133
+ @source.delete_data(:md, objs_to_update)
134
+ # update data
135
+ remove_hash.each do |key, obj|
136
+ next unless objs_to_update[key]
137
+ obj.each do |attrib, value|
138
+ objs_to_update[key].delete(attrib)
139
+ objs_to_update.delete(key) if objs_to_update[key].empty?
140
+ end
141
+ end if remove_hash
142
+ new_hash.each do |key, obj|
143
+ objs_to_update[key] ||= {}
144
+ objs_to_update[key].merge!(obj)
145
+ end if new_hash
146
+ # store new data into DB
147
+ @source.put_data(:md, objs_to_update, true)
148
+ diff_count += objs_to_update.size
149
+ @source.update_count(:md_size,diff_count)
126
150
  end
151
+ @source.announce_changes
127
152
  end
128
153
 
129
154
  def fast_delete(delete_objs, timeout=10,raise_on_expire=false)
@@ -132,6 +157,7 @@ module Rhoconnect
132
157
  @source.delete_data(:md, delete_objs)
133
158
  @source.update_count(:md_size,diff_count)
134
159
  end
160
+ @source.announce_changes
135
161
  end
136
162
 
137
163
  def push_objects(objects,timeout=10,raise_on_expire=false,rebuild_md=true)
@@ -158,7 +184,8 @@ module Rhoconnect
158
184
  end
159
185
 
160
186
  @source.update_count(:md_size,diff_count)
161
- end
187
+ end
188
+ @source.announce_changes
162
189
  end
163
190
 
164
191
  def push_deletes(objects,timeout=10,raise_on_expire=false,rebuild_md=true)
@@ -184,7 +211,8 @@ module Rhoconnect
184
211
  end
185
212
 
186
213
  @source.update_count(:md_size,diff_count)
187
- end
214
+ end
215
+ @source.announce_changes
188
216
  end
189
217
 
190
218
  private