rhosync 2.1.16 → 2.1.17.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +8 -0
- data/Rakefile +0 -1
- data/lib/rhosync.rb +1 -1
- data/lib/rhosync/api/fast_delete.rb +8 -0
- data/lib/rhosync/api/fast_insert.rb +8 -0
- data/lib/rhosync/api/fast_update.rb +8 -0
- data/lib/rhosync/app.rb +0 -3
- data/lib/rhosync/bulk_data/bulk_data.rb +5 -1
- data/lib/rhosync/client_sync.rb +15 -0
- data/lib/rhosync/jobs/bulk_data_job.rb +22 -2
- data/lib/rhosync/server.rb +20 -11
- data/lib/rhosync/source_sync.rb +31 -1
- data/lib/rhosync/stats/middleware.rb +13 -8
- data/lib/rhosync/version.rb +1 -1
- data/spec/api/api_helper.rb +2 -0
- data/spec/api/fast_delete_spec.rb +27 -0
- data/spec/api/fast_insert_spec.rb +28 -0
- data/spec/api/fast_update_spec.rb +51 -0
- data/spec/api/stats_spec.rb +2 -0
- data/spec/client_sync_spec.rb +40 -11
- data/spec/jobs/bulk_data_job_spec.rb +14 -5
- data/spec/perf/bulk_data_perf_spec.rb +1 -0
- data/spec/ping/apple_spec.rb +14 -8
- data/spec/server/server_spec.rb +2 -8
- data/spec/source_sync_spec.rb +20 -8
- data/spec/spec_helper.rb +22 -0
- data/spec/stats/middleware_spec.rb +11 -1
- metadata +54 -60
data/CHANGELOG
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## 2.1.17 (not yet released)
|
2
|
+
* Refactor server middleware. Remove explicit rack dependency. Fix broken rspec examples.
|
3
|
+
* Fixing error with recursive loading of application.rb in ruby-1.8.7 and ree
|
4
|
+
* #28330213 - Implementing fast_insert/update/delete API
|
5
|
+
* #27612327 - Bulk Sync Not Returning Errors from Zendesk ticket #2336
|
6
|
+
* #28219647 - Schema Change Error from Zendesk ticket #2353
|
7
|
+
* #28328057 - Feature Request: Adding a Bulk Data Job after_perform hook from Zendesk ticket #2367
|
8
|
+
|
1
9
|
## 2.1.16
|
2
10
|
* revert rack support for v. 1.4.1 and lock to v. 1.3.6 due to problems with Heroku deployment (Rack 1.4.1 produces 502 error)
|
3
11
|
|
data/Rakefile
CHANGED
@@ -66,7 +66,6 @@ begin
|
|
66
66
|
gemspec.files = FileList["[A-Z]*", "{bench,bin,generators,lib,spec,tasks}/**/*"]
|
67
67
|
|
68
68
|
# TODO: Due to https://www.pivotaltracker.com/story/show/3417862, we can't use JSON 1.4.3
|
69
|
-
gemspec.add_dependency "rack", "~> 1.3.6"
|
70
69
|
gemspec.add_dependency "sinatra", "~> 1.3.1"
|
71
70
|
gemspec.add_dependency "json", "~>1.4.2"
|
72
71
|
gemspec.add_dependency "sqlite3-ruby", "~>1.2.5"
|
data/lib/rhosync.rb
CHANGED
@@ -137,7 +137,7 @@ module Rhosync
|
|
137
137
|
if secret == '<changeme>'
|
138
138
|
log "*"*60+"\n\n"
|
139
139
|
log "WARNING: Change the session secret in config.ru from <changeme> to something secure."
|
140
|
-
log " i.e. running `rake secret` in
|
140
|
+
log " i.e. running `rake rhosync:secret` in your rhosync app directory will generate a secret you could use.\n\n"
|
141
141
|
log "*"*60
|
142
142
|
end
|
143
143
|
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
Server.api :fast_delete do |params,user|
|
2
|
+
source = Source.load(params[:source_id],{:app_id=>APP_NAME,:user_id=>params[:user_id]})
|
3
|
+
source_sync = SourceSync.new(source)
|
4
|
+
timeout = params[:timeout] || 10
|
5
|
+
raise_on_expire = params[:raise_on_expire] || false
|
6
|
+
source_sync.fast_delete(params[:data], timeout,raise_on_expire)
|
7
|
+
'done'
|
8
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
Server.api :fast_insert do |params,user|
|
2
|
+
source = Source.load(params[:source_id],{:app_id=>APP_NAME,:user_id=>params[:user_id]})
|
3
|
+
source_sync = SourceSync.new(source)
|
4
|
+
timeout = params[:timeout] || 10
|
5
|
+
raise_on_expire = params[:raise_on_expire] || false
|
6
|
+
source_sync.fast_insert(params[:data], timeout,raise_on_expire)
|
7
|
+
'done'
|
8
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
Server.api :fast_update do |params,user|
|
2
|
+
source = Source.load(params[:source_id],{:app_id=>APP_NAME,:user_id=>params[:user_id]})
|
3
|
+
source_sync = SourceSync.new(source)
|
4
|
+
timeout = params[:timeout] || 10
|
5
|
+
raise_on_expire = params[:raise_on_expire] || false
|
6
|
+
source_sync.fast_update(params[:delete_data], params[:data],timeout,raise_on_expire)
|
7
|
+
'done'
|
8
|
+
end
|
data/lib/rhosync/app.rb
CHANGED
data/lib/rhosync/client_sync.rb
CHANGED
@@ -256,6 +256,21 @@ module Rhosync
|
|
256
256
|
|
257
257
|
if data and data.completed? and data.dbfiles_exist?
|
258
258
|
client.update_clientdoc(sources)
|
259
|
+
sources.each do |src|
|
260
|
+
s = Source.load(src, {:user_id => client.user_id, :app_id => client.app_id})
|
261
|
+
errordoc = s.docname(:errors)
|
262
|
+
errors = {}
|
263
|
+
Store.lock(errordoc) do
|
264
|
+
errors = Store.get_data(errordoc)
|
265
|
+
end
|
266
|
+
unless errors.empty?
|
267
|
+
# FIXME: :result => :bulk_sync_error, :errors => "#{errors}"
|
268
|
+
log "Bulk sync errors are found in #{src}: #{errors}"
|
269
|
+
# Delete all related bulk files
|
270
|
+
data.delete_files
|
271
|
+
return {:result => :url, :url => ''}
|
272
|
+
end
|
273
|
+
end
|
259
274
|
{:result => :url, :url => data.url}
|
260
275
|
elsif data
|
261
276
|
{:result => :wait}
|
@@ -21,8 +21,8 @@ module Rhosync
|
|
21
21
|
create_hsql_data_file(bulk_data,ts) if Rhosync.blackberry_bulk_sync
|
22
22
|
lap_timer('create_hsql_data_file',timer)
|
23
23
|
log "finished bulk data process"
|
24
|
-
bulk_data.state = :completed
|
25
|
-
bulk_data.refresh_time = Time.now.to_i + Rhosync.bulk_sync_poll_interval
|
24
|
+
#bulk_data.state = :completed
|
25
|
+
#bulk_data.refresh_time = Time.now.to_i + Rhosync.bulk_sync_poll_interval
|
26
26
|
else
|
27
27
|
raise Exception.new("No bulk data found for #{params["data_name"]}")
|
28
28
|
end
|
@@ -33,6 +33,26 @@ module Rhosync
|
|
33
33
|
raise e
|
34
34
|
end
|
35
35
|
end
|
36
|
+
|
37
|
+
def self.after_perform_x(*args)
|
38
|
+
log "BulkDataJob.after_perform_x hook called ..."
|
39
|
+
params = args[0] # 1st parameter is bulk data
|
40
|
+
begin
|
41
|
+
bulk_data = BulkData.load(params["data_name"]) if BulkData.is_exist?(params["data_name"])
|
42
|
+
if bulk_data
|
43
|
+
bulk_data.state = :completed
|
44
|
+
bulk_data.refresh_time = Time.now.to_i + Rhosync.bulk_sync_poll_interval
|
45
|
+
log "BulkDataJob.after_perform_x hook set data state to complete."
|
46
|
+
else
|
47
|
+
raise Exception.new("No bulk data found for #{params["data_name"]}")
|
48
|
+
end
|
49
|
+
rescue Exception => e
|
50
|
+
bulk_data.delete if bulk_data
|
51
|
+
log "Bulk data after_perform_x raised: #{e.message}"
|
52
|
+
log e.backtrace.join("\n")
|
53
|
+
raise e
|
54
|
+
end
|
55
|
+
end
|
36
56
|
|
37
57
|
def self.import_data_to_object_values(db,source)
|
38
58
|
data = source.get_data(:md)
|
data/lib/rhosync/server.rb
CHANGED
@@ -28,13 +28,28 @@ module Rhosync
|
|
28
28
|
set :stats, false
|
29
29
|
|
30
30
|
# default secret
|
31
|
-
|
31
|
+
@secret = '<changeme>'
|
32
32
|
|
33
33
|
# Setup route and mimetype for bulk data downloads
|
34
34
|
# TODO: Figure out why "mime :data, 'application/octet-stream'" doesn't work
|
35
35
|
Rack::Mime::MIME_TYPES['.data'] = 'application/octet-stream'
|
36
36
|
|
37
37
|
include Rhosync
|
38
|
+
|
39
|
+
# Set rhosync middleware
|
40
|
+
set :use_middleware, Proc.new {
|
41
|
+
return false if @middleware_configured # Middleware might be configured only once!
|
42
|
+
|
43
|
+
use Rhosync::BodyContentTypeParser
|
44
|
+
use Rhosync::Stats::Middleware
|
45
|
+
Rhosync::Server.set :secret, @secret unless settings.respond_to?(:secret)
|
46
|
+
use Rack::Session::Cookie,
|
47
|
+
:key => 'rhosync_session',
|
48
|
+
:expire_after => 31536000,
|
49
|
+
:secret => Rhosync::Server.secret
|
50
|
+
|
51
|
+
@middleware_configured ||= true
|
52
|
+
}
|
38
53
|
|
39
54
|
helpers do
|
40
55
|
def request_action
|
@@ -145,19 +160,13 @@ module Rhosync
|
|
145
160
|
|
146
161
|
# hook into new so we can enable middleware
|
147
162
|
def self.new
|
148
|
-
use Rhosync::BodyContentTypeParser
|
149
163
|
if settings.respond_to?(:stats) and settings.send(:stats) == true
|
150
|
-
|
151
|
-
Rhosync.stats = true
|
164
|
+
Rhosync.stats = true
|
152
165
|
else
|
153
|
-
|
154
|
-
|
166
|
+
Rhosync::Server.disable :stats
|
167
|
+
Rhosync.stats = false
|
155
168
|
end
|
156
|
-
|
157
|
-
use Rack::Session::Cookie,
|
158
|
-
:key => 'rhosync_session',
|
159
|
-
:expire_after => 31536000,
|
160
|
-
:secret => Rhosync::Server.secret
|
169
|
+
settings.use_middleware
|
161
170
|
super
|
162
171
|
end
|
163
172
|
|
data/lib/rhosync/source_sync.rb
CHANGED
@@ -81,6 +81,29 @@ module Rhosync
|
|
81
81
|
@source.app_id,@source.user_id,client_id,params)
|
82
82
|
end
|
83
83
|
|
84
|
+
def fast_insert(new_objs, timeout=10,raise_on_expire=false)
|
85
|
+
@source.lock(:md,timeout,raise_on_expire) do |s|
|
86
|
+
diff_count = new_objs.size
|
87
|
+
@source.put_data(:md, new_objs, true)
|
88
|
+
@source.update_count(:md_size,diff_count)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def fast_update(orig_hash, new_hash, timeout=10,raise_on_expire=false)
|
93
|
+
@source.lock(:md,timeout,raise_on_expire) do |s|
|
94
|
+
@source.delete_data(:md, orig_hash)
|
95
|
+
@source.put_data(:md, new_hash, true)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def fast_delete(delete_objs, timeout=10,raise_on_expire=false)
|
100
|
+
@source.lock(:md,timeout,raise_on_expire) do |s|
|
101
|
+
diff_count = -delete_objs.size
|
102
|
+
@source.delete_data(:md, delete_objs)
|
103
|
+
@source.update_count(:md_size,diff_count)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
84
107
|
def push_objects(objects,timeout=10,raise_on_expire=false,rebuild_md=true)
|
85
108
|
@source.lock(:md,timeout,raise_on_expire) do |s|
|
86
109
|
diff_count = 0
|
@@ -259,7 +282,14 @@ module Rhosync
|
|
259
282
|
data = @adapter.send(method)
|
260
283
|
if data
|
261
284
|
@source.put_value(method,data)
|
262
|
-
|
285
|
+
if method == :schema
|
286
|
+
parsed = JSON.parse(data)
|
287
|
+
schema_version = parsed['version']
|
288
|
+
raise "Mandatory version key is not defined in source adapter schema method" if schema_version.nil?
|
289
|
+
@source.put_value("#{method}_sha1",Digest::SHA1.hexdigest(schema_version))
|
290
|
+
else
|
291
|
+
@source.put_value("#{method}_sha1",Digest::SHA1.hexdigest(data))
|
292
|
+
end
|
263
293
|
end
|
264
294
|
end
|
265
295
|
end
|
@@ -6,14 +6,19 @@ module Rhosync
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def call(env)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
9
|
+
if Rhosync.stats || Rhosync::Server.stats
|
10
|
+
start = Time.now.to_f
|
11
|
+
status, headers, body = @app.call(env)
|
12
|
+
finish = Time.now.to_f
|
13
|
+
metric = "http:#{env['REQUEST_METHOD']}:#{env['PATH_INFO']}"
|
14
|
+
source_name = env['rack.request.query_hash']["source_name"] if env['rack.request.query_hash']
|
15
|
+
metric << ":#{source_name}" if source_name
|
16
|
+
Record.save_average(metric,finish - start)
|
17
|
+
[status, headers, body]
|
18
|
+
else
|
19
|
+
status, headers, body = @app.call(env)
|
20
|
+
[status, headers, body]
|
21
|
+
end
|
17
22
|
end
|
18
23
|
end
|
19
24
|
end
|
data/lib/rhosync/version.rb
CHANGED
data/spec/api/api_helper.rb
CHANGED
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhoconnectApiFastDelete" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should delete an object from rhosync's :md" do
|
7
|
+
data = {'1' => @product1, '2' => @product2, '3' => @product3}
|
8
|
+
@s = Source.load(@s_fields[:name],@s_params)
|
9
|
+
set_state(@s.docname(:md) => data,@s.docname(:md_size) => '3')
|
10
|
+
post "/api/fast_delete", :api_token => @api_token,
|
11
|
+
:user_id => @u.id, :source_id => @s_fields[:name], :data => {'3' => @product3}
|
12
|
+
last_response.should be_ok
|
13
|
+
data.delete('3')
|
14
|
+
verify_result(@s.docname(:md) => data,@s.docname(:md_size)=>'2')
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should not properly delete the object if fast_delete is called without all the attributes (because fast_delete doesn't ensure any data integrity)" do
|
18
|
+
data = {'1' => @product1, '2' => @product2, '3' => @product3}
|
19
|
+
delete_data = {'3' => {'price' => '1.99'}}
|
20
|
+
@s = Source.load(@s_fields[:name],@s_params)
|
21
|
+
set_state(@s.docname(:md) => data,@s.docname(:md_size) => '3')
|
22
|
+
post "/api/fast_delete", :api_token => @api_token,
|
23
|
+
:user_id => @u.id, :source_id => @s_fields[:name], :data => delete_data
|
24
|
+
last_response.should be_ok
|
25
|
+
verify_result(@s.docname(:md) => data,@s.docname(:md_size)=>'2')
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhoconnectApiFastInsert" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should append new objects to rhosync's :md" do
|
7
|
+
data = {'1' => @product1, '2' => @product2}
|
8
|
+
@s = Source.load(@s_fields[:name],@s_params)
|
9
|
+
set_state(@s.docname(:md) => data,@s.docname(:md_size) => '2')
|
10
|
+
post "/api/fast_insert", :api_token => @api_token,
|
11
|
+
:user_id => @u.id, :source_id => @s_fields[:name], :data => {'3' => @product3}
|
12
|
+
last_response.should be_ok
|
13
|
+
data.merge!({'3' => @product3})
|
14
|
+
verify_result(@s.docname(:md) => data,@s.docname(:md_size)=>'3')
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should incorrectly append data to existing object (because fast_insert doesn't ensure any data integrity)" do
|
18
|
+
data = {'1' => @product1, '2' => @product2, '3' => @product3}
|
19
|
+
incorrect_insert = {'3' => {'price' => '1.99', 'new_field' => 'value'}}
|
20
|
+
@s = Source.load(@s_fields[:name],@s_params)
|
21
|
+
set_state(@s.docname(:md) => data,@s.docname(:md_size) => '3')
|
22
|
+
post "/api/fast_insert", :api_token => @api_token,
|
23
|
+
:user_id => @u.id, :source_id => @s_fields[:name], :data => incorrect_insert
|
24
|
+
last_response.should be_ok
|
25
|
+
data['3'].merge!(incorrect_insert['3'])
|
26
|
+
verify_result(@s.docname(:md) => data,@s.docname(:md_size)=>'4')
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhoconnectApiFastUpdate" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should update an attribute and add new one for an object in rhosync's :md" do
|
7
|
+
data = {'1' => @product1, '2' => @product2, '3' => @product3}
|
8
|
+
@s = Source.load(@s_fields[:name],@s_params)
|
9
|
+
set_state(@s.docname(:md) => data,@s.docname(:md_size) => '3')
|
10
|
+
|
11
|
+
orig_obj_attrs = {'3' => {'price' => @product3['price']}}
|
12
|
+
new_obj_attrs = {'3' => {'price' => '0.99', 'new_attr' => 'new_value'}}
|
13
|
+
|
14
|
+
post "/api/fast_update", :api_token => @api_token,
|
15
|
+
:user_id => @u.id, :source_id => @s_fields[:name], :delete_data => orig_obj_attrs, :data => new_obj_attrs
|
16
|
+
last_response.should be_ok
|
17
|
+
data['3'].merge!(new_obj_attrs['3'])
|
18
|
+
verify_result(@s.docname(:md) => data,@s.docname(:md_size)=>'3')
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should update one attr, add one attr, and remove one attr for an object in rhosync's :md" do
|
22
|
+
data = {'1' => @product1, '2' => @product2, '3' => @product3}
|
23
|
+
@s = Source.load(@s_fields[:name],@s_params)
|
24
|
+
set_state(@s.docname(:md) => data,@s.docname(:md_size) => '3')
|
25
|
+
|
26
|
+
orig_obj_attrs = {'3' => {'name' => @product3['name'], 'price' => @product3['price']}}
|
27
|
+
new_obj_attrs = {'3' => {'price' => '0.99', 'new_attr' => 'new_value'}}
|
28
|
+
|
29
|
+
post "/api/fast_update", :api_token => @api_token,
|
30
|
+
:user_id => @u.id, :source_id => @s_fields[:name], :delete_data => orig_obj_attrs, :data => new_obj_attrs
|
31
|
+
last_response.should be_ok
|
32
|
+
data['3'].delete('name')
|
33
|
+
data['3'].merge!(new_obj_attrs['3'])
|
34
|
+
verify_result(@s.docname(:md) => data,@s.docname(:md_size)=>'3')
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should remove all attributes , but leave the count incorrect (because fast_update doesn't check if the whole object is deleted)" do
|
38
|
+
data = {'1' => @product1, '2' => @product2, '3' => @product3}
|
39
|
+
@s = Source.load(@s_fields[:name],@s_params)
|
40
|
+
set_state(@s.docname(:md) => data,@s.docname(:md_size) => '3')
|
41
|
+
|
42
|
+
orig_obj_attrs = {'3' => @product3}
|
43
|
+
new_obj_attrs = {}
|
44
|
+
|
45
|
+
post "/api/fast_update", :api_token => @api_token,
|
46
|
+
:user_id => @u.id, :source_id => @s_fields[:name], :delete_data => orig_obj_attrs, :data => new_obj_attrs
|
47
|
+
last_response.should be_ok
|
48
|
+
data.delete('3')
|
49
|
+
verify_result(@s.docname(:md) => data,@s.docname(:md_size)=>'3')
|
50
|
+
end
|
51
|
+
end
|
data/spec/api/stats_spec.rb
CHANGED
@@ -9,10 +9,12 @@ describe "RhosyncApiStats" do
|
|
9
9
|
|
10
10
|
before(:each) do
|
11
11
|
Rhosync::Server.set :stats, true
|
12
|
+
Rhosync.stats = true
|
12
13
|
end
|
13
14
|
|
14
15
|
after(:each) do
|
15
16
|
Rhosync::Server.set :stats, false
|
17
|
+
Rhosync.stats = false
|
16
18
|
end
|
17
19
|
|
18
20
|
it "should retrieve metric names" do
|
data/spec/client_sync_spec.rb
CHANGED
@@ -9,6 +9,9 @@ describe "ClientSync" do
|
|
9
9
|
lambda { ClientSync.new(nil,@c,2) }.should raise_error(ArgumentError,'Unknown source')
|
10
10
|
end
|
11
11
|
|
12
|
+
let(:mock_schema) { {"property" => { "name" => "string", "brand" => "string" }, "version" => "1.0"} }
|
13
|
+
let(:sha1) { get_sha1(mock_schema['version']) }
|
14
|
+
|
12
15
|
before(:each) do
|
13
16
|
@s = Source.load(@s_fields[:name],@s_params)
|
14
17
|
@cs = ClientSync.new(@s,@c,2)
|
@@ -372,7 +375,6 @@ describe "ClientSync" do
|
|
372
375
|
token1.should be_nil
|
373
376
|
Store.get_data(@c.docname(:search)).should == {}
|
374
377
|
end
|
375
|
-
|
376
378
|
end
|
377
379
|
|
378
380
|
describe "page methods" do
|
@@ -380,10 +382,20 @@ describe "ClientSync" do
|
|
380
382
|
Store.put_data(@s.docname(:md),@data).should == true
|
381
383
|
Store.get_data(@s.docname(:md)).should == @data
|
382
384
|
Store.put_value(@s.docname(:md_size),@data.size)
|
383
|
-
|
384
|
-
@cs.compute_page
|
385
|
+
|
386
|
+
progress_count, total_count, res = @cs.compute_page
|
387
|
+
progress_count.to_i.should == 0
|
388
|
+
total_count.to_i.should == 3
|
389
|
+
res.each do |key, value|
|
390
|
+
@data.has_key?(key).should == true
|
391
|
+
@data[key].should == value
|
392
|
+
end
|
393
|
+
|
385
394
|
Store.get_value(@cs.client.docname(:cd_size)).to_i.should == 0
|
386
|
-
Store.get_data(@cs.client.docname(:page)).
|
395
|
+
Store.get_data(@cs.client.docname(:page)).each do |key, value|
|
396
|
+
@data.has_key?(key).should == true
|
397
|
+
@data[key].should == value
|
398
|
+
end
|
387
399
|
end
|
388
400
|
|
389
401
|
it "appends diff to the client document" do
|
@@ -483,7 +495,7 @@ describe "ClientSync" do
|
|
483
495
|
token = @c.get_value(:page_token)
|
484
496
|
result.should == [{"version"=>ClientSync::VERSION},{"token"=>token},
|
485
497
|
{"count"=>1}, {"progress_count"=>0},{"total_count"=>1},{'insert'=>expected}]
|
486
|
-
@c.get_value(:schema_sha1).should ==
|
498
|
+
@c.get_value(:schema_sha1).should == sha1
|
487
499
|
end
|
488
500
|
end
|
489
501
|
|
@@ -494,8 +506,8 @@ describe "ClientSync" do
|
|
494
506
|
token = @c.get_value(:page_token)
|
495
507
|
result.should == [{"version"=>ClientSync::VERSION},{"token"=>token},
|
496
508
|
{"count"=>0}, {"progress_count"=>0},{"total_count"=>0},{'schema-changed'=>'true'}]
|
497
|
-
@c.get_value(:schema_page).should ==
|
498
|
-
@c.get_value(:schema_sha1).should ==
|
509
|
+
@c.get_value(:schema_page).should == sha1
|
510
|
+
@c.get_value(:schema_sha1).should == sha1
|
499
511
|
end
|
500
512
|
end
|
501
513
|
|
@@ -506,8 +518,8 @@ describe "ClientSync" do
|
|
506
518
|
token = @c.get_value(:page_token)
|
507
519
|
@cs.send_cud.should == [{"version"=>ClientSync::VERSION},{"token"=>token},
|
508
520
|
{"count"=>0}, {"progress_count"=>0},{"total_count"=>0},{'schema-changed'=>'true'}]
|
509
|
-
@c.get_value(:schema_page).should ==
|
510
|
-
@c.get_value(:schema_sha1).should ==
|
521
|
+
@c.get_value(:schema_page).should == sha1
|
522
|
+
@c.get_value(:schema_sha1).should == sha1
|
511
523
|
end
|
512
524
|
end
|
513
525
|
|
@@ -519,7 +531,7 @@ describe "ClientSync" do
|
|
519
531
|
@cs.send_cud(token).should == [{"version"=>ClientSync::VERSION},{"token"=>""},
|
520
532
|
{"count"=>0}, {"progress_count"=>0},{"total_count"=>0},{}]
|
521
533
|
@c.get_value(:schema_page).should be_nil
|
522
|
-
@c.get_value(:schema_sha1).should ==
|
534
|
+
@c.get_value(:schema_sha1).should == sha1
|
523
535
|
end
|
524
536
|
end
|
525
537
|
|
@@ -538,7 +550,7 @@ describe "ClientSync" do
|
|
538
550
|
@cs.send_cud(token).should == [{"version"=>ClientSync::VERSION},{"token"=>""},
|
539
551
|
{"count"=>0}, {"progress_count"=>0},{"total_count"=>0},{}]
|
540
552
|
@c.get_value(:schema_page).should be_nil
|
541
|
-
@c.get_value(:schema_sha1).should ==
|
553
|
+
@c.get_value(:schema_sha1).should == sha1
|
542
554
|
data = BulkData.load(docname)
|
543
555
|
data.refresh_time.should <= Time.now.to_i
|
544
556
|
end
|
@@ -574,6 +586,7 @@ describe "ClientSync" do
|
|
574
586
|
set_state('test_db_storage' => @data)
|
575
587
|
ClientSync.bulk_data(:user,@c)
|
576
588
|
BulkDataJob.perform("data_name" => bulk_data_docname(@a.id,@u.id))
|
589
|
+
BulkDataJob.after_perform_x("data_name" => bulk_data_docname(@a.id,@u.id))
|
577
590
|
ClientSync.bulk_data(:user,@c).should == {:result => :url,
|
578
591
|
:url => BulkData.load(bulk_data_docname(@a.id,@u.id)).url}
|
579
592
|
verify_result(
|
@@ -581,6 +594,18 @@ describe "ClientSync" do
|
|
581
594
|
"source:#{@a_fields[:name]}:#{@u_fields[:login]}:#{@s_fields[:name]}:md" => @data,
|
582
595
|
"source:#{@a_fields[:name]}:#{@u_fields[:login]}:#{@s_fields[:name]}:md_copy" => @data)
|
583
596
|
end
|
597
|
+
|
598
|
+
it "should return empty bulk data url if there are errors in query" do
|
599
|
+
ClientSync.bulk_data(:user,@c)
|
600
|
+
BulkDataJob.perform("data_name" => bulk_data_docname(@a.id,@u.id))
|
601
|
+
BulkDataJob.after_perform_x("data_name" => bulk_data_docname(@a.id,@u.id))
|
602
|
+
errordoc = @s.docname(:errors) # source SampleAdapter
|
603
|
+
operation = 'query'
|
604
|
+
Store.lock(errordoc) do
|
605
|
+
Store.put_data(errordoc,{"#{operation}-error"=>{'message'=>"Some exception message"}}, true)
|
606
|
+
end
|
607
|
+
ClientSync.bulk_data(:user,@c).should == {:result => :url, :url => ''}
|
608
|
+
end
|
584
609
|
|
585
610
|
it "should escape bulk data url" do
|
586
611
|
name = 'a b'
|
@@ -590,6 +615,7 @@ describe "ClientSync" do
|
|
590
615
|
:user_id => name,
|
591
616
|
:sources => [@s_fields[:name]])
|
592
617
|
BulkDataJob.perform("data_name" => bulk_data_docname(@a.id,name))
|
618
|
+
BulkDataJob.after_perform_x("data_name" => bulk_data_docname(@a.id,name))
|
593
619
|
data = BulkData.load(bulk_data_docname(@a.id,name))
|
594
620
|
data.url.should match /a%20b/
|
595
621
|
data.delete
|
@@ -600,6 +626,7 @@ describe "ClientSync" do
|
|
600
626
|
@s.partition = :app
|
601
627
|
ClientSync.bulk_data(:app,@c)
|
602
628
|
BulkDataJob.perform("data_name" => bulk_data_docname(@a.id,"*"))
|
629
|
+
BulkDataJob.after_perform_x("data_name" => bulk_data_docname(@a.id,"*"))
|
603
630
|
ClientSync.bulk_data(:app,@c).should == {:result => :url,
|
604
631
|
:url => BulkData.load(bulk_data_docname(@a.id,"*")).url}
|
605
632
|
verify_result(
|
@@ -613,6 +640,7 @@ describe "ClientSync" do
|
|
613
640
|
@s.sync_type = :bulk_sync_only
|
614
641
|
ClientSync.bulk_data(:user,@c)
|
615
642
|
BulkDataJob.perform("data_name" => bulk_data_docname(@a.id,@u.id))
|
643
|
+
BulkDataJob.after_perform_x("data_name" => bulk_data_docname(@a.id,@u.id))
|
616
644
|
ClientSync.bulk_data(:user,@c).should == {:result => :url,
|
617
645
|
:url => BulkData.load(bulk_data_docname(@a.id,@u.id)).url}
|
618
646
|
verify_result(
|
@@ -626,6 +654,7 @@ describe "ClientSync" do
|
|
626
654
|
Rhosync.blackberry_bulk_sync = true
|
627
655
|
ClientSync.bulk_data(:user,@c)
|
628
656
|
BulkDataJob.perform("data_name" => bulk_data_docname(@a.id,@u.id))
|
657
|
+
BulkDataJob.after_perform_x("data_name" => bulk_data_docname(@a.id,@u.id))
|
629
658
|
data = BulkData.load(bulk_data_docname(@a.id,@u.id))
|
630
659
|
ClientSync.bulk_data(:user,@c).should == {:result => :url, :url => data.url}
|
631
660
|
File.delete(data.dbfile)
|
@@ -12,6 +12,8 @@ describe "BulkDataJob" do
|
|
12
12
|
delete_data_directory
|
13
13
|
end
|
14
14
|
|
15
|
+
let(:mock_schema) { {"property" => { "name" => "string", "brand" => "string" }, "version" => "1.0"} }
|
16
|
+
|
15
17
|
it "should create bulk data files from master document" do
|
16
18
|
set_state('test_db_storage' => @data)
|
17
19
|
docname = bulk_data_docname(@a.id,@u.id)
|
@@ -24,6 +26,7 @@ describe "BulkDataJob" do
|
|
24
26
|
:user_id => @u.id,
|
25
27
|
:sources => [@s_fields[:name], 'FixedSchemaAdapter'])
|
26
28
|
BulkDataJob.perform("data_name" => data.name)
|
29
|
+
BulkDataJob.after_perform_x("data_name" => data.name)
|
27
30
|
data = BulkData.load(docname)
|
28
31
|
data.completed?.should == true
|
29
32
|
verify_result(@s.docname(:md) => @data,@s.docname(:md_copy) => @data)
|
@@ -51,6 +54,7 @@ describe "BulkDataJob" do
|
|
51
54
|
:user_id => @u.id,
|
52
55
|
:sources => [@s_fields[:name]])
|
53
56
|
BulkDataJob.perform("data_name" => data.name)
|
57
|
+
BulkDataJob.after_perform_x("data_name" => data.name)
|
54
58
|
data = BulkData.load(docname)
|
55
59
|
data.completed?.should == true
|
56
60
|
verify_result(@s.docname(:md) => @data,@s.docname(:md_copy) => @data)
|
@@ -69,6 +73,7 @@ describe "BulkDataJob" do
|
|
69
73
|
:user_id => @u.id,
|
70
74
|
:sources => [@s_fields[:name]])
|
71
75
|
BulkDataJob.perform("data_name" => data.name)
|
76
|
+
BulkDataJob.after_perform_x("data_name" => data.name)
|
72
77
|
data = BulkData.load(docname)
|
73
78
|
data.completed?.should == true
|
74
79
|
verify_result(@s.docname(:md) => @data,
|
@@ -88,11 +93,11 @@ describe "BulkDataJob" do
|
|
88
93
|
:user_id => @u.id,
|
89
94
|
:sources => [@s_fields[:name]])
|
90
95
|
BulkDataJob.perform("data_name" => data.name)
|
96
|
+
BulkDataJob.after_perform_x("data_name" => data.name)
|
91
97
|
data = BulkData.load(docname)
|
92
98
|
data.completed?.should == true
|
93
|
-
verify_result(@s.docname(:md) => @data,
|
94
|
-
|
95
|
-
@s.docname(:md_copy) => @data)
|
99
|
+
verify_result(@s.docname(:md) => @data, @s.docname(:md_copy) => @data)
|
100
|
+
JSON.parse(Store.get_value(@s.docname(:schema))).should == mock_schema
|
96
101
|
validate_db(data,@s.name => @data).should == true
|
97
102
|
end
|
98
103
|
end
|
@@ -108,7 +113,9 @@ describe "BulkDataJob" do
|
|
108
113
|
end
|
109
114
|
|
110
115
|
it "should delete bulk data if exception is raised" do
|
111
|
-
lambda {
|
116
|
+
lambda {
|
117
|
+
BulkDataJob.perform("data_name" => 'broken')
|
118
|
+
BulkDataJob.after_perform_x("data_name" => data.name) }.should raise_error(Exception)
|
112
119
|
Store.db.keys('bulk_data*').should == []
|
113
120
|
end
|
114
121
|
|
@@ -118,7 +125,9 @@ describe "BulkDataJob" do
|
|
118
125
|
:app_id => 'broken',
|
119
126
|
:user_id => @u.id,
|
120
127
|
:sources => [@s_fields[:name]])
|
121
|
-
lambda {
|
128
|
+
lambda {
|
129
|
+
BulkDataJob.perform("data_name" => data.name)
|
130
|
+
BulkDataJob.after_perform_x("data_name" => data.name) }.should raise_error(Exception)
|
122
131
|
Store.db.keys('bulk_data*').should == []
|
123
132
|
end
|
124
133
|
end
|
@@ -27,6 +27,7 @@ describe "BulkData Performance" do
|
|
27
27
|
:user_id => @u.id,
|
28
28
|
:sources => [@s_fields[:name]])
|
29
29
|
BulkDataJob.perform("data_name" => data.name)
|
30
|
+
BulkDataJob.after_perform_x("data_name" => data.name)
|
30
31
|
lap_timer('BulkDataJob.perform duration',start)
|
31
32
|
end
|
32
33
|
end
|
data/spec/ping/apple_spec.rb
CHANGED
@@ -41,18 +41,24 @@ describe "Ping Apple" do
|
|
41
41
|
end
|
42
42
|
|
43
43
|
it "should compute apn_message" do
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
expected_hash = {
|
45
|
+
"aps"=>{"vibrate"=>"5", "badge"=>5, "alert"=>"hello world", "sound"=>"hello.mp3"},
|
46
|
+
"do_sync"=>["SampleAdapter"]
|
47
|
+
}
|
48
|
+
apn_message = Apple.apn_message(@params)
|
49
|
+
apn_message.start_with?("\000\000 \253\315\000g").should be_true
|
50
|
+
JSON.parse(apn_message.sub("\000\000 \253\315\000g","")).should == expected_hash
|
48
51
|
end
|
49
52
|
|
50
53
|
it "should compute apn_message with source array" do
|
51
54
|
@params['sources'] << 'SimpleAdapter'
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
55
|
+
expected_hash = {
|
56
|
+
"aps"=>{"vibrate"=>"5", "badge"=>5, "alert"=>"hello world", "sound"=>"hello.mp3"},
|
57
|
+
"do_sync"=>["SampleAdapter", "SimpleAdapter"]
|
58
|
+
}
|
59
|
+
apn_message = Apple.apn_message(@params)
|
60
|
+
apn_message.start_with?("\000\000 \253\315\000w").should be_true
|
61
|
+
JSON.parse(apn_message.sub("\000\000 \253\315\000w","")).should == expected_hash
|
56
62
|
end
|
57
63
|
|
58
64
|
it "should raise SocketError if socket fails" do
|
data/spec/server/server_spec.rb
CHANGED
@@ -70,14 +70,6 @@ describe "Server" do
|
|
70
70
|
Rhosync::Server.secret.should == "secure!"
|
71
71
|
end
|
72
72
|
|
73
|
-
it "should use Stats::Middleware if stats enabled" do
|
74
|
-
Rhosync::Server.enable :stats
|
75
|
-
Rhosync::Server.new
|
76
|
-
Rhosync.stats.should == true
|
77
|
-
Rhosync.stats = nil
|
78
|
-
Rhosync::Server.disable :stats
|
79
|
-
end
|
80
|
-
|
81
73
|
it "should update session secret to default" do
|
82
74
|
Rhosync::Server.set :secret, "<changeme>"
|
83
75
|
Rhosync::Server.secret.should == "<changeme>"
|
@@ -380,6 +372,7 @@ describe "Server" do
|
|
380
372
|
set_state('test_db_storage' => @data)
|
381
373
|
get "/application/bulk_data", :partition => :user, :client_id => @c.id
|
382
374
|
BulkDataJob.perform("data_name" => bulk_data_docname(@a.id,@u.id))
|
375
|
+
BulkDataJob.after_perform_x("data_name" => bulk_data_docname(@a.id,@u.id))
|
383
376
|
get "/application/bulk_data", :partition => :user, :client_id => @c.id
|
384
377
|
last_response.should be_ok
|
385
378
|
data = BulkData.load(bulk_data_docname(@a.id,@u.id))
|
@@ -392,6 +385,7 @@ describe "Server" do
|
|
392
385
|
set_state('test_db_storage' => @data)
|
393
386
|
get "/application/bulk_data", :partition => :user, :client_id => @c.id
|
394
387
|
BulkDataJob.perform("data_name" => bulk_data_docname(@a.id,@u.id))
|
388
|
+
BulkDataJob.after_perform_x("data_name" => bulk_data_docname(@a.id,@u.id))
|
395
389
|
get "/application/bulk_data", :partition => :user, :client_id => @c.id
|
396
390
|
get JSON.parse(last_response.body)["url"]
|
397
391
|
last_response.should be_ok
|
data/spec/source_sync_spec.rb
CHANGED
@@ -9,6 +9,8 @@ describe "SourceSync" do
|
|
9
9
|
@ss = SourceSync.new(@s)
|
10
10
|
end
|
11
11
|
|
12
|
+
let(:mock_schema) { {"property" => { "name" => "string", "brand" => "string" }, "version" => "1.0"} }
|
13
|
+
|
12
14
|
it "should create SourceSync" do
|
13
15
|
@ss.adapter.is_a?(SampleAdapter).should == true
|
14
16
|
end
|
@@ -78,12 +80,25 @@ describe "SourceSync" do
|
|
78
80
|
expected = {'1'=>@product1,'2'=>@product2}
|
79
81
|
set_state('test_db_storage' => expected)
|
80
82
|
@ss.process_query
|
81
|
-
verify_result(@s.docname(:md) => expected
|
82
|
-
|
83
|
-
|
83
|
+
verify_result(@s.docname(:md) => expected)
|
84
|
+
JSON.parse(Store.get_value(@s.docname(:schema))).should == mock_schema
|
85
|
+
Store.get_value(@s.docname(:schema_sha1)).should == get_sha1(mock_schema['version'])
|
84
86
|
end
|
85
87
|
end
|
86
|
-
|
88
|
+
|
89
|
+
it "should raise exception if source adapter schema has no version key/value pair" do
|
90
|
+
mock_schema_no_version_method([SampleAdapter]) do
|
91
|
+
expected = {'1'=>@product1,'2'=>@product2}
|
92
|
+
set_state('test_db_storage' => expected)
|
93
|
+
@ss.process_query
|
94
|
+
errordoc = @s.docname(:errors)
|
95
|
+
errors = {}
|
96
|
+
Store.lock(errordoc) { errors = Store.get_data(errordoc) }
|
97
|
+
errors.empty?().should == false
|
98
|
+
errors["query-error"]["message"].should == "Mandatory version key is not defined in source adapter schema method"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
87
102
|
it "should process source adapter with stash" do
|
88
103
|
expected = {'1'=>@product1,'2'=>@product2}
|
89
104
|
set_state('test_db_storage' => expected)
|
@@ -152,7 +167,6 @@ describe "SourceSync" do
|
|
152
167
|
verify_result(
|
153
168
|
@c.docname(:update_errors) =>
|
154
169
|
{"#{ERROR}-error"=>{"message"=>msg}, ERROR=>data[ERROR]},
|
155
|
-
@c.docname(:update) => {'4'=> { 'price' => '199.99'}},
|
156
170
|
@c.docname(:update_rollback) => {ERROR=>{"price"=>"99.99"}})
|
157
171
|
end
|
158
172
|
end
|
@@ -174,9 +188,7 @@ describe "SourceSync" do
|
|
174
188
|
data = add_error_object({'2'=>@product2},msg)
|
175
189
|
set_state(@c.docname(:delete) => data)
|
176
190
|
@ss.delete(@c.id)
|
177
|
-
verify_result(@c.docname(:delete_errors) =>
|
178
|
-
{"#{ERROR}-error"=>{"message"=>msg}, ERROR=>data[ERROR]},
|
179
|
-
@c.docname(:delete) => {'2'=>@product2})
|
191
|
+
verify_result(@c.docname(:delete_errors) => {"#{ERROR}-error"=>{"message"=>msg}, ERROR=>data[ERROR]})
|
180
192
|
end
|
181
193
|
end
|
182
194
|
|
data/spec/spec_helper.rb
CHANGED
@@ -194,6 +194,23 @@ module TestHelpers
|
|
194
194
|
end
|
195
195
|
end
|
196
196
|
|
197
|
+
def mock_schema_no_version_method(adapters, &block)
|
198
|
+
adapters.each do |klass|
|
199
|
+
klass.class_eval 'def schema
|
200
|
+
{
|
201
|
+
"property" => {
|
202
|
+
"name" => "string",
|
203
|
+
"brand" => "string"
|
204
|
+
}
|
205
|
+
}.to_json
|
206
|
+
end'
|
207
|
+
end
|
208
|
+
yield
|
209
|
+
adapters.each do |klass|
|
210
|
+
klass.class_eval "def schema; end"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
197
214
|
def unzip_file(file,file_dir)
|
198
215
|
Zip::ZipFile.open(file) do |zip_file|
|
199
216
|
zip_file.each do |f|
|
@@ -203,6 +220,11 @@ module TestHelpers
|
|
203
220
|
end
|
204
221
|
end
|
205
222
|
end
|
223
|
+
|
224
|
+
def get_sha1(str)
|
225
|
+
Digest::SHA1.hexdigest(str)
|
226
|
+
end
|
227
|
+
|
206
228
|
end #TestHelpers
|
207
229
|
|
208
230
|
describe "RhosyncHelper", :shared => true do
|
@@ -1,4 +1,7 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','spec_helper')
|
2
|
+
require File.join(File.dirname(__FILE__),'..','..','lib','rhosync','server.rb')
|
1
3
|
require 'rhosync'
|
4
|
+
|
2
5
|
STATS_RECORD_RESOLUTION = 2 unless defined? STATS_RECORD_RESOLUTION
|
3
6
|
STATS_RECORD_SIZE = 8 unless defined? STATS_RECORD_SIZE
|
4
7
|
|
@@ -12,10 +15,17 @@ describe "Middleware" do
|
|
12
15
|
Store.db.flushdb
|
13
16
|
app = mock('app')
|
14
17
|
app.stub!(:call)
|
18
|
+
Rhosync.stats = true
|
19
|
+
Rhosync::Server.enable :stats
|
15
20
|
@middleware = Middleware.new(app)
|
16
21
|
Store.stub!(:lock).and_yield
|
17
22
|
end
|
18
|
-
|
23
|
+
|
24
|
+
after(:each) do
|
25
|
+
Rhosync.stats = false
|
26
|
+
Rhosync::Server.disable :stats
|
27
|
+
end
|
28
|
+
|
19
29
|
it "should compute http average" do
|
20
30
|
Time.stub!(:now).and_return { @now += 0.3; @now }
|
21
31
|
env = {
|
metadata
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rhosync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 391570199
|
5
|
+
prerelease: 7
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
|
9
|
+
- 17
|
10
|
+
- beta
|
11
|
+
- 1
|
12
|
+
version: 2.1.17.beta1
|
11
13
|
platform: ruby
|
12
14
|
authors:
|
13
15
|
- Rhomobile
|
@@ -15,28 +17,12 @@ autorequire:
|
|
15
17
|
bindir: bin
|
16
18
|
cert_chain: []
|
17
19
|
|
18
|
-
date: 2012-
|
20
|
+
date: 2012-04-24 00:00:00 Z
|
19
21
|
dependencies:
|
20
|
-
- !ruby/object:Gem::Dependency
|
21
|
-
name: rack
|
22
|
-
prerelease: false
|
23
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
-
none: false
|
25
|
-
requirements:
|
26
|
-
- - ~>
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
hash: 23
|
29
|
-
segments:
|
30
|
-
- 1
|
31
|
-
- 3
|
32
|
-
- 6
|
33
|
-
version: 1.3.6
|
34
|
-
type: :runtime
|
35
|
-
version_requirements: *id001
|
36
22
|
- !ruby/object:Gem::Dependency
|
37
23
|
name: sinatra
|
38
24
|
prerelease: false
|
39
|
-
requirement: &
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
40
26
|
none: false
|
41
27
|
requirements:
|
42
28
|
- - ~>
|
@@ -48,11 +34,11 @@ dependencies:
|
|
48
34
|
- 1
|
49
35
|
version: 1.3.1
|
50
36
|
type: :runtime
|
51
|
-
version_requirements: *
|
37
|
+
version_requirements: *id001
|
52
38
|
- !ruby/object:Gem::Dependency
|
53
39
|
name: json
|
54
40
|
prerelease: false
|
55
|
-
requirement: &
|
41
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
56
42
|
none: false
|
57
43
|
requirements:
|
58
44
|
- - ~>
|
@@ -64,11 +50,11 @@ dependencies:
|
|
64
50
|
- 2
|
65
51
|
version: 1.4.2
|
66
52
|
type: :runtime
|
67
|
-
version_requirements: *
|
53
|
+
version_requirements: *id002
|
68
54
|
- !ruby/object:Gem::Dependency
|
69
55
|
name: sqlite3-ruby
|
70
56
|
prerelease: false
|
71
|
-
requirement: &
|
57
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
72
58
|
none: false
|
73
59
|
requirements:
|
74
60
|
- - ~>
|
@@ -80,11 +66,11 @@ dependencies:
|
|
80
66
|
- 5
|
81
67
|
version: 1.2.5
|
82
68
|
type: :runtime
|
83
|
-
version_requirements: *
|
69
|
+
version_requirements: *id003
|
84
70
|
- !ruby/object:Gem::Dependency
|
85
71
|
name: rubyzip
|
86
72
|
prerelease: false
|
87
|
-
requirement: &
|
73
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
88
74
|
none: false
|
89
75
|
requirements:
|
90
76
|
- - ~>
|
@@ -96,11 +82,11 @@ dependencies:
|
|
96
82
|
- 4
|
97
83
|
version: 0.9.4
|
98
84
|
type: :runtime
|
99
|
-
version_requirements: *
|
85
|
+
version_requirements: *id004
|
100
86
|
- !ruby/object:Gem::Dependency
|
101
87
|
name: uuidtools
|
102
88
|
prerelease: false
|
103
|
-
requirement: &
|
89
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
104
90
|
none: false
|
105
91
|
requirements:
|
106
92
|
- - ">="
|
@@ -112,11 +98,11 @@ dependencies:
|
|
112
98
|
- 1
|
113
99
|
version: 2.1.1
|
114
100
|
type: :runtime
|
115
|
-
version_requirements: *
|
101
|
+
version_requirements: *id005
|
116
102
|
- !ruby/object:Gem::Dependency
|
117
103
|
name: redis
|
118
104
|
prerelease: false
|
119
|
-
requirement: &
|
105
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
120
106
|
none: false
|
121
107
|
requirements:
|
122
108
|
- - ~>
|
@@ -128,11 +114,11 @@ dependencies:
|
|
128
114
|
- 1
|
129
115
|
version: 2.1.1
|
130
116
|
type: :runtime
|
131
|
-
version_requirements: *
|
117
|
+
version_requirements: *id006
|
132
118
|
- !ruby/object:Gem::Dependency
|
133
119
|
name: resque
|
134
120
|
prerelease: false
|
135
|
-
requirement: &
|
121
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
136
122
|
none: false
|
137
123
|
requirements:
|
138
124
|
- - ~>
|
@@ -144,11 +130,11 @@ dependencies:
|
|
144
130
|
- 0
|
145
131
|
version: 1.14.0
|
146
132
|
type: :runtime
|
147
|
-
version_requirements: *
|
133
|
+
version_requirements: *id007
|
148
134
|
- !ruby/object:Gem::Dependency
|
149
135
|
name: rest-client
|
150
136
|
prerelease: false
|
151
|
-
requirement: &
|
137
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
152
138
|
none: false
|
153
139
|
requirements:
|
154
140
|
- - ~>
|
@@ -160,11 +146,11 @@ dependencies:
|
|
160
146
|
- 1
|
161
147
|
version: 1.6.1
|
162
148
|
type: :runtime
|
163
|
-
version_requirements: *
|
149
|
+
version_requirements: *id008
|
164
150
|
- !ruby/object:Gem::Dependency
|
165
151
|
name: templater
|
166
152
|
prerelease: false
|
167
|
-
requirement: &
|
153
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
168
154
|
none: false
|
169
155
|
requirements:
|
170
156
|
- - ~>
|
@@ -176,11 +162,11 @@ dependencies:
|
|
176
162
|
- 0
|
177
163
|
version: 1.0.0
|
178
164
|
type: :runtime
|
179
|
-
version_requirements: *
|
165
|
+
version_requirements: *id009
|
180
166
|
- !ruby/object:Gem::Dependency
|
181
167
|
name: rake
|
182
168
|
prerelease: false
|
183
|
-
requirement: &
|
169
|
+
requirement: &id010 !ruby/object:Gem::Requirement
|
184
170
|
none: false
|
185
171
|
requirements:
|
186
172
|
- - ~>
|
@@ -193,11 +179,11 @@ dependencies:
|
|
193
179
|
- 2
|
194
180
|
version: 0.9.2.2
|
195
181
|
type: :runtime
|
196
|
-
version_requirements: *
|
182
|
+
version_requirements: *id010
|
197
183
|
- !ruby/object:Gem::Dependency
|
198
184
|
name: log4r
|
199
185
|
prerelease: false
|
200
|
-
requirement: &
|
186
|
+
requirement: &id011 !ruby/object:Gem::Requirement
|
201
187
|
none: false
|
202
188
|
requirements:
|
203
189
|
- - ~>
|
@@ -209,11 +195,11 @@ dependencies:
|
|
209
195
|
- 7
|
210
196
|
version: 1.1.7
|
211
197
|
type: :development
|
212
|
-
version_requirements: *
|
198
|
+
version_requirements: *id011
|
213
199
|
- !ruby/object:Gem::Dependency
|
214
200
|
name: jeweler
|
215
201
|
prerelease: false
|
216
|
-
requirement: &
|
202
|
+
requirement: &id012 !ruby/object:Gem::Requirement
|
217
203
|
none: false
|
218
204
|
requirements:
|
219
205
|
- - ">="
|
@@ -225,11 +211,11 @@ dependencies:
|
|
225
211
|
- 0
|
226
212
|
version: 1.4.0
|
227
213
|
type: :development
|
228
|
-
version_requirements: *
|
214
|
+
version_requirements: *id012
|
229
215
|
- !ruby/object:Gem::Dependency
|
230
216
|
name: rspec
|
231
217
|
prerelease: false
|
232
|
-
requirement: &
|
218
|
+
requirement: &id013 !ruby/object:Gem::Requirement
|
233
219
|
none: false
|
234
220
|
requirements:
|
235
221
|
- - ">="
|
@@ -241,11 +227,11 @@ dependencies:
|
|
241
227
|
- 0
|
242
228
|
version: 1.3.0
|
243
229
|
type: :development
|
244
|
-
version_requirements: *
|
230
|
+
version_requirements: *id013
|
245
231
|
- !ruby/object:Gem::Dependency
|
246
232
|
name: rcov
|
247
233
|
prerelease: false
|
248
|
-
requirement: &
|
234
|
+
requirement: &id014 !ruby/object:Gem::Requirement
|
249
235
|
none: false
|
250
236
|
requirements:
|
251
237
|
- - ">="
|
@@ -257,11 +243,11 @@ dependencies:
|
|
257
243
|
- 8
|
258
244
|
version: 0.9.8
|
259
245
|
type: :development
|
260
|
-
version_requirements: *
|
246
|
+
version_requirements: *id014
|
261
247
|
- !ruby/object:Gem::Dependency
|
262
248
|
name: faker
|
263
249
|
prerelease: false
|
264
|
-
requirement: &
|
250
|
+
requirement: &id015 !ruby/object:Gem::Requirement
|
265
251
|
none: false
|
266
252
|
requirements:
|
267
253
|
- - ">="
|
@@ -273,11 +259,11 @@ dependencies:
|
|
273
259
|
- 1
|
274
260
|
version: 0.3.1
|
275
261
|
type: :development
|
276
|
-
version_requirements: *
|
262
|
+
version_requirements: *id015
|
277
263
|
- !ruby/object:Gem::Dependency
|
278
264
|
name: rack-test
|
279
265
|
prerelease: false
|
280
|
-
requirement: &
|
266
|
+
requirement: &id016 !ruby/object:Gem::Requirement
|
281
267
|
none: false
|
282
268
|
requirements:
|
283
269
|
- - ">="
|
@@ -289,11 +275,11 @@ dependencies:
|
|
289
275
|
- 3
|
290
276
|
version: 0.5.3
|
291
277
|
type: :development
|
292
|
-
version_requirements: *
|
278
|
+
version_requirements: *id016
|
293
279
|
- !ruby/object:Gem::Dependency
|
294
280
|
name: thor
|
295
281
|
prerelease: false
|
296
|
-
requirement: &
|
282
|
+
requirement: &id017 !ruby/object:Gem::Requirement
|
297
283
|
none: false
|
298
284
|
requirements:
|
299
285
|
- - ">="
|
@@ -305,7 +291,7 @@ dependencies:
|
|
305
291
|
- 6
|
306
292
|
version: 0.13.6
|
307
293
|
type: :development
|
308
|
-
version_requirements: *
|
294
|
+
version_requirements: *id017
|
309
295
|
description: RhoSync Synchronization Framework and related command-line utilities
|
310
296
|
email: dev@rhomobile.com
|
311
297
|
executables:
|
@@ -368,6 +354,9 @@ files:
|
|
368
354
|
- lib/rhosync/api/create_user.rb
|
369
355
|
- lib/rhosync/api/delete_client.rb
|
370
356
|
- lib/rhosync/api/delete_user.rb
|
357
|
+
- lib/rhosync/api/fast_delete.rb
|
358
|
+
- lib/rhosync/api/fast_insert.rb
|
359
|
+
- lib/rhosync/api/fast_update.rb
|
371
360
|
- lib/rhosync/api/get_api_token.rb
|
372
361
|
- lib/rhosync/api/get_client_params.rb
|
373
362
|
- lib/rhosync/api/get_db_doc.rb
|
@@ -484,6 +473,9 @@ files:
|
|
484
473
|
- spec/api/create_user_spec.rb
|
485
474
|
- spec/api/delete_client_spec.rb
|
486
475
|
- spec/api/delete_user_spec.rb
|
476
|
+
- spec/api/fast_delete_spec.rb
|
477
|
+
- spec/api/fast_insert_spec.rb
|
478
|
+
- spec/api/fast_update_spec.rb
|
487
479
|
- spec/api/get_api_token_spec.rb
|
488
480
|
- spec/api/get_client_params_spec.rb
|
489
481
|
- spec/api/get_db_doc_spec.rb
|
@@ -579,16 +571,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
579
571
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
580
572
|
none: false
|
581
573
|
requirements:
|
582
|
-
- - "
|
574
|
+
- - ">"
|
583
575
|
- !ruby/object:Gem::Version
|
584
|
-
hash:
|
576
|
+
hash: 25
|
585
577
|
segments:
|
586
|
-
-
|
587
|
-
|
578
|
+
- 1
|
579
|
+
- 3
|
580
|
+
- 1
|
581
|
+
version: 1.3.1
|
588
582
|
requirements: []
|
589
583
|
|
590
584
|
rubyforge_project:
|
591
|
-
rubygems_version: 1.8.
|
585
|
+
rubygems_version: 1.8.20
|
592
586
|
signing_key:
|
593
587
|
specification_version: 3
|
594
588
|
summary: RhoSync Synchronization Framework
|