rhoconnect 4.0.0.beta.12 → 4.0.0.beta.24

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 (88) hide show
  1. data/CHANGELOG.md +34 -0
  2. data/Gemfile +5 -8
  3. data/Gemfile.lock +34 -32
  4. data/Rakefile +2 -12
  5. data/bench/run_bench.sh +1 -1
  6. data/bench/spec/bench_spec_helper.rb +3 -5
  7. data/bin/rhoconnect +20 -13
  8. data/commands/dtach/dtach_install.rb +3 -3
  9. data/commands/generators/update.rb +1 -0
  10. data/commands/parser.rb +180 -0
  11. data/commands/rhoconnect/config.rb +8 -4
  12. data/commands/rhoconnect/get_token.rb +3 -1
  13. data/commands/rhoconnect/routes.rb +34 -0
  14. data/commands/rhoconnect/secret.rb +1 -1
  15. data/commands/rhoconnect/set_admin_password.rb +2 -1
  16. data/commands/rhoconnect/startbg.rb +4 -4
  17. data/commands/rhoconnect/stop.rb +2 -2
  18. data/commands/rhoconnect_console/console.rb +6 -6
  19. data/commands/rhoconnect_spec/spec.rb +2 -1
  20. data/commands/rhoconnect_war/war.rb +1 -0
  21. data/commands/utilities/redis_runner.rb +2 -2
  22. data/doc/data-partitioning.txt +20 -7
  23. data/doc/extending-rhoconnect-server.txt +36 -7
  24. data/doc/push-client-setup-rps.txt +3 -3
  25. data/doc/source-adapters-js.txt +41 -4
  26. data/doc/source-adapters.txt +3 -0
  27. data/generators/templates/application/rcgemfile +1 -5
  28. data/generators/templates/application/spec/spec_helper.rb +0 -9
  29. data/generators/templates/source/models/js/model.js +8 -0
  30. data/generators/templates/source/models/ruby/model.rb +5 -11
  31. data/install.sh +2 -2
  32. data/installer/unix-like/rho_connect_install_constants.rb +3 -3
  33. data/installer/utils/delete_from_s3.rb +3 -6
  34. data/installer/utils/download_from_s3.rb +5 -9
  35. data/installer/utils/verify_checksum.rb +16 -11
  36. data/js-adapters/ballroom.js +9 -0
  37. data/js-adapters/exceptions.js +60 -0
  38. data/js-adapters/node.rb +14 -5
  39. data/js-adapters/node_channel.rb +68 -48
  40. data/js-adapters/rhoconnect_helpers.js +8 -2
  41. data/js-adapters/router.js +16 -14
  42. data/lib/rhoconnect.rb +5 -5
  43. data/lib/rhoconnect/client.rb +2 -2
  44. data/lib/rhoconnect/condition/add_parameter.rb +21 -0
  45. data/lib/rhoconnect/controller/clients_controller.rb +1 -1
  46. data/lib/rhoconnect/controller/js_base.rb +1 -2
  47. data/lib/rhoconnect/controller/system_controller.rb +33 -10
  48. data/lib/rhoconnect/db_adapter.rb +1 -1
  49. data/lib/rhoconnect/document.rb +11 -3
  50. data/lib/rhoconnect/handler/changes.rb +20 -19
  51. data/lib/rhoconnect/handler/changes/engine.rb +48 -25
  52. data/lib/rhoconnect/handler/changes/hooks.rb +36 -0
  53. data/lib/rhoconnect/handler/changes/runner.rb +12 -2
  54. data/lib/rhoconnect/handler/helpers.rb +4 -4
  55. data/lib/rhoconnect/jobs/source_job.rb +1 -1
  56. data/lib/rhoconnect/model/base.rb +32 -8
  57. data/lib/rhoconnect/model/helpers.rb +15 -0
  58. data/lib/rhoconnect/model/helpers/find_duplicates_on_update.rb +85 -0
  59. data/lib/rhoconnect/model/js_base.rb +23 -28
  60. data/lib/rhoconnect/server.rb +23 -18
  61. data/lib/rhoconnect/source.rb +10 -17
  62. data/lib/rhoconnect/store.rb +36 -57
  63. data/lib/rhoconnect/test_methods.rb +5 -4
  64. data/lib/rhoconnect/utilities.rb +7 -5
  65. data/lib/rhoconnect/version.rb +2 -2
  66. data/lib/rhoconnect/web-console/server.rb +17 -16
  67. data/rhoconnect.gemspec +23 -24
  68. data/spec/apps/rhotestapp/controllers/js/js_sample_controller.js +4 -0
  69. data/spec/apps/rhotestapp/models/js/js_sample.js +36 -0
  70. data/spec/apps/rhotestapp/models/ruby/sample_adapter.rb +34 -19
  71. data/spec/async_spec.rb +1 -1
  72. data/spec/cli/cli_spec.rb +69 -31
  73. data/spec/client_sync_spec.rb +30 -13
  74. data/spec/controllers/js_base_spec.rb +10 -4
  75. data/spec/jobs/source_job_spec.rb +1 -1
  76. data/spec/models/{js_model_spec.rb → js_base_spec.rb} +63 -13
  77. data/spec/server/server_spec.rb +20 -0
  78. data/spec/server/stats_spec.rb +7 -17
  79. data/spec/source_adapter_spec.rb +6 -0
  80. data/spec/source_sync_spec.rb +219 -54
  81. data/spec/spec_helper.rb +8 -13
  82. data/spec/store_spec.rb +6 -4
  83. data/spec/test_methods_spec.rb +4 -4
  84. metadata +14 -27
  85. data/commands/execute.rb +0 -48
  86. data/commands/utilities/utilities.rb +0 -6
  87. data/generators/templates/application/controllers/application_controller.rb +0 -17
  88. data/lib/rhoconnect/js_adapter.rb +0 -79
@@ -1,4 +1,4 @@
1
-
1
+ var exceptions = require('./exceptions');
2
2
 
3
3
  var stashResult = function(resp){
4
4
  var json = {};
@@ -58,4 +58,10 @@ var Store = function(){
58
58
  exports.stashResult = stashResult;
59
59
  exports.getData = getData;
60
60
  exports.source = source;
61
- module.exports.Store = new Store();
61
+ module.exports.Store = new Store();
62
+ module.exports.Exception = exceptions.Exception;
63
+ module.exports.LoginException = exceptions.LoginException;
64
+ module.exports.LogoffException = exceptions.LogoffException;
65
+ module.exports.ServerTimeoutException = exceptions.ServerTimeoutException;
66
+ module.exports.ServerErrorException = exceptions.ServerErrorException;
67
+ module.exports.ObjectConflictErrorException = exceptions.ObjectConflictErrorException;
@@ -1,7 +1,7 @@
1
1
  var Response = require('./response');
2
2
  var Request = require('./request');
3
3
 
4
- var router = function(json){
4
+ var router = function(json,send){
5
5
  switch(json['route']){
6
6
  case 'request':
7
7
  try {
@@ -23,34 +23,36 @@ var router = function(json){
23
23
  else{
24
24
  model_dir = process.cwd() + "/models/js/";
25
25
  }
26
- //console.error("path is: ******* " + model_dir + json['klss'] + '.js');
27
26
  var mod = require(model_dir + json['klss'] + '.js');
28
27
  mod[json['function']](resp1);
29
28
  }
30
29
  else{
31
- //console.error("reg routes are: " + registeredRoutes[json['url']]);
32
30
  registeredRoutes[json['url']](request,resp1);
33
31
  }
34
32
  break;
35
33
  }
36
34
  catch(e){
37
- console.error("Node.js error caught: "+ e);
38
- console.error("Backtrace: " + e.stack);
39
- resp1.exception = {"error": e};
35
+ console.error(e.stack || e.toString());
36
+ resp1.exception = {"error": {"error_type": e.name, "message": e.message, "stacktrace": e.stack} };
40
37
  resp1.send(null);
41
38
  }
42
39
  break;
43
40
  case 'response':
44
- //console.error("result callback is: " + json['callback'])
45
- var cback = json['callback'];
46
- json['callback'] = undefined;
47
- var resp2 = new Response();
48
- resp2.header = {'request_id':json['request_id'],'route':'response'};
49
- resp2.result = json['result'];
41
+ try {
42
+ var cback = json['callback'];
43
+ json['callback'] = undefined;
44
+ var resp2 = new Response();
45
+ resp2.header = {'request_id':json['request_id'],'route':'response'};
46
+ resp2.result = json['result'];
50
47
 
51
48
 
52
- rhoconnectCallbacks[cback](resp2);
53
- delete rhoconnectCallbacks[cback];
49
+ rhoconnectCallbacks[cback](resp2);
50
+ delete rhoconnectCallbacks[cback];
51
+ } catch(e) {
52
+ console.error(e.stack || e.toString());
53
+ resp2.exception = {"error": {"error_type": e.name, "message": e.message, "stacktrace": e.stack} };
54
+ resp2.send(null);
55
+ }
54
56
  break;
55
57
  case 'deregister':
56
58
  var br = require('ballroom');
@@ -56,7 +56,7 @@ module Rhoconnect
56
56
  :log_disabled, :license, :bulk_sync_poll_interval, :stats, :appserver, :api_token,
57
57
  :raise_on_expired_lock, :lock_duration, :cookie_expire, :predefined_sources,
58
58
  :connection_pool_size, :connection_pool_timeout, :redis_timeout, :store_key_ttl,
59
- :disable_resque_console, :disable_rc_console, :use_node
59
+ :disable_resque_console, :disable_rc_console, :use_node, :restart_node_on_error
60
60
  end
61
61
 
62
62
  # this mixin adds the controller into the Application's URL Map
@@ -83,7 +83,6 @@ module Rhoconnect
83
83
  end
84
84
  end
85
85
  app_url_map['/'] = Rhoconnect::DefaultServer.new
86
- #puts " and we have URL Map #{app_url_map.inspect}"
87
86
  app_url_map
88
87
  end
89
88
 
@@ -121,6 +120,7 @@ module Rhoconnect
121
120
  Rhoconnect.disable_rc_console ||= false
122
121
  Rhoconnect.disable_resque_console ||= false
123
122
  Rhoconnect.use_node = Rhoconnect.use_node.nil? ? true : Rhoconnect.use_node
123
+ Rhoconnect.restart_node_on_error ||= true if Rhoconnect.use_node
124
124
  if File.directory?(File.join(Rhoconnect.app_directory,'sources'))
125
125
  check_and_add(File.join(Rhoconnect.app_directory,'sources'))
126
126
  # post deprecation warning !!!
@@ -189,8 +189,8 @@ _MIGRATE_TO_NEW_RHOCONNECT
189
189
  Source.update_associations(app.sources)
190
190
  end
191
191
 
192
- def start_nodejs_channels
193
- Node.shell_node
192
+ def start_nodejs_channels(opts = {})
193
+ Node.shell_node(opts)
194
194
  NodeChannel.bootstrap if Node.started
195
195
  end
196
196
 
@@ -383,7 +383,7 @@ _MIGRATE_TO_NEW_RHOCONNECT
383
383
  end
384
384
 
385
385
  def log(*args)
386
- now = Time.now.strftime('%I:%M:%S %p %Y-%m-%d')
386
+ now = Time.now.strftime('%I:%M:%S.%L %p %Y-%m-%d')
387
387
  puts "[#{Process.pid}][#{now}] #{args.join}" unless Rhoconnect.log_disabled
388
388
  end
389
389
 
@@ -97,8 +97,8 @@ module Rhoconnect
97
97
  end
98
98
 
99
99
  def flush_source_documents(source_name)
100
- self.class.valid_doctypes.each do |doctype|
101
- flush_source_data(doctype, source_name)
100
+ self.class.valid_doctypes.each do |docname, doctype|
101
+ flush_source_data(docname, source_name)
102
102
  end
103
103
  end
104
104
 
@@ -0,0 +1,21 @@
1
+ module Rhoconnect
2
+ module Condition
3
+ module AddParameter
4
+ def self.extended(base)
5
+ base.include_add_parameter_condition
6
+ end
7
+
8
+ def include_add_parameter_condition
9
+ set(:add_parameter) do |*args|
10
+ condition do
11
+ if args
12
+ args.each do |argument|
13
+ params[argument[0]] = argument[1]
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -66,7 +66,7 @@ module Rhoconnect
66
66
  Rhoconnect::Stats::Record.update('clientdocs') do
67
67
  c = Client.load(params[:client_id],{:source_name => params[:source_id]})
68
68
  res = {}
69
- Client.valid_doctypes.each do |doc|
69
+ Client.valid_doctypes.each do |doc, doctype|
70
70
  db_key = c.docname(doc)
71
71
  res.merge!(doc => db_key)
72
72
  end
@@ -7,7 +7,6 @@ module Rhoconnect
7
7
  end
8
8
 
9
9
  class JsBase < Rhoconnect::Controller::Base
10
-
11
10
  # Add helpers for deprecated routes
12
11
  Rhoconnect::DefaultServer.helpers Rhoconnect::Controller::JsBaseHelpers
13
12
 
@@ -40,7 +39,7 @@ module Rhoconnect
40
39
  def self.process_defaults(klass,defaults)
41
40
  defaults.each do |default|
42
41
  default.each do |key,val|
43
- klass.send(:set_default,key,val)
42
+ klass.send(:set_default,key.to_sym,val)
44
43
  end
45
44
  end
46
45
  end
@@ -1,5 +1,5 @@
1
1
  module Rhoconnect
2
- module Controller
2
+ module Controller
3
3
  class SystemController < Rhoconnect::Controller::APIBase
4
4
  set_default :admin_required, true
5
5
  set_default :login_required, false
@@ -7,30 +7,53 @@ module Rhoconnect
7
7
  set_default :client_required, false
8
8
 
9
9
  register Rhoconnect::EndPoint
10
-
10
+
11
11
  get "/appserver", \
12
12
  :deprecated_route => {:verb => :post, :url => ['/api/get_adapter', '/api/source/get_adapter']} do
13
13
  {:adapter_url => Rhoconnect.appserver}.to_json
14
14
  end
15
-
15
+
16
16
  post "/appserver", \
17
17
  :deprecated_route => {:verb => :post, :url => ['/api/save_adapter', '/api/source/save_adapter']} do
18
18
  Rhoconnect.appserver = params['adapter_url'] || params[:attributes]['adapter_url']
19
19
  end
20
-
20
+
21
21
  get "/license", \
22
22
  :deprecated_route => {:verb => :post, :url => ['/api/get_license_info', '/api/admin/get_license_info']} do
23
- {:rhoconnect_version => Rhoconnect.license.rhoconnect_version,
24
- :licensee => Rhoconnect.license.licensee,
25
- :seats => Rhoconnect.license.seats,
23
+ {:rhoconnect_version => Rhoconnect.license.rhoconnect_version,
24
+ :licensee => Rhoconnect.license.licensee,
25
+ :seats => Rhoconnect.license.seats,
26
26
  :issued => Rhoconnect.license.issued,
27
27
  :available => Rhoconnect.license.available }.to_json
28
28
  end
29
-
29
+
30
30
  post "/login", :rc_handler => :admin_authenticate, :admin_required => false, :deprecated_route => {:verb => :post, :url => ['/login', '/api/admin/login']} do
31
31
  user = User.authenticate(params[:login], params[:password])
32
32
  end
33
33
 
34
+ # Path used on the RhoConnect instance to handle application credentials
35
+ get "/rps_login", :admin_required => false do
36
+ auth = Rack::Auth::Basic::Request.new(request.env)
37
+ if auth.provided? and auth.basic? and auth.credentials
38
+ login, password = auth.credentials
39
+ settings = get_config(Rhoconnect.base_directory)[Rhoconnect.environment]
40
+ if settings and settings[:push_server]
41
+ url = URI.parse(settings[:push_server])
42
+ app_login = url.user
43
+ app_pwd = url.password.nil? ? '' : url.password
44
+ if login == app_login && password == app_pwd
45
+ status(204)
46
+ else
47
+ raise ApiException.new(401, "Invalid RhoConnect Push server credentials")
48
+ end
49
+ else
50
+ raise ApiException.new(500, "Invalid RhoConnect Push settings")
51
+ end
52
+ else
53
+ raise ApiException.new(401, "Invalid Basic Authorization header")
54
+ end
55
+ end
56
+
34
57
  post "/reset", :deprecated_route => {:verb => :post, :url => ['/api/reset', '/api/admin/reset']} do
35
58
  keep_token = current_user.token.value
36
59
  Store.flush_all
@@ -39,7 +62,7 @@ module Rhoconnect
39
62
  current_user.token = keep_token
40
63
  "DB reset"
41
64
  end
42
-
65
+
43
66
  get "/stats", \
44
67
  :deprecated_route => {:verb => :post, :url => ['/api/stats', '/api/admin/stats']} do
45
68
  if Rhoconnect.stats == true
@@ -51,7 +74,7 @@ module Rhoconnect
51
74
  rtype = Rhoconnect::Stats::Record.rtype(metric)
52
75
  if rtype == 'zset'
53
76
  # returns [] if no results
54
- Rhoconnect::Stats::Record.range(metric,params[:start],params[:finish]).to_json
77
+ Rhoconnect::Stats::Record.range(metric,params[:start],params[:finish]).to_json
55
78
  elsif rtype == 'string'
56
79
  Rhoconnect::Stats::Record.get_value(metric) || ''
57
80
  else
@@ -32,7 +32,7 @@ class DBAdapter
32
32
  self['AutoCommit'] = true
33
33
  end
34
34
  end
35
- else # Ruby 1.8/1.9
35
+ else # Ruby 1.9
36
36
  require 'sqlite3'
37
37
  db = SQLite3::Database.new(dbfile)
38
38
  end
@@ -7,15 +7,23 @@ module Document
7
7
 
8
8
  module ClassMethods
9
9
  def define_valid_doctypes(doctypes = [])
10
- @valid_doctypes ||= Set.new
10
+ @valid_doctypes ||= {}
11
11
  doctypes.each do |doctype|
12
- @valid_doctypes.add(doctype.to_sym)
12
+ @valid_doctypes[doctype.to_sym] = :document
13
+ end
14
+ @enforce_valid_doctypes ||= true
15
+ end
16
+
17
+ def define_valid_queues(queues = [])
18
+ @valid_doctypes ||= {}
19
+ queues.each do |doctype|
20
+ @valid_doctypes[doctype.to_sym] = :queue
13
21
  end
14
22
  @enforce_valid_doctypes ||= true
15
23
  end
16
24
 
17
25
  def valid_doctypes
18
- @valid_doctypes ||= Set.new
26
+ @valid_doctypes ||= {}
19
27
  @valid_doctypes
20
28
  end
21
29
 
@@ -1,30 +1,31 @@
1
- require 'rhoconnect/handler/helpers.rb'
2
- require 'rhoconnect/handler/changes/execute_methods.rb'
3
- require 'rhoconnect/handler/changes/runner.rb'
4
- require 'rhoconnect/handler/changes/pass_through_runner.rb'
5
- require 'rhoconnect/handler/changes/engine.rb'
1
+ require 'rhoconnect/handler/helpers'
2
+ require 'rhoconnect/handler/changes/execute_methods'
3
+ require 'rhoconnect/handler/changes/runner'
4
+ require 'rhoconnect/handler/changes/pass_through_runner'
5
+ require 'rhoconnect/handler/changes/engine'
6
+ require 'rhoconnect/handler/changes/hooks'
6
7
 
7
8
  module Rhoconnect
8
9
  module Handler
9
10
  module Changes
10
11
  def self.registered(app)
11
12
  # CUD
12
- app.post "/", :rc_handler => :cud, :login_required => true, :admin_required => false,
13
- :source_required => true, :client_required => true,
14
- :deprecated_route => {:verb => :post, :url => ['/api/application', '/application', '/api/application/queue_updates']} do
15
- operation = params[:operation]
16
- @model.send operation.to_sym, params["#{operation}_object".to_sym]
17
- end
13
+ app.post "/", :rc_handler => :cud, :login_required => true, :admin_required => false,
14
+ :source_required => true, :client_required => true,
15
+ :deprecated_route => {:verb => :post, :url => ['/api/application', '/application', '/api/application/queue_updates']} do
16
+ operation = params[:operation]
17
+ @model.send operation.to_sym, params["#{operation}_object".to_sym]
18
+ end
18
19
 
19
- app.put "/:id", :rc_handler => :update, :login_required => true, :admin_required => false,
20
- :source_required => true, :client_required => true do
21
- @model.update(params[:update_object])
22
- end
20
+ app.put "/:id", :rc_handler => :update, :login_required => true, :admin_required => false,
21
+ :source_required => true, :client_required => true do
22
+ @model.update(params[:update_object])
23
+ end
23
24
 
24
- app.delete "/:id", :rc_handler => :delete, :login_required => true, :admin_required => false,
25
- :source_required => true, :client_required => true do
26
- @model.delete(params[:delete_object])
27
- end
25
+ app.delete "/:id", :rc_handler => :delete, :login_required => true, :admin_required => false,
26
+ :source_required => true, :client_required => true do
27
+ @model.delete(params[:delete_object])
28
+ end
28
29
  end
29
30
  end
30
31
  end
@@ -135,23 +135,42 @@ module Rhoconnect
135
135
  def _process_cud(operation)
136
136
  # take everything from the queue and erase it
137
137
  # so that no other process will be able to process it again
138
- operation_hashes = []
138
+ operation_data = []
139
139
  client_ids = []
140
- operation_hashes,client_ids = @source.process_queue(operation)
141
- invalid_meta = @model.validate(operation,operation_hashes,client_ids)
140
+ queue_key = params[:queue_key]
141
+ queue_name = (queue_key ? "#{operation}:#{queue_key}" : "#{operation}")
142
+
143
+ operation_data,client_ids = @source.process_queue(queue_name)
144
+ invalid_meta = @model.run_validators(operation,operation_data,client_ids)
145
+
146
+ # load all clients involved in the current queue
147
+ processed_clients = {}
148
+ client_ids.each do |client_id|
149
+ processed_clients[client_id] = Client.load(client_id,{:source_name => @source.name}) unless processed_clients[client_id]
150
+ end
142
151
 
143
152
  errors,links,deletes,creates,dels = {},{},{},{},{}
144
- operation_hashes.each_with_index do |client_operation_data,index|
153
+ operation_data.each_with_index do |client_operation_data,index|
145
154
  client_id = client_ids[index]
155
+ client = processed_clients[client_id]
146
156
 
157
+ # for now - each client operation data can have only one entry (single source CUD)
158
+ # TODO: should be fixed for multi-source CUD
159
+ source_id = client_operation_data[0][0]
160
+ source_operation_data = client_operation_data[0][1]
147
161
  current_invalid_meta = invalid_meta[index] || {}
148
- client_operation_data.each do |key, value|
162
+ current_invalid_source_meta = current_invalid_meta[source_id] || {}
163
+ record_index = 0
164
+ source_operation_data.each do |source_entry|
149
165
  begin
166
+ key = source_entry[0]
167
+ value = source_entry[1]
150
168
  continue_loop = true
151
169
  modified_recs = [{:client_id => client_id, :key => key, :value => value }]
152
- record_invalid_meta = current_invalid_meta[key] || {}
153
- # Remove object from queue
154
- client_operation_data.delete(key)
170
+ record_invalid_meta = current_invalid_source_meta[record_index] || {}
171
+ # remove processed entries
172
+ source_operation_data = source_operation_data.drop(1)
173
+ record_index += 1
155
174
 
156
175
  # skip the rec - if it is a duplicate of some other record
157
176
  next if record_invalid_meta[:duplicate_of]
@@ -166,6 +185,9 @@ module Rhoconnect
166
185
  raise Rhoconnect::Model::ObjectConflictErrorException.new(record_invalid_meta[:error]) if record_invalid_meta[:error]
167
186
 
168
187
  # Call on source adapter to process individual object
188
+ # NOTE: call should be made from the correct model instance
189
+ model.source = Source.load(@source.name,
190
+ {:user_id => client.user_id,:app_id => APP_NAME})
169
191
  case operation
170
192
  when 'create'
171
193
  _process_create(modified_recs,key,value)
@@ -200,16 +222,11 @@ module Rhoconnect
200
222
  end
201
223
 
202
224
  # Record rest of queue (if something in the middle failed)
203
- if not client_operation_data.empty?
204
- @source.push_queue(operation,client_id,client_operation_data,true)
225
+ if not source_operation_data.empty?
226
+ @source.push_queue(queue_name,client_id,[[source_id, source_operation_data]],true)
205
227
  end
206
228
  end
207
229
 
208
- # now, process all the modified docs
209
- processed_clients = {}
210
- client_ids.each do |client_id|
211
- processed_clients[client_id] = Client.load(client_id,{:source_name => @source.name}) unless processed_clients[client_id]
212
- end
213
230
  { "delete_page" => deletes,
214
231
  "#{operation}_links" => links,
215
232
  "#{operation}_errors" => errors }.each do |doctype,client_docs|
@@ -226,12 +243,15 @@ module Rhoconnect
226
243
  client = processed_clients[client_id]
227
244
  client.put_data(:cd,client_doc,true)
228
245
  client.update_count(:cd_size,client_doc.size)
229
- total_creates.merge!(client_doc)
246
+ total_creates[client.user_id] ||= {}
247
+ total_creates[client.user_id].merge!(client_doc)
230
248
  end
231
- unless total_creates.empty?
232
- @source.lock(:md) do |s|
233
- s.put_data(:md,total_creates,true)
234
- s.update_count(:md_size,total_creates.size)
249
+ total_creates.each do |user_id, creates_doc|
250
+ creates_source = Source.load(@source.name,
251
+ {:user_id => user_id,:app_id => APP_NAME})
252
+ creates_source.lock(:md) do |s|
253
+ s.put_data(:md,creates_doc,true)
254
+ s.update_count(:md_size,creates_doc.size)
235
255
  end
236
256
  end
237
257
  end
@@ -245,12 +265,15 @@ module Rhoconnect
245
265
  client = processed_clients[client_id]
246
266
  client.delete_data(:cd,client_doc)
247
267
  client.update_count(:cd_size,-client_doc.size)
248
- total_dels.merge!(client_doc)
268
+ total_dels[client.user_id] ||= {}
269
+ total_dels[client.user_id].merge!(client_doc)
249
270
  end
250
- unless total_dels.empty?
251
- @source.lock(:md) do |s|
252
- s.delete_data(:md,total_dels)
253
- s.update_count(:md_size,-total_dels.size)
271
+ total_dels.each do |user_id, dels_doc|
272
+ dels_source = Source.load(@source.name,
273
+ {:user_id => user_id,:app_id => APP_NAME})
274
+ dels_source.lock(:md) do |s|
275
+ s.delete_data(:md,dels_doc)
276
+ s.update_count(:md_size,-dels_doc.size)
254
277
  end
255
278
  end
256
279
  end