maestrano-connector-rails 0.3.13 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/app/jobs/maestrano/connector/rails/synchronization_job.rb +10 -4
- data/app/models/maestrano/connector/rails/concerns/entity.rb +43 -32
- data/app/models/maestrano/connector/rails/organization.rb +2 -2
- data/app/models/maestrano/connector/rails/synchronization.rb +9 -0
- data/lib/generators/connector/templates/oauth_controller.rb +1 -0
- data/maestrano-connector-rails.gemspec +6 -4
- data/spec/jobs/synchronization_job_spec.rb +26 -0
- data/spec/models/complex_entity_spec.rb +3 -3
- data/spec/models/entity_spec.rb +99 -48
- data/spec/models/{organizaztion_spec.rb → organization_spec.rb} +2 -2
- data/spec/models/synchronization_spec.rb +22 -0
- data/template/maestrano-connector-template.rb +10 -0
- data/template/routes.rb +7 -0
- data/template/sidekiq.rb +1 -0
- data/template/sidekiq.yml +4 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 296c3f72e80c6876a39e3161e752292bad97d03f
|
4
|
+
data.tar.gz: 155def8dc10315c64595ae0c4e6284890f896254
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 97e21e2088c3d7774052fe11aa6380e456dfa884a1165a57696bc21b723db99696410cde4011d2c6f9824a92d0e15fa7251d2c21a48dd6892ec3ea0293264879
|
7
|
+
data.tar.gz: 9915cf3654bb531970ccaf5dee230a53ec5de525b96b08659bd2dd912d67eca7457619c8f5545c9695daa63b6d1594c2084f7d1d58e1995adb0d415f729b158d
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
@@ -11,12 +11,19 @@ module Maestrano::Connector::Rails
|
|
11
11
|
return unless organization.sync_enabled
|
12
12
|
|
13
13
|
# Check if previous synchronization is still running
|
14
|
-
|
15
|
-
|
16
|
-
ConnectorLogger.log('info', organization, "Previous synchronization is still running")
|
14
|
+
if Synchronization.where(organization_id: organization.id, status: 'RUNNING').where(created_at: (30.minutes.ago..Time.now)).exists?
|
15
|
+
ConnectorLogger.log('info', organization, "Synchronization skipped: Previous synchronization is still running")
|
17
16
|
return
|
18
17
|
end
|
19
18
|
|
19
|
+
# Check if recovery mode: last 3 synchronizations have failed
|
20
|
+
if Synchronization.where(organization_id: organization.id, status: 'ERROR').order(created_at: :desc).limit(3).count == 3 \
|
21
|
+
&& Synchronization.where(organization_id: organization.id).order(created_at: :desc).limit(1).first.updated_at > 1.day.ago
|
22
|
+
ConnectorLogger.log('info', organization, "Synchronization skipped: Recovery mode (three previous synchronizations have failed)")
|
23
|
+
return
|
24
|
+
end
|
25
|
+
|
26
|
+
# Trigger synchronization
|
20
27
|
ConnectorLogger.log('info', organization, "Start synchronization, opts=#{opts}")
|
21
28
|
current_synchronization = Synchronization.create_running(organization)
|
22
29
|
|
@@ -49,7 +56,6 @@ module Maestrano::Connector::Rails
|
|
49
56
|
def sync_entity(entity_name, organization, connec_client, external_client, last_synchronization, opts)
|
50
57
|
entity_instance = "Entities::#{entity_name.titleize.split.join}".constantize.new
|
51
58
|
|
52
|
-
|
53
59
|
entity_instance.before_sync(connec_client, external_client, last_synchronization, organization, opts)
|
54
60
|
external_entities = entity_instance.get_external_entities(external_client, last_synchronization, organization, opts)
|
55
61
|
connec_entities = entity_instance.get_connec_entities(connec_client, last_synchronization, organization, opts)
|
@@ -117,11 +117,11 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
117
117
|
end
|
118
118
|
|
119
119
|
def can_read_connec?
|
120
|
-
|
120
|
+
can_write_external?
|
121
121
|
end
|
122
122
|
|
123
123
|
def can_read_external?
|
124
|
-
|
124
|
+
can_write_connec?
|
125
125
|
end
|
126
126
|
|
127
127
|
def can_write_connec?
|
@@ -191,14 +191,14 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
191
191
|
query_params[:$filter] = filter
|
192
192
|
end
|
193
193
|
response = client.get("/#{self.class.normalized_connec_entity_name}?#{query_params.to_query}")
|
194
|
-
raise "No data received from Connec! when trying to fetch #{self.class.
|
194
|
+
raise "No data received from Connec! when trying to fetch #{self.class.normalized_connec_entity_name}" unless response
|
195
195
|
|
196
196
|
response_hash = JSON.parse(response.body)
|
197
197
|
Maestrano::Connector::Rails::ConnectorLogger.log('debug', organization, "received first page entity=#{self.class.connec_entity_name}, response=#{response.body}")
|
198
198
|
if response_hash["#{self.class.normalized_connec_entity_name}"]
|
199
199
|
entities << response_hash["#{self.class.normalized_connec_entity_name}"]
|
200
200
|
else
|
201
|
-
raise "Received unrecognized Connec! data when trying to fetch #{self.class.
|
201
|
+
raise "Received unrecognized Connec! data when trying to fetch #{self.class.normalized_connec_entity_name}"
|
202
202
|
end
|
203
203
|
|
204
204
|
# Fetch subsequent pages
|
@@ -231,42 +231,53 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
231
231
|
return unless self.class.can_write_connec?
|
232
232
|
|
233
233
|
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending #{Maestrano::Connector::Rails::External.external_name} #{self.class.external_entity_name.pluralize} to Connec! #{connec_entity_name.pluralize}")
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
234
|
+
|
235
|
+
request_per_call = 100
|
236
|
+
start = 0
|
237
|
+
while start < mapped_external_entities_with_idmaps.size
|
238
|
+
# Prepare batch request
|
239
|
+
batch_entities = mapped_external_entities_with_idmaps.slice(start, request_per_call)
|
240
|
+
batch_request = {sequential: true, ops: []}
|
241
|
+
batch_entities.each do |mapped_external_entity_with_idmap|
|
242
|
+
external_entity = mapped_external_entity_with_idmap[:entity]
|
243
|
+
idmap = mapped_external_entity_with_idmap[:idmap]
|
239
244
|
if idmap.connec_id.blank?
|
240
|
-
|
241
|
-
idmap.update_attributes(connec_id: connec_entity['id'], last_push_to_connec: Time.now, message: nil)
|
245
|
+
batch_request[:ops] << batch_op('post', external_entity, nil, self.class.normalize_connec_entity_name(connec_entity_name), organization)
|
242
246
|
else
|
243
247
|
next unless self.class.can_update_connec?
|
244
|
-
|
245
|
-
idmap.update_attributes(last_push_to_connec: Time.now, message: nil)
|
248
|
+
batch_request[:ops] << batch_op('put', external_entity, idmap.connec_id, self.class.normalize_connec_entity_name(connec_entity_name), organization)
|
246
249
|
end
|
247
|
-
rescue => e
|
248
|
-
# Store Connec! error if any
|
249
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('error', organization, "Error while pushing to Connec!: #{e}")
|
250
|
-
idmap.update_attributes(message: e.message)
|
251
250
|
end
|
252
|
-
end
|
253
|
-
end
|
254
251
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
252
|
+
# Batch call
|
253
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending batch request to Connec! for #{self.class.normalize_connec_entity_name(connec_entity_name)}. Batch_request_size: #{batch_request[:ops].size}. Call_number: #{(start/request_per_call) + 1}")
|
254
|
+
response = connec_client.post('/batch', batch_request)
|
255
|
+
response = JSON.parse(response.body)
|
256
|
+
|
257
|
+
# Parse barch response
|
258
|
+
response['results'].each_with_index do |result, index|
|
259
|
+
if result['status'] == 200
|
260
|
+
batch_entities[index][:idmap].update_attributes(last_push_to_connec: Time.now, message: nil)
|
261
|
+
elsif result['status'] == 201
|
262
|
+
batch_entities[index][:idmap].update_attributes(connec_id: result['body'][self.class.normalize_connec_entity_name(connec_entity_name)]['id'], last_push_to_connec: Time.now, message: nil)
|
263
|
+
else
|
264
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('error', organization, "Error while pushing to Connec!: #{result['body']}")
|
265
|
+
batch_entities[index][:idmap].update_attributes(message: result['body'])
|
266
|
+
end
|
267
|
+
end
|
268
|
+
start += request_per_call
|
269
|
+
end
|
261
270
|
end
|
262
271
|
|
263
|
-
def
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
272
|
+
def batch_op(method, mapped_external_entity, id, connec_entity_name, organization)
|
273
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending #{method.upcase} #{connec_entity_name}: #{mapped_external_entity} to Connec! (Preparing batch request)")
|
274
|
+
{
|
275
|
+
method: method,
|
276
|
+
url: "/api/v2/#{organization.uid}/#{connec_entity_name}" + (id.nil? ? '' : "/#{id}"),
|
277
|
+
params: {
|
278
|
+
"#{connec_entity_name}".to_sym => mapped_external_entity
|
279
|
+
}
|
280
|
+
}
|
270
281
|
end
|
271
282
|
|
272
283
|
def map_to_external_with_idmap(entity, organization)
|
@@ -23,8 +23,8 @@ module Maestrano::Connector::Rails
|
|
23
23
|
#===================================
|
24
24
|
has_many :user_organization_rels
|
25
25
|
has_many :users, through: :user_organization_rels
|
26
|
-
has_many :id_maps
|
27
|
-
has_many :synchronizations
|
26
|
+
has_many :id_maps, dependent: :destroy
|
27
|
+
has_many :synchronizations, dependent: :destroy
|
28
28
|
|
29
29
|
#===================================
|
30
30
|
# Validation
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Maestrano::Connector::Rails
|
2
2
|
class Synchronization < ActiveRecord::Base
|
3
|
+
# Keeping only 100 synchronizations per organization
|
4
|
+
after_create :clean_synchronizations
|
3
5
|
|
4
6
|
#===================================
|
5
7
|
# Associations
|
@@ -35,5 +37,12 @@ module Maestrano::Connector::Rails
|
|
35
37
|
def set_partial
|
36
38
|
self.update_attributes(partial: true)
|
37
39
|
end
|
40
|
+
|
41
|
+
def clean_synchronizations
|
42
|
+
count = self.organization.synchronizations.count
|
43
|
+
if count > 100
|
44
|
+
self.organization.synchronizations.limit(count - 100).destroy_all
|
45
|
+
end
|
46
|
+
end
|
38
47
|
end
|
39
48
|
end
|
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: maestrano-connector-rails 0.
|
5
|
+
# stub: maestrano-connector-rails 0.4.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "maestrano-connector-rails"
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.4.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Pierre Berard"]
|
14
|
-
s.date = "2016-04-
|
14
|
+
s.date = "2016-04-14"
|
15
15
|
s.description = "Maestrano is the next generation marketplace for SME applications. See https://maestrano.com for details."
|
16
16
|
s.email = "pierre.berard@maestrano.com"
|
17
17
|
s.executables = ["rails"]
|
@@ -162,7 +162,7 @@ Gem::Specification.new do |s|
|
|
162
162
|
"spec/models/entity_spec.rb",
|
163
163
|
"spec/models/external_spec.rb",
|
164
164
|
"spec/models/id_map_spec.rb",
|
165
|
-
"spec/models/
|
165
|
+
"spec/models/organization_spec.rb",
|
166
166
|
"spec/models/sub_entity_base_spec.rb",
|
167
167
|
"spec/models/synchronization_spec.rb",
|
168
168
|
"spec/models/user_organization_rel_spec.rb",
|
@@ -181,6 +181,8 @@ Gem::Specification.new do |s|
|
|
181
181
|
"template/settings/settings.yml",
|
182
182
|
"template/settings/test.yml",
|
183
183
|
"template/settings/uat.yml",
|
184
|
+
"template/sidekiq.rb",
|
185
|
+
"template/sidekiq.yml",
|
184
186
|
"template/spec_helper.rb"
|
185
187
|
]
|
186
188
|
s.homepage = "http://github.com/maestrano/maestrano-connector-rails"
|
@@ -19,6 +19,32 @@ describe Maestrano::Connector::Rails::SynchronizationJob do
|
|
19
19
|
context 'with sync_enabled set to true' do
|
20
20
|
before {organization.update(sync_enabled: true)}
|
21
21
|
|
22
|
+
describe 'recovery mode' do
|
23
|
+
describe 'skipping' do
|
24
|
+
before {
|
25
|
+
3.times do
|
26
|
+
organization.synchronizations.create(status: 'ERROR')
|
27
|
+
end
|
28
|
+
}
|
29
|
+
|
30
|
+
it 'skipped the sync if 3 failed sync' do
|
31
|
+
expect{ subject }.to_not change{ Maestrano::Connector::Rails::Synchronization.count }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'not skipping' do
|
36
|
+
before {
|
37
|
+
3.times do
|
38
|
+
organization.synchronizations.create(status: 'ERROR', created_at: 2.day.ago, updated_at: 2.day.ago)
|
39
|
+
end
|
40
|
+
}
|
41
|
+
|
42
|
+
it 'does not skip the sync if 3 failed sync but last sync more than a day ago' do
|
43
|
+
expect{ subject }.to change{ Maestrano::Connector::Rails::Synchronization.count }.by(1)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
22
48
|
it 'creates a synchronization' do
|
23
49
|
expect{ subject }.to change{ Maestrano::Connector::Rails::Synchronization.count }.by(1)
|
24
50
|
end
|
@@ -141,13 +141,13 @@ describe Maestrano::Connector::Rails::ComplexEntity do
|
|
141
141
|
|
142
142
|
it 'calls external_model_to_connec_model' do
|
143
143
|
allow(subject).to receive(:connec_model_to_external_model).and_return({})
|
144
|
-
expect(subject).to receive(:external_model_to_connec_model).with({a: {}}).and_return({})
|
144
|
+
expect(subject).to receive(:external_model_to_connec_model).with({a: {}}, organization).and_return({})
|
145
145
|
subject.consolidate_and_map_data({}, {a: {}}, organization, opt)
|
146
146
|
end
|
147
147
|
|
148
148
|
it 'calls connec_model_to_external_model' do
|
149
149
|
allow(subject).to receive(:external_model_to_connec_model).and_return({})
|
150
|
-
expect(subject).to receive(:connec_model_to_external_model).with({a: {}}).and_return({})
|
150
|
+
expect(subject).to receive(:connec_model_to_external_model).with({a: {}}, organization).and_return({})
|
151
151
|
subject.consolidate_and_map_data({a: {}}, {}, organization, opt)
|
152
152
|
end
|
153
153
|
|
@@ -388,7 +388,7 @@ describe Maestrano::Connector::Rails::ComplexEntity do
|
|
388
388
|
allow(klass).to receive(:external?).and_return(true)
|
389
389
|
allow(klass).to receive(:entity_name).and_return('n')
|
390
390
|
end
|
391
|
-
allow(client).to receive(:
|
391
|
+
allow(client).to receive(:post).and_return(ActionDispatch::Response.new(200, {}, {results: [{status: 200, body: {connec1s: {}}}]}.to_json, {}))
|
392
392
|
}
|
393
393
|
it 'is successful' do
|
394
394
|
subject.push_entities_to_connec(client, external_hash, organization)
|
data/spec/models/entity_spec.rb
CHANGED
@@ -281,7 +281,7 @@ describe Maestrano::Connector::Rails::Entity do
|
|
281
281
|
before {
|
282
282
|
allow(client).to receive(:get).and_return(nil)
|
283
283
|
}
|
284
|
-
it { expect{ subject.get_connec_entities(client, nil, organization) }.to raise_error("No data received from Connec! when trying to fetch #{connec_name.pluralize}") }
|
284
|
+
it { expect{ subject.get_connec_entities(client, nil, organization) }.to raise_error("No data received from Connec! when trying to fetch #{connec_name.pluralize.downcase}") }
|
285
285
|
end
|
286
286
|
end
|
287
287
|
|
@@ -294,7 +294,7 @@ describe Maestrano::Connector::Rails::Entity do
|
|
294
294
|
end
|
295
295
|
|
296
296
|
describe 'push_entities_to_connec_to' do
|
297
|
-
let(:organization) { create(:organization) }
|
297
|
+
let(:organization) { create(:organization, uid: 'cld-123') }
|
298
298
|
let(:idmap1) { create(:idmap, organization: organization) }
|
299
299
|
let(:idmap2) { create(:idmap, organization: organization, connec_id: nil, last_push_to_connec: nil) }
|
300
300
|
let(:entity1) { {name: 'John'} }
|
@@ -310,8 +310,7 @@ describe Maestrano::Connector::Rails::Entity do
|
|
310
310
|
}
|
311
311
|
|
312
312
|
it 'does nothing' do
|
313
|
-
expect(subject).to_not receive(:
|
314
|
-
expect(subject).to_not receive(:update_connec_entity)
|
313
|
+
expect(subject).to_not receive(:batch_op)
|
315
314
|
subject.push_entities_to_connec_to(client, entities_with_idmaps, connec_name, organization)
|
316
315
|
end
|
317
316
|
end
|
@@ -319,66 +318,118 @@ describe Maestrano::Connector::Rails::Entity do
|
|
319
318
|
context 'when create_only' do
|
320
319
|
before {
|
321
320
|
allow(subject.class).to receive(:can_update_connec?).and_return(false)
|
321
|
+
allow(client).to receive(:post).and_return(ActionDispatch::Response.new(200, {}, {results: []}.to_json, {}))
|
322
322
|
}
|
323
|
-
|
324
|
-
|
325
|
-
expect(subject).
|
323
|
+
|
324
|
+
it 'creates batch op for create only' do
|
325
|
+
expect(subject).to receive(:batch_op).once.with('post', entity2, nil, connec_name.downcase.pluralize, organization)
|
326
|
+
expect(subject).to_not receive(:batch_op).with('put', any_args)
|
326
327
|
subject.push_entities_to_connec_to(client, entities_with_idmaps, connec_name, organization)
|
327
328
|
end
|
328
329
|
end
|
329
330
|
|
330
|
-
|
331
|
-
|
332
|
-
|
331
|
+
context 'without errors' do
|
332
|
+
let(:result200) { {status: 200, body: {connec_name.downcase.pluralize.to_sym => {}}} }
|
333
|
+
let(:result201) { {status: 201, body: {connec_name.downcase.pluralize.to_sym => {id: id}}} }
|
334
|
+
before {
|
335
|
+
allow(client).to receive(:post).and_return(ActionDispatch::Response.new(200, {}, {results: [result200, result201]}.to_json, {}))
|
336
|
+
}
|
333
337
|
|
334
|
-
|
335
|
-
|
336
|
-
|
338
|
+
let(:batch_request) {
|
339
|
+
{
|
340
|
+
sequential: true,
|
341
|
+
ops: [
|
342
|
+
{
|
343
|
+
:method=>"put",
|
344
|
+
:url=>"/api/v2/cld-123/people/#{idmap1.connec_id}",
|
345
|
+
:params=>{:people=>{:name=>"John"}}
|
346
|
+
},
|
347
|
+
{
|
348
|
+
:method=>"post",
|
349
|
+
:url=>"/api/v2/cld-123/people",
|
350
|
+
:params=>{:people=>{:name=>"Jane"}}
|
351
|
+
}
|
352
|
+
]
|
353
|
+
}
|
354
|
+
}
|
337
355
|
|
338
|
-
|
356
|
+
it 'calls batch op' do
|
357
|
+
expect(subject).to receive(:batch_op).twice
|
358
|
+
subject.push_entities_to_connec_to(client, entities_with_idmaps, connec_name, organization)
|
359
|
+
end
|
339
360
|
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
expect(idmap2.last_push_to_connec).to_not be_nil
|
345
|
-
end
|
361
|
+
it 'creates a batch request' do
|
362
|
+
expect(client).to receive(:post).with('/batch', batch_request)
|
363
|
+
subject.push_entities_to_connec_to(client, entities_with_idmaps, connec_name, organization)
|
364
|
+
end
|
346
365
|
|
347
|
-
|
348
|
-
|
349
|
-
idmap1.reload
|
350
|
-
expect(idmap1.message).to_not be nil
|
351
|
-
end
|
352
|
-
end
|
366
|
+
it 'update the idmaps' do
|
367
|
+
old_push_date = idmap1.last_push_to_connec
|
353
368
|
|
354
|
-
|
355
|
-
let(:entity) { {name: 'John'} }
|
369
|
+
subject.push_entities_to_connec_to(client, entities_with_idmaps, connec_name, organization)
|
356
370
|
|
357
|
-
|
358
|
-
|
359
|
-
|
371
|
+
idmap1.reload
|
372
|
+
expect(idmap1.last_push_to_connec).to_not eql(old_push_date)
|
373
|
+
idmap2.reload
|
374
|
+
expect(idmap2.connec_id).to eql(id)
|
375
|
+
expect(idmap2.last_push_to_connec).to_not be_nil
|
376
|
+
end
|
360
377
|
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
end
|
378
|
+
describe 'batch batch calls' do
|
379
|
+
let(:entities) { [] }
|
380
|
+
let(:results) { [] }
|
365
381
|
|
366
|
-
|
367
|
-
|
382
|
+
context 'when 100 entities' do
|
383
|
+
before {
|
384
|
+
100.times do
|
385
|
+
entities << entity_with_idmap1
|
386
|
+
results << result200
|
387
|
+
end
|
388
|
+
allow(client).to receive(:post).and_return(ActionDispatch::Response.new(200, {}, {results: results}.to_json, {}))
|
389
|
+
}
|
390
|
+
|
391
|
+
it 'does one call' do
|
392
|
+
expect(client).to receive(:post).once
|
393
|
+
subject.push_entities_to_connec_to(client, entities, connec_name, organization)
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
context 'when more than 100 entities' do
|
398
|
+
before {
|
399
|
+
100.times do
|
400
|
+
entities << entity_with_idmap1
|
401
|
+
results << result200
|
402
|
+
end
|
403
|
+
entities << entity_with_idmap2
|
404
|
+
allow(client).to receive(:post).and_return(ActionDispatch::Response.new(200, {}, {results: results}.to_json, {}), ActionDispatch::Response.new(200, {}, {results: [result201]}.to_json, {}))
|
405
|
+
}
|
406
|
+
|
407
|
+
it 'does several call' do
|
408
|
+
expect(client).to receive(:post).twice
|
409
|
+
subject.push_entities_to_connec_to(client, entities, connec_name, organization)
|
410
|
+
end
|
411
|
+
|
412
|
+
it 'updates the idmap' do
|
413
|
+
subject.push_entities_to_connec_to(client, entities, connec_name, organization)
|
414
|
+
idmap2.reload
|
415
|
+
expect(idmap2.connec_id).to eql(id)
|
416
|
+
expect(idmap2.last_push_to_connec).to_not be_nil
|
417
|
+
end
|
418
|
+
end
|
419
|
+
end
|
368
420
|
end
|
369
|
-
end
|
370
421
|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
allow(client).to receive(:put).and_return(ActionDispatch::Response.new(200, {}, {}.to_json, {}))
|
377
|
-
}
|
422
|
+
context 'with errors' do
|
423
|
+
let(:result400) { {status: 400, body: 'Not Found'} }
|
424
|
+
before {
|
425
|
+
allow(client).to receive(:post).and_return(ActionDispatch::Response.new(200, {}, {results: [result400, result400]}.to_json, {}))
|
426
|
+
}
|
378
427
|
|
379
|
-
|
380
|
-
|
381
|
-
|
428
|
+
it 'stores the errr in the idmap' do
|
429
|
+
subject.push_entities_to_connec_to(client, entities_with_idmaps, '', organization)
|
430
|
+
idmap2.reload
|
431
|
+
expect(idmap2.message).to eq result400[:body]
|
432
|
+
end
|
382
433
|
end
|
383
434
|
end
|
384
435
|
|
@@ -13,8 +13,8 @@ describe Maestrano::Connector::Rails::Organization do
|
|
13
13
|
#Associations
|
14
14
|
it { should have_many(:user_organization_rels) }
|
15
15
|
it { should have_many(:users) }
|
16
|
-
it { should have_many(:id_maps) }
|
17
|
-
it { should have_many(:synchronizations) }
|
16
|
+
it { should have_many(:id_maps).dependent(:destroy) }
|
17
|
+
it { should have_many(:synchronizations).dependent(:destroy) }
|
18
18
|
|
19
19
|
describe 'creation' do
|
20
20
|
subject { Maestrano::Connector::Rails::Organization.new }
|
@@ -71,5 +71,27 @@ describe Maestrano::Connector::Rails::Synchronization do
|
|
71
71
|
expect(sync.partial).to be(true)
|
72
72
|
end
|
73
73
|
end
|
74
|
+
|
75
|
+
describe 'clean_synchronizations' do
|
76
|
+
let!(:organization) { create(:organization) }
|
77
|
+
let!(:sync) { create(:synchronization, organization: organization) }
|
78
|
+
let!(:sync2) { create(:synchronization, organization: organization) }
|
79
|
+
|
80
|
+
context 'when less than 100 syncs' do
|
81
|
+
it 'does nothing' do
|
82
|
+
expect{ sync.clean_synchronizations }.to_not change{ organization.synchronizations.count }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'when more than 100 syncs' do
|
87
|
+
before {
|
88
|
+
allow_any_instance_of(ActiveRecord::Associations::CollectionProxy).to receive(:count).and_return(102)
|
89
|
+
}
|
90
|
+
|
91
|
+
it 'destroy the idmaps' do
|
92
|
+
expect{ sync.clean_synchronizations }.to change{ Maestrano::Connector::Rails::Synchronization.count }.by(-2)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
74
96
|
end
|
75
97
|
end
|
@@ -61,6 +61,12 @@ gem 'uglifier', '>= 1.3.0'
|
|
61
61
|
gem 'maestrano-connector-rails'
|
62
62
|
gem 'config'
|
63
63
|
|
64
|
+
# Background jobs
|
65
|
+
gem 'sinatra', :require => nil
|
66
|
+
gem 'sidekiq'
|
67
|
+
gem 'sidekiq-cron'
|
68
|
+
gem 'slim'
|
69
|
+
|
64
70
|
|
65
71
|
gem_group :test do
|
66
72
|
gem 'simplecov'
|
@@ -95,6 +101,10 @@ after_bundle do
|
|
95
101
|
run 'echo \'uat:
|
96
102
|
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>\' >> config/secrets.yml'
|
97
103
|
|
104
|
+
# Sidekiq
|
105
|
+
copy_file 'sidekiq.yml', 'config/sidekiq.yml'
|
106
|
+
copy_file 'sidekiq.rb', 'config/initializers/sidekiq.rb'
|
107
|
+
|
98
108
|
# Settings
|
99
109
|
run 'bundle exec rails g config:install'
|
100
110
|
remove_dir 'config/settings'
|
data/template/routes.rb
CHANGED
@@ -10,4 +10,11 @@ Rails.application.routes.draw do
|
|
10
10
|
|
11
11
|
get 'synchronizations/index' => 'synchronizations#index'
|
12
12
|
get 'shared_entities/index' => 'shared_entities#index'
|
13
|
+
|
14
|
+
# Sidekiq Admin
|
15
|
+
require 'sidekiq/web'
|
16
|
+
Sidekiq::Web.use Rack::Auth::Basic do |username, password|
|
17
|
+
username == ENV['SIDEKIQ_USERNAME'] && password == ENV['SIDEKIQ_PASSWORD']
|
18
|
+
end
|
19
|
+
mount Sidekiq::Web => '/sidekiq'
|
13
20
|
end
|
data/template/sidekiq.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Sidekiq::Cron::Job.create(name: 'AllSynchronizationsJob runs every hour', cron: '0 * * * *', class: 'Maestrano::Connector::Rails::AllSynchronizationsJob')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: maestrano-connector-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pierre Berard
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-04-
|
11
|
+
date: 2016-04-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: maestrano-rails
|
@@ -372,7 +372,7 @@ files:
|
|
372
372
|
- spec/models/entity_spec.rb
|
373
373
|
- spec/models/external_spec.rb
|
374
374
|
- spec/models/id_map_spec.rb
|
375
|
-
- spec/models/
|
375
|
+
- spec/models/organization_spec.rb
|
376
376
|
- spec/models/sub_entity_base_spec.rb
|
377
377
|
- spec/models/synchronization_spec.rb
|
378
378
|
- spec/models/user_organization_rel_spec.rb
|
@@ -391,6 +391,8 @@ files:
|
|
391
391
|
- template/settings/settings.yml
|
392
392
|
- template/settings/test.yml
|
393
393
|
- template/settings/uat.yml
|
394
|
+
- template/sidekiq.rb
|
395
|
+
- template/sidekiq.yml
|
394
396
|
- template/spec_helper.rb
|
395
397
|
homepage: http://github.com/maestrano/maestrano-connector-rails
|
396
398
|
licenses:
|