rhosync 2.1.3 → 2.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +9 -0
- data/lib/rhosync/api/list_sources.rb +1 -1
- data/lib/rhosync/jobs/bulk_data_job.rb +2 -2
- data/lib/rhosync/model.rb +10 -10
- data/lib/rhosync/server.rb +28 -12
- data/lib/rhosync/source.rb +110 -34
- data/lib/rhosync/version.rb +1 -1
- data/lib/rhosync.rb +3 -7
- data/spec/api/get_source_params_spec.rb +7 -5
- data/spec/api/push_deletes_spec.rb +1 -0
- data/spec/api/push_objects_spec.rb +1 -0
- data/spec/api/rhosync_api_spec.rb +8 -5
- data/spec/bulk_data/bulk_data_spec.rb +4 -0
- data/spec/client_spec.rb +4 -0
- data/spec/client_sync_spec.rb +11 -10
- data/spec/document_spec.rb +4 -0
- data/spec/jobs/source_job_spec.rb +4 -0
- data/spec/server/server_spec.rb +6 -0
- data/spec/source_adapter_spec.rb +2 -0
- data/spec/source_spec.rb +27 -7
- data/spec/source_sync_spec.rb +3 -2
- data/spec/spec_helper.rb +2 -3
- data/spec/sync_states_spec.rb +1 -0
- metadata +5 -7
data/CHANGELOG
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## 2.1.6
|
2
|
+
* #13830841 - fixed issue where current_user.login doesn't match @source.user_id
|
3
|
+
|
4
|
+
## 2.1.5
|
5
|
+
* #13578473 - fixed "undefined method `user_id' for nil:NilClass" error in server.rb
|
6
|
+
|
7
|
+
## 2.1.4
|
8
|
+
* #13354369 - bug fix "rhosync bootstrap process shouldn't store sources in redis"
|
9
|
+
|
1
10
|
## 2.1.3
|
2
11
|
* #4398193 - ping should only send push messages to unique device pin list
|
3
12
|
* #13022667 - settings.yml doesn't work for setting external Redis instances
|
@@ -6,7 +6,7 @@ Server.api :list_sources do |params,user|
|
|
6
6
|
res = []
|
7
7
|
sources.each do |name|
|
8
8
|
s = Source.load(name,{:app_id => APP_NAME,:user_id => '*'})
|
9
|
-
if s.partition_type and s.partition_type == params[:partition_type]
|
9
|
+
if s.partition_type and s.partition_type == params[:partition_type].to_sym
|
10
10
|
res << name
|
11
11
|
end
|
12
12
|
end
|
@@ -122,8 +122,8 @@ module Rhosync
|
|
122
122
|
values (?,?,?,?,?,?,?,?,?,?)") do |stmt|
|
123
123
|
sources_refs.each do |source_name,ref|
|
124
124
|
s = ref[:source]
|
125
|
-
stmt.execute(s.source_id,s.name,s.priority,s.partition_type,
|
126
|
-
s.sync_type,refs_to_s(ref[:refs]),s.get_value(:metadata),s.schema,s.blob_attribs,s.has_many)
|
125
|
+
stmt.execute(s.source_id,s.name,s.priority,s.partition_type.to_s,
|
126
|
+
s.sync_type.to_s,refs_to_s(ref[:refs]),s.get_value(:metadata),s.schema,s.blob_attribs,s.has_many)
|
127
127
|
end
|
128
128
|
end
|
129
129
|
end
|
data/lib/rhosync/model.rb
CHANGED
@@ -59,14 +59,15 @@ module Rhosync
|
|
59
59
|
res
|
60
60
|
end
|
61
61
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
62
|
+
# TODO: not used anymore
|
63
|
+
# def update(attribs)
|
64
|
+
# self.class.fields.each do |field|
|
65
|
+
# if field[:name] != 'name' and field[:name] != 'rho__id'
|
66
|
+
# redis.del field_key(field[:name])
|
67
|
+
# end
|
68
|
+
# end
|
69
|
+
# self.class.populate_attributes(self,attribs)
|
70
|
+
# end
|
70
71
|
|
71
72
|
protected
|
72
73
|
def prefix #:nodoc:
|
@@ -111,8 +112,7 @@ module Rhosync
|
|
111
112
|
end
|
112
113
|
|
113
114
|
def load(id, params={})
|
114
|
-
|
115
|
-
populate_attributes(self.with_key(id),params)
|
115
|
+
populate_attributes(self.with_key(id),params) if self.is_exist?(id)
|
116
116
|
end
|
117
117
|
|
118
118
|
def populate_attributes(obj,attribs)
|
data/lib/rhosync/server.rb
CHANGED
@@ -88,7 +88,13 @@ module Rhosync
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def api_user
|
91
|
-
request_action == 'get_api_token'
|
91
|
+
if request_action == 'get_api_token'
|
92
|
+
current_user
|
93
|
+
else
|
94
|
+
u = ApiToken.load(params[:api_token])
|
95
|
+
raise "Wrong API token - #{params[:api_token].inspect}" unless u
|
96
|
+
u.user
|
97
|
+
end
|
92
98
|
end
|
93
99
|
|
94
100
|
def current_app
|
@@ -113,7 +119,9 @@ module Rhosync
|
|
113
119
|
if @client.nil? and params[:client_id]
|
114
120
|
@client = Client.load(params[:client_id].to_s,
|
115
121
|
params[:source_name] ? {:source_name => current_source.name} : {:source_name => '*'})
|
116
|
-
@client
|
122
|
+
if @client and current_user and @client.user_id != current_user.login
|
123
|
+
@client.switch_user(current_user.login)
|
124
|
+
end
|
117
125
|
@client
|
118
126
|
end
|
119
127
|
end
|
@@ -204,25 +212,33 @@ module Rhosync
|
|
204
212
|
end
|
205
213
|
|
206
214
|
post '/application/clientlogin' do
|
207
|
-
|
208
|
-
|
215
|
+
catch_all do
|
216
|
+
logout
|
217
|
+
do_login
|
218
|
+
end
|
209
219
|
end
|
210
220
|
|
211
221
|
get '/application/clientcreate' do
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
222
|
+
catch_all do
|
223
|
+
content_type :json
|
224
|
+
client = Client.create(:user_id => current_user.id,:app_id => current_app.id)
|
225
|
+
client.update_fields(params)
|
226
|
+
{ "client" => { "client_id" => client.id.to_s } }.merge!(source_config).to_json
|
227
|
+
end
|
216
228
|
end
|
217
229
|
|
218
230
|
post '/application/clientregister' do
|
219
|
-
|
220
|
-
|
231
|
+
catch_all do
|
232
|
+
current_client.update_fields(params)
|
233
|
+
source_config.to_json
|
234
|
+
end
|
221
235
|
end
|
222
236
|
|
223
237
|
get '/application/clientreset' do
|
224
|
-
|
225
|
-
|
238
|
+
catch_all do
|
239
|
+
ClientSync.reset(current_client)
|
240
|
+
source_config.to_json
|
241
|
+
end
|
226
242
|
end
|
227
243
|
|
228
244
|
# Member routes
|
data/lib/rhosync/source.rb
CHANGED
@@ -1,51 +1,117 @@
|
|
1
1
|
module Rhosync
|
2
|
-
class
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
2
|
+
class MemoryModel
|
3
|
+
@@model_data = {}
|
4
|
+
@@string_fields = []
|
5
|
+
@@integer_fields = []
|
6
|
+
attr_accessor :id
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_accessor :validates_presence
|
10
|
+
|
11
|
+
def define_fields(string_fields = [], integer_fields = [])
|
12
|
+
@@string_fields,@@integer_fields = string_fields,integer_fields
|
13
|
+
integer_fields.each do |attrib|
|
14
|
+
define_method("#{attrib}=") do |value|
|
15
|
+
value = (value.nil?) ? nil : value.to_i
|
16
|
+
instance_variable_set(:"@#{attrib}", value)
|
17
|
+
end
|
18
|
+
define_method("#{attrib}") do
|
19
|
+
instance_variable_get(:"@#{attrib}")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
string_fields.each do |attrib|
|
23
|
+
define_method("#{attrib}=") do |value|
|
24
|
+
instance_variable_set(:"@#{attrib}", value)
|
25
|
+
end
|
26
|
+
define_method("#{attrib}") do
|
27
|
+
instance_variable_get(:"@#{attrib}")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
@@string_fields << :id
|
31
|
+
@@string_fields << :rho__id
|
32
|
+
end
|
33
|
+
|
34
|
+
def validates_presence_of(*names)
|
35
|
+
self.validates_presence ||= []
|
36
|
+
names.each do |name|
|
37
|
+
self.validates_presence << name
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def is_exist?(id)
|
42
|
+
!@@model_data[id.to_sym].nil?
|
43
|
+
end
|
44
|
+
|
45
|
+
def class_prefix(classname)
|
46
|
+
classname.to_s.
|
47
|
+
sub(%r{(.*::)}, '').
|
48
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
49
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
50
|
+
downcase
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_array
|
55
|
+
res = []
|
56
|
+
@@string_fields.each do |field|
|
57
|
+
res << {"name" => field, "value" => send(field.to_sym), "type" => "string"}
|
58
|
+
end
|
59
|
+
@@integer_fields.each do |field|
|
60
|
+
res << {"name" => field, "value" => send(field.to_sym), "type" => "integer"}
|
61
|
+
end
|
62
|
+
res
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Source < MemoryModel
|
67
|
+
attr_accessor :app_id, :user_id, :rho__id
|
68
|
+
|
69
|
+
validates_presence_of :name
|
20
70
|
|
21
71
|
include Document
|
22
72
|
include LockOps
|
73
|
+
|
74
|
+
# source fields
|
75
|
+
define_fields([:name, :url, :login, :password, :callback_url, :partition_type, :sync_type,
|
76
|
+
:queue, :query_queue, :cud_queue, :belongs_to, :has_many], [:source_id, :priority, :poll_interval])
|
77
|
+
|
78
|
+
def initialize(fields)
|
79
|
+
fields.each do |name,value|
|
80
|
+
arg = "#{name}=".to_sym
|
81
|
+
self.send(arg, value) if self.respond_to?(arg)
|
82
|
+
end
|
83
|
+
end
|
23
84
|
|
24
85
|
def self.set_defaults(fields)
|
25
86
|
fields[:url] ||= ''
|
26
87
|
fields[:login] ||= ''
|
27
88
|
fields[:password] ||= ''
|
28
89
|
fields[:priority] ||= 3
|
29
|
-
fields[:partition_type]
|
90
|
+
fields[:partition_type] = fields[:partition_type] ? fields[:partition_type].to_sym : :user
|
30
91
|
fields[:poll_interval] ||= 300
|
31
|
-
fields[:sync_type]
|
92
|
+
fields[:sync_type] = fields[:sync_type] ? fields[:sync_type].to_sym : :incremental
|
93
|
+
fields[:id] = fields[:name]
|
94
|
+
fields[:rho__id] = fields[:name]
|
32
95
|
fields[:belongs_to] = fields[:belongs_to].to_json if fields[:belongs_to]
|
33
96
|
fields[:schema] = fields[:schema].to_json if fields[:schema]
|
34
97
|
end
|
35
98
|
|
36
99
|
def self.create(fields,params)
|
37
100
|
fields = fields.with_indifferent_access # so we can access hash keys as symbols
|
38
|
-
# validate_attributes(params)
|
39
|
-
fields[:id] = fields[:name]
|
40
101
|
set_defaults(fields)
|
41
|
-
|
102
|
+
obj = new(fields)
|
103
|
+
obj.assign_args(params)
|
104
|
+
@@model_data[obj.rho__id.to_sym] = obj
|
105
|
+
obj
|
42
106
|
end
|
43
107
|
|
44
|
-
def self.load(
|
108
|
+
def self.load(obj_id,params)
|
45
109
|
validate_attributes(params)
|
46
|
-
|
110
|
+
obj = @@model_data[obj_id.to_sym]
|
111
|
+
obj.assign_args(params) if obj
|
112
|
+
obj
|
47
113
|
end
|
48
|
-
|
114
|
+
|
49
115
|
def self.update_associations(sources)
|
50
116
|
params = {:app_id => APP_NAME,:user_id => '*'}
|
51
117
|
sources.each { |source| Source.load(source, params).has_many = nil }
|
@@ -58,7 +124,8 @@ module Rhosync
|
|
58
124
|
attrib = entry.keys[0]
|
59
125
|
model = entry[attrib]
|
60
126
|
owner = Source.load(model, params)
|
61
|
-
owner.has_many
|
127
|
+
owner.has_many ||= ''
|
128
|
+
owner.has_many = owner.has_many+',' if owner.has_many.length > 0
|
62
129
|
owner.has_many += [source,attrib].join(',')
|
63
130
|
end
|
64
131
|
else
|
@@ -68,6 +135,16 @@ module Rhosync
|
|
68
135
|
end
|
69
136
|
end
|
70
137
|
|
138
|
+
def self.delete_all
|
139
|
+
@@model_data.each { |k,v| v.delete }
|
140
|
+
@@model_data = {}
|
141
|
+
end
|
142
|
+
|
143
|
+
def assign_args(params)
|
144
|
+
self.user_id = params[:user_id]
|
145
|
+
self.app_id = params[:app_id]
|
146
|
+
end
|
147
|
+
|
71
148
|
def blob_attribs
|
72
149
|
return '' unless self.schema
|
73
150
|
schema = JSON.parse(self.schema)
|
@@ -82,7 +159,7 @@ module Rhosync
|
|
82
159
|
def update(fields)
|
83
160
|
fields = fields.with_indifferent_access # so we can access hash keys as symbols
|
84
161
|
self.class.set_defaults(fields)
|
85
|
-
super(fields)
|
162
|
+
#super(fields)
|
86
163
|
end
|
87
164
|
|
88
165
|
def clone(src_doctype,dst_doctype)
|
@@ -91,12 +168,12 @@ module Rhosync
|
|
91
168
|
|
92
169
|
# Return the user associated with a source
|
93
170
|
def user
|
94
|
-
@user
|
171
|
+
@user = User.load(self.user_id)
|
95
172
|
end
|
96
173
|
|
97
174
|
# Return the app the source belongs to
|
98
175
|
def app
|
99
|
-
@app
|
176
|
+
@app = App.load(self.app_id)
|
100
177
|
end
|
101
178
|
|
102
179
|
def schema
|
@@ -106,8 +183,7 @@ module Rhosync
|
|
106
183
|
def read_state
|
107
184
|
id = {:app_id => self.app_id,:user_id => user_by_partition,
|
108
185
|
:source_name => self.name}
|
109
|
-
|
110
|
-
@read_state ||= ReadState.create(id)
|
186
|
+
ReadState.load(id) || ReadState.create(id)
|
111
187
|
end
|
112
188
|
|
113
189
|
def doc_suffix(doctype)
|
@@ -116,7 +192,7 @@ module Rhosync
|
|
116
192
|
|
117
193
|
def delete
|
118
194
|
flash_data('*')
|
119
|
-
|
195
|
+
@@model_data.delete(rho__id.to_sym) if rho__id
|
120
196
|
end
|
121
197
|
|
122
198
|
def partition
|
@@ -144,7 +220,7 @@ module Rhosync
|
|
144
220
|
end
|
145
221
|
yield client_id,params if need_refresh
|
146
222
|
end
|
147
|
-
|
223
|
+
|
148
224
|
private
|
149
225
|
def self.validate_attributes(params)
|
150
226
|
raise ArgumentError.new('Missing required attribute user_id') unless params[:user_id]
|
data/lib/rhosync/version.rb
CHANGED
data/lib/rhosync.rb
CHANGED
@@ -91,15 +91,11 @@ module Rhosync
|
|
91
91
|
app = App.create(:name => app_name)
|
92
92
|
end
|
93
93
|
sources = config[:sources] || []
|
94
|
+
Source.delete_all
|
94
95
|
sources.each do |source_name,fields|
|
95
96
|
check_for_schema_field!(fields)
|
96
|
-
|
97
|
-
|
98
|
-
s.update(fields)
|
99
|
-
else
|
100
|
-
fields[:name] = source_name
|
101
|
-
Source.create(fields,{:app_id => app.name})
|
102
|
-
end
|
97
|
+
fields[:name] = source_name
|
98
|
+
Source.create(fields,{:app_id => app.name})
|
103
99
|
unless app.sources.members.include?(source_name)
|
104
100
|
app.sources << source_name
|
105
101
|
end
|
@@ -5,13 +5,14 @@ describe "RhosyncApiGetSourceParams" do
|
|
5
5
|
|
6
6
|
it "should list source attributes" do
|
7
7
|
post "/api/get_source_params", {:api_token => @api_token, :source_id =>"SampleAdapter"}
|
8
|
-
JSON.parse(last_response.body).
|
8
|
+
result = JSON.parse(last_response.body).sort {|x,y| y["name"] <=> x["name"] }
|
9
|
+
result.should == [
|
9
10
|
{"name"=>"rho__id", "value"=>"SampleAdapter", "type"=>"string"},
|
10
11
|
{"name"=>"source_id", "value"=>nil, "type"=>"integer"},
|
11
12
|
{"name"=>"name", "value"=>"SampleAdapter", "type"=>"string"},
|
12
|
-
{"name"=>"url", "value"=>"", "type"=>"string"},
|
13
|
-
{"name"=>"login", "value"=>"", "type"=>"string"},
|
14
|
-
{"name"=>"password", "value"=>"", "type"=>"string"},
|
13
|
+
{"name"=>"url", "value"=>"http://example.com", "type"=>"string"},
|
14
|
+
{"name"=>"login", "value"=>"testuser", "type"=>"string"},
|
15
|
+
{"name"=>"password", "value"=>"testpass", "type"=>"string"},
|
15
16
|
{"name"=>"priority", "value"=>3, "type"=>"integer"},
|
16
17
|
{"name"=>"callback_url", "value"=>nil, "type"=>"string"},
|
17
18
|
{"name"=>"poll_interval", "value"=>300, "type"=>"integer"},
|
@@ -19,9 +20,10 @@ describe "RhosyncApiGetSourceParams" do
|
|
19
20
|
{"name"=>"sync_type", "value"=>"incremental", "type"=>"string"},
|
20
21
|
{"name"=>"belongs_to", "type"=>"string", "value"=>nil},
|
21
22
|
{"name"=>"has_many", "type"=>"string", "value"=>"FixedSchemaAdapter,brand"},
|
23
|
+
{"name"=>"id", "value"=>"SampleAdapter", "type"=>"string"},
|
22
24
|
{"name"=>"queue", "value"=>nil, "type"=>"string"},
|
23
25
|
{"name"=>"query_queue", "value"=>nil, "type"=>"string"},
|
24
|
-
{"name"=>"cud_queue", "value"=>nil, "type"=>"string"}]
|
26
|
+
{"name"=>"cud_queue", "value"=>nil, "type"=>"string"}].sort {|x,y| y["name"] <=> x["name"] }
|
25
27
|
end
|
26
28
|
|
27
29
|
end
|
@@ -5,6 +5,7 @@ describe "RhosyncApiPushDeletes" do
|
|
5
5
|
|
6
6
|
it "should delete object from :md" do
|
7
7
|
data = {'1' => @product1, '2' => @product2, '3' => @product3}
|
8
|
+
@s = Source.load(@s_fields[:name],@s_params)
|
8
9
|
set_state(@s.docname(:md) => data)
|
9
10
|
data.delete('2')
|
10
11
|
post "/api/push_deletes", :api_token => @api_token,
|
@@ -14,6 +14,7 @@ describe "RhosyncApiPushObjects" do
|
|
14
14
|
it "should push updates to existing objects to rhosync's :md" do
|
15
15
|
data = {'1' => @product1, '2' => @product2, '3' => @product3}
|
16
16
|
update = {'price' => '0.99', 'new_field' => 'value'}
|
17
|
+
@s = Source.load(@s_fields[:name],@s_params)
|
17
18
|
set_state(@s.docname(:md) => data)
|
18
19
|
update.each do |key,value|
|
19
20
|
data['2'][key] = value
|
@@ -152,13 +152,15 @@ describe "RhosyncApi" do
|
|
152
152
|
end
|
153
153
|
|
154
154
|
it "should list source attributes using direct api call" do
|
155
|
-
RhosyncApi::get_source_params(
|
155
|
+
result = RhosyncApi::get_source_params(
|
156
|
+
'',@api_token,"SampleAdapter").sort {|x,y| y["name"] <=> x["name"] }
|
157
|
+
result.should == [
|
156
158
|
{"name"=>"rho__id", "value"=>"SampleAdapter", "type"=>"string"},
|
157
159
|
{"name"=>"source_id", "value"=>nil, "type"=>"integer"},
|
158
160
|
{"name"=>"name", "value"=>"SampleAdapter", "type"=>"string"},
|
159
|
-
{"name"=>"url", "value"=>"", "type"=>"string"},
|
160
|
-
{"name"=>"login", "value"=>"", "type"=>"string"},
|
161
|
-
{"name"=>"password", "value"=>"", "type"=>"string"},
|
161
|
+
{"name"=>"url", "value"=>"http://example.com", "type"=>"string"},
|
162
|
+
{"name"=>"login", "value"=>"testuser", "type"=>"string"},
|
163
|
+
{"name"=>"password", "value"=>"testpass", "type"=>"string"},
|
162
164
|
{"name"=>"priority", "value"=>3, "type"=>"integer"},
|
163
165
|
{"name"=>"callback_url", "value"=>nil, "type"=>"string"},
|
164
166
|
{"name"=>"poll_interval", "value"=>300, "type"=>"integer"},
|
@@ -166,9 +168,10 @@ describe "RhosyncApi" do
|
|
166
168
|
{"name"=>"sync_type", "value"=>"incremental", "type"=>"string"},
|
167
169
|
{"name"=>"belongs_to", "type"=>"string", "value"=>nil},
|
168
170
|
{"name"=>"has_many", "type"=>"string", "value"=>"FixedSchemaAdapter,brand"},
|
171
|
+
{"name"=>"id", "value"=>"SampleAdapter", "type"=>"string"},
|
169
172
|
{"name"=>"queue", "value"=>nil, "type"=>"string"},
|
170
173
|
{"name"=>"query_queue", "value"=>nil, "type"=>"string"},
|
171
|
-
{"name"=>"cud_queue", "value"=>nil, "type"=>"string"}]
|
174
|
+
{"name"=>"cud_queue", "value"=>nil, "type"=>"string"}].sort {|x,y| y["name"] <=> x["name"] }
|
172
175
|
end
|
173
176
|
|
174
177
|
it "should list source attributes using rest call" do
|
data/spec/client_spec.rb
CHANGED
@@ -7,6 +7,10 @@ describe "Client" do
|
|
7
7
|
it_should_behave_like "SpecBootstrapHelper"
|
8
8
|
it_should_behave_like "SourceAdapterHelper"
|
9
9
|
|
10
|
+
before(:each) do
|
11
|
+
@s = Source.load(@s_fields[:name],@s_params)
|
12
|
+
end
|
13
|
+
|
10
14
|
it "should create client with fields" do
|
11
15
|
@c.id.length.should == 32
|
12
16
|
@c.device_type.should == @c_fields[:device_type]
|
data/spec/client_sync_spec.rb
CHANGED
@@ -10,6 +10,7 @@ describe "ClientSync" do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
before(:each) do
|
13
|
+
@s = Source.load(@s_fields[:name],@s_params)
|
13
14
|
@cs = ClientSync.new(@s,@c,2)
|
14
15
|
end
|
15
16
|
|
@@ -341,7 +342,7 @@ describe "ClientSync" do
|
|
341
342
|
token1.should be_nil
|
342
343
|
Store.get_data(@c.docname(:search)).should == {}
|
343
344
|
end
|
344
|
-
|
345
|
+
|
345
346
|
end
|
346
347
|
|
347
348
|
describe "page methods" do
|
@@ -354,40 +355,40 @@ describe "ClientSync" do
|
|
354
355
|
Store.get_value(@cs.client.docname(:cd_size)).to_i.should == 0
|
355
356
|
Store.get_data(@cs.client.docname(:page)).should == @expected
|
356
357
|
end
|
357
|
-
|
358
|
+
|
358
359
|
it "appends diff to the client document" do
|
359
360
|
@cd = {'3'=>@product3}
|
360
361
|
Store.put_data(@c.docname(:cd),@cd)
|
361
362
|
Store.get_data(@c.docname(:cd)).should == @cd
|
362
|
-
|
363
|
+
|
363
364
|
@page = {'1'=>@product1,'2'=>@product2}
|
364
365
|
@expected = {'1'=>@product1,'2'=>@product2,'3'=>@product3}
|
365
|
-
|
366
|
+
|
366
367
|
Store.put_data(@c.docname(:cd),@page,true).should == true
|
367
368
|
Store.get_data(@c.docname(:cd)).should == @expected
|
368
369
|
end
|
369
|
-
|
370
|
+
|
370
371
|
it "should return deleted objects in the client document" do
|
371
372
|
Store.put_data(@s.docname(:md),@data).should == true
|
372
373
|
Store.get_data(@s.docname(:md)).should == @data
|
373
|
-
|
374
|
+
|
374
375
|
@cd = {'1'=>@product1,'2'=>@product2,'3'=>@product3,'4'=>@product4}
|
375
376
|
Store.put_data(@cs.client.docname(:cd),@cd)
|
376
377
|
Store.get_data(@cs.client.docname(:cd)).should == @cd
|
377
|
-
|
378
|
+
|
378
379
|
@expected = {'4'=>@product4}
|
379
380
|
@cs.compute_deleted_page.should == @expected
|
380
381
|
Store.get_data(@cs.client.docname(:delete_page)).should == @expected
|
381
382
|
end
|
382
|
-
|
383
|
+
|
383
384
|
it "should delete objects from client document" do
|
384
385
|
Store.put_data(@s.docname(:md),@data).should == true
|
385
386
|
Store.get_data(@s.docname(:md)).should == @data
|
386
|
-
|
387
|
+
|
387
388
|
@cd = {'1'=>@product1,'2'=>@product2,'3'=>@product3,'4'=>@product4}
|
388
389
|
Store.put_data(@cs.client.docname(:cd),@cd)
|
389
390
|
Store.get_data(@cs.client.docname(:cd)).should == @cd
|
390
|
-
|
391
|
+
|
391
392
|
Store.delete_data(@cs.client.docname(:cd),@cs.compute_deleted_page).should == true
|
392
393
|
Store.get_data(@cs.client.docname(:cd)).should == @data
|
393
394
|
end
|
data/spec/document_spec.rb
CHANGED
@@ -4,6 +4,10 @@ describe "Document" do
|
|
4
4
|
it_should_behave_like "SpecBootstrapHelper"
|
5
5
|
it_should_behave_like "SourceAdapterHelper"
|
6
6
|
|
7
|
+
before(:each) do
|
8
|
+
@s = Source.load(@s_fields[:name],@s_params)
|
9
|
+
end
|
10
|
+
|
7
11
|
it "should generate client docname" do
|
8
12
|
@c.docname(:foo).should == "client:#{@a.id}:#{@u.id}:#{@c.id}:#{@s_fields[:name]}:foo"
|
9
13
|
end
|
@@ -4,6 +4,10 @@ describe "SourceJob" do
|
|
4
4
|
it_should_behave_like "SpecBootstrapHelper"
|
5
5
|
it_should_behave_like "SourceAdapterHelper"
|
6
6
|
|
7
|
+
before(:each) do
|
8
|
+
@s = Source.load(@s_fields[:name],@s_params)
|
9
|
+
end
|
10
|
+
|
7
11
|
it "should perform process_query" do
|
8
12
|
set_state('test_db_storage' => @data)
|
9
13
|
SourceJob.perform('query',@s.id,@s.app_id,@s.user_id,nil,nil)
|
data/spec/server/server_spec.rb
CHANGED
@@ -187,6 +187,12 @@ describe "Server" do
|
|
187
187
|
get "/application",:client_id => @c.id,:source_name => @s.name,:version => ClientSync::VERSION
|
188
188
|
JSON.parse(last_response.body).last['insert'].should == data
|
189
189
|
end
|
190
|
+
|
191
|
+
it "should return error on routes if client doesn't exist" do
|
192
|
+
get "/application",:client_id => "missingclient",:source_name => @s.name,:version => ClientSync::VERSION
|
193
|
+
last_response.body.should == "Unknown client"
|
194
|
+
last_response.status.should == 500
|
195
|
+
end
|
190
196
|
end
|
191
197
|
|
192
198
|
describe "source routes" do
|
data/spec/source_adapter_spec.rb
CHANGED
@@ -16,6 +16,7 @@ describe "SourceAdapter" do
|
|
16
16
|
it_should_behave_like "SourceAdapterHelper"
|
17
17
|
|
18
18
|
before(:each) do
|
19
|
+
@s = Source.load(@s_fields[:name],@s_params)
|
19
20
|
@s.name = 'SimpleAdapter'
|
20
21
|
@sa = SourceAdapter.create(@s,nil)
|
21
22
|
end
|
@@ -37,6 +38,7 @@ describe "SourceAdapter" do
|
|
37
38
|
@s_fields[:name] = 'Broken'
|
38
39
|
broken_source = Source.create(@s_fields,@s_params)
|
39
40
|
lambda { SourceAdapter.create(broken_source) }.should raise_error(Exception)
|
41
|
+
broken_source.delete
|
40
42
|
end
|
41
43
|
|
42
44
|
it "should create SourceAdapter with trailing spaces" do
|
data/spec/source_spec.rb
CHANGED
@@ -4,6 +4,10 @@ describe "Source" do
|
|
4
4
|
it_should_behave_like "SpecBootstrapHelper"
|
5
5
|
it_should_behave_like "SourceAdapterHelper"
|
6
6
|
|
7
|
+
before(:each) do
|
8
|
+
@s = Source.load(@s_fields[:name],@s_params)
|
9
|
+
end
|
10
|
+
|
7
11
|
it "should create and load source with @s_fields and @s_params" do
|
8
12
|
@s.name.should == @s_fields[:name]
|
9
13
|
@s.url.should == @s_fields[:url]
|
@@ -30,6 +34,7 @@ describe "Source" do
|
|
30
34
|
@s1.poll_interval.should == 300
|
31
35
|
@s1.app_id.should == @s_params[:app_id]
|
32
36
|
@s1.user_id.should == @s_params[:user_id]
|
37
|
+
# puts "#{@s1.inspect()}" # FIXME:
|
33
38
|
end
|
34
39
|
|
35
40
|
it "should create source with user" do
|
@@ -40,17 +45,31 @@ describe "Source" do
|
|
40
45
|
@s.app.name.should == @a_fields[:name]
|
41
46
|
@s.docname(:md).should == "source:#{@s.app.id}:#{@u.id}:#{@s_fields[:name]}:md"
|
42
47
|
end
|
48
|
+
|
49
|
+
it 'should return values that set by setter method' do
|
50
|
+
@s.login = "shurab"
|
51
|
+
@s.login.should == "shurab"
|
52
|
+
@s.poll_interval = 350
|
53
|
+
@s.poll_interval.should == 350
|
54
|
+
@s.poll_interval = nil
|
55
|
+
@s.poll_interval.should == nil
|
56
|
+
@s.url = nil
|
57
|
+
@s.url.should be_nil
|
58
|
+
end
|
43
59
|
|
44
60
|
it "should delete source" do
|
45
61
|
@s.delete
|
46
62
|
Source.is_exist?(@s_fields[:name]).should == false
|
63
|
+
@s = Source.create(@s_fields,@s_params)
|
47
64
|
end
|
48
65
|
|
49
66
|
it "should delete master and all documents associated with source" do
|
50
|
-
|
67
|
+
key = @s.docname('*')
|
68
|
+
set_state(key => @data)
|
51
69
|
@s.delete
|
52
|
-
verify_result(
|
53
|
-
Store.db.keys(
|
70
|
+
verify_result(key => {})
|
71
|
+
Store.db.keys(key).should == []
|
72
|
+
@s = Source.create(@s_fields,@s_params)
|
54
73
|
end
|
55
74
|
|
56
75
|
it "should create source with default partition user" do
|
@@ -68,16 +87,17 @@ describe "Source" do
|
|
68
87
|
@s_fields[:queue] = :default
|
69
88
|
@s_fields[:query_queue] = :query
|
70
89
|
@s_fields[:cud_queue] = :cud
|
71
|
-
Source.create(@s_fields,@s_params)
|
90
|
+
@s = Source.create(@s_fields,@s_params)
|
72
91
|
s = Source.load(@s_fields[:name],@s_params)
|
73
|
-
s.queue.should ==
|
74
|
-
s.query_queue.should ==
|
75
|
-
s.cud_queue.should ==
|
92
|
+
s.queue.should == :default
|
93
|
+
s.query_queue.should == :query
|
94
|
+
s.cud_queue.should == :cud
|
76
95
|
end
|
77
96
|
|
78
97
|
it "should add associations based on belongs_to field for a source" do
|
79
98
|
@s2 = Source.create({:name => 'SimpleAdapter'}, @s_params)
|
80
99
|
@s2.belongs_to = [{'product_id' => 'SampleAdapter'}].to_json
|
100
|
+
sf = Source.load(@s1.name,{:app_id => @a.id,:user_id => '*'})
|
81
101
|
Source.update_associations([@s.name,@s1.name, @s2.name])
|
82
102
|
s = Source.load(@s.name,{:app_id => @a.id,:user_id => '*'})
|
83
103
|
s.has_many.should == "#{@s1.name},brand,#{@s2.name},product_id"
|
data/spec/source_sync_spec.rb
CHANGED
@@ -5,6 +5,7 @@ describe "SourceSync" do
|
|
5
5
|
it_should_behave_like "SourceAdapterHelper"
|
6
6
|
|
7
7
|
before(:each) do
|
8
|
+
@s = Source.load(@s_fields[:name],@s_params)
|
8
9
|
@ss = SourceSync.new(@s)
|
9
10
|
end
|
10
11
|
|
@@ -51,7 +52,7 @@ describe "SourceSync" do
|
|
51
52
|
@ss.process_query
|
52
53
|
verify_result(@s.docname(:md) => expected)
|
53
54
|
end
|
54
|
-
|
55
|
+
|
55
56
|
it "should never call read on any call of process" do
|
56
57
|
@s.poll_interval = -1
|
57
58
|
Store.put_data('test_db_storage',{'1'=>@product1})
|
@@ -207,7 +208,7 @@ describe "SourceSync" do
|
|
207
208
|
|
208
209
|
describe "app-level partitioning" do
|
209
210
|
it "should create app-level masterdoc with '__shared__' docname" do
|
210
|
-
@s1 = Source.load(@s_fields[:name]
|
211
|
+
@s1 = Source.load(@s_fields[:name],{:user_id => "testuser",:app_id => @a.id})
|
211
212
|
@s1.partition = :app
|
212
213
|
@ss1 = SourceSync.new(@s1)
|
213
214
|
expected = {'1'=>@product1,'2'=>@product2}
|
data/spec/spec_helper.rb
CHANGED
@@ -209,6 +209,7 @@ describe "RhosyncHelper", :shared => true do
|
|
209
209
|
before(:each) do
|
210
210
|
Store.create
|
211
211
|
Store.db.flushdb
|
212
|
+
# Source.delete_all # TODO: should have this
|
212
213
|
end
|
213
214
|
end
|
214
215
|
|
@@ -284,10 +285,8 @@ describe "DBObjectsHelper", :shared => true do
|
|
284
285
|
:app_id => @a.id
|
285
286
|
}
|
286
287
|
@c = Client.create(@c_fields,{:source_name => @s_fields[:name]})
|
287
|
-
@s = Source.
|
288
|
-
@s = Source.create(@s_fields,@s_params) if @s.nil?
|
288
|
+
@s = Source.create(@s_fields,@s_params)
|
289
289
|
@s1 = Source.load('FixedSchemaAdapter',@s_params)
|
290
|
-
@s1 = Source.create({:name => 'FixedSchemaAdapter'},@s_params) if @s1.nil?
|
291
290
|
config = Rhosync.source_config["sources"]['FixedSchemaAdapter']
|
292
291
|
@s1.update(config)
|
293
292
|
@r = @s.read_state
|
data/spec/sync_states_spec.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rhosync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 2.1.
|
9
|
+
- 6
|
10
|
+
version: 2.1.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Rhomobile
|
@@ -15,8 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-05-
|
19
|
-
default_executable: rhosync
|
18
|
+
date: 2011-05-25 00:00:00 Z
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
22
21
|
name: json
|
@@ -544,7 +543,6 @@ files:
|
|
544
543
|
- examples/simple/application.rb
|
545
544
|
- examples/simple/sources/sample_adapter.rb
|
546
545
|
- examples/simple/sources/simple_adapter.rb
|
547
|
-
has_rdoc: true
|
548
546
|
homepage: http://rhomobile.com/products/rhosync
|
549
547
|
licenses: []
|
550
548
|
|
@@ -574,7 +572,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
574
572
|
requirements: []
|
575
573
|
|
576
574
|
rubyforge_project:
|
577
|
-
rubygems_version: 1.
|
575
|
+
rubygems_version: 1.8.3
|
578
576
|
signing_key:
|
579
577
|
specification_version: 3
|
580
578
|
summary: RhoSync Synchronization Framework
|