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

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