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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1bbfaa5ac97f708d566708de56514b14bbddb040
4
- data.tar.gz: 72fb30f4f46dd655388cf485b0f8ef7baa89e9ce
3
+ metadata.gz: 296c3f72e80c6876a39e3161e752292bad97d03f
4
+ data.tar.gz: 155def8dc10315c64595ae0c4e6284890f896254
5
5
  SHA512:
6
- metadata.gz: 29e41e854f2b8fa36cc6b129c64cf1abda814de8ede2d3d975557ae85ca730306ef973d6276a0da137ca18a7fa6f1d1f684f9127106ecbbc88ceac4b709943d3
7
- data.tar.gz: c3e7b00e9e92829e32e243d94e82a15696e517a4a297101a0a6d082f6c24752033eec20b10791ac3ed36d604a0673248f985fa025c775d440e5b243e3581cfbc
6
+ metadata.gz: 97e21e2088c3d7774052fe11aa6380e456dfa884a1165a57696bc21b723db99696410cde4011d2c6f9824a92d0e15fa7251d2c21a48dd6892ec3ea0293264879
7
+ data.tar.gz: 9915cf3654bb531970ccaf5dee230a53ec5de525b96b08659bd2dd912d67eca7457619c8f5545c9695daa63b6d1594c2084f7d1d58e1995adb0d415f729b158d
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.13
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
- previous_synchronization = Synchronization.where(organization_id: organization.id).order(created_at: :desc).first
15
- if previous_synchronization && previous_synchronization.status == 'RUNNING' && previous_synchronization.created_at > (Time.now - 30.minutes)
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
- true
120
+ can_write_external?
121
121
  end
122
122
 
123
123
  def can_read_external?
124
- true
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.connec_entity_name.pluralize}" unless response
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.connec_entity_name.pluralize}"
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
- mapped_external_entities_with_idmaps.each do |mapped_external_entity_with_idmap|
235
- external_entity = mapped_external_entity_with_idmap[:entity]
236
- idmap = mapped_external_entity_with_idmap[:idmap]
237
-
238
- begin
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
- connec_entity = create_connec_entity(connec_client, external_entity, self.class.normalize_connec_entity_name(connec_entity_name), organization)
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
- connec_entity = update_connec_entity(connec_client, external_entity, idmap.connec_id, self.class.normalize_connec_entity_name(connec_entity_name), organization)
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
- def create_connec_entity(connec_client, mapped_external_entity, connec_entity_name, organization)
256
- Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending create #{connec_entity_name}: #{mapped_external_entity} to Connec!")
257
- response = connec_client.post("/#{connec_entity_name}", { "#{connec_entity_name}".to_sym => mapped_external_entity })
258
- response = JSON.parse(response.body)
259
- raise "Connec!: #{response['errors']['title']}" if response['errors'] && response['errors']['title']
260
- response["#{connec_entity_name}"]
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 update_connec_entity(connec_client, mapped_external_entity, connec_id, connec_entity_name, organization)
264
-
265
- Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending update #{connec_entity_name}: #{mapped_external_entity} to Connec!")
266
- response = connec_client.put("/#{connec_entity_name}/#{connec_id}", { "#{connec_entity_name}".to_sym => mapped_external_entity })
267
- response = JSON.parse(response.body)
268
- raise "Connec!: #{response['errors']['title']}" if response['errors'] && response['errors']['title']
269
- response["#{connec_entity_name}"]
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
@@ -22,6 +22,7 @@ class OauthController < ApplicationController
22
22
  if organization && is_admin?(current_user, organization)
23
23
  # TODO
24
24
  # Update organization with oauth params
25
+ # Should at least set oauth_uid, oauth_token and oauth_provider
25
26
  end
26
27
 
27
28
  redirect_to root_url
@@ -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.3.13 ruby lib
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.3.13"
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-08"
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/organizaztion_spec.rb",
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(:put).and_return(ActionDispatch::Response.new(200, {}, {people: {}}.to_json, {}))
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)
@@ -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(:create_connec_entity)
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
- it 'calls create only' do
324
- expect(subject).to receive(:create_connec_entity).with(client, entity2, connec_name.downcase.pluralize, organization)
325
- expect(subject).to_not receive(:update_connec_entity)
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
- it 'create or update the entities and idmaps according to their idmap state' do
331
- allow(subject).to receive(:create_connec_entity).and_return({'id' => id})
332
- allow(subject).to receive(:external_entity_name).and_return(external_name)
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
- expect(subject).to receive(:create_connec_entity).with(client, entity2, connec_name.downcase.pluralize, organization)
335
- expect(subject).to receive(:update_connec_entity).with(client, entity1, idmap1.connec_id, connec_name.downcase.pluralize, organization)
336
- old_push_date = idmap1.last_push_to_connec
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
- subject.push_entities_to_connec_to(client, entities_with_idmaps, connec_name, organization)
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
- idmap1.reload
341
- expect(idmap1.last_push_to_connec).to_not eql(old_push_date)
342
- idmap2.reload
343
- expect(idmap2.connec_id).to eql(id)
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
- it 'stores an errr if any in the idmap' do
348
- subject.push_entities_to_connec_to(client, entities_with_idmaps, '', organization)
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
- describe 'create_connec_entity' do
355
- let(:entity) { {name: 'John'} }
369
+ subject.push_entities_to_connec_to(client, entities_with_idmaps, connec_name, organization)
356
370
 
357
- before {
358
- allow(client).to receive(:post).and_return(ActionDispatch::Response.new(200, {}, {people: entity}.to_json, {}))
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
- it 'sends a post to connec' do
362
- expect(client).to receive(:post).with("/#{connec_name.downcase.pluralize}", {"#{connec_name.downcase.pluralize}".to_sym => entity})
363
- subject.create_connec_entity(client, entity, connec_name.downcase.pluralize, organization)
364
- end
378
+ describe 'batch batch calls' do
379
+ let(:entities) { [] }
380
+ let(:results) { [] }
365
381
 
366
- it 'returns the created entity' do
367
- expect(subject.create_connec_entity(client, entity, connec_name.downcase.pluralize, organization)).to eql(JSON.parse(entity.to_json))
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
- describe 'update_connec_entity' do
372
- let(:organization) { create(:organization) }
373
- let(:entity) { {name: 'John'} }
374
- let(:id) { '88ye-777ab' }
375
- before {
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
- it 'sends a put to connec' do
380
- expect(client).to receive(:put).with("/#{connec_name.downcase.pluralize}/#{id}", {"#{connec_name.downcase.pluralize}".to_sym => entity})
381
- subject.update_connec_entity(client, entity, id, connec_name.downcase.pluralize, organization)
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
@@ -0,0 +1 @@
1
+ Sidekiq::Cron::Job.create(name: 'AllSynchronizationsJob runs every hour', cron: '0 * * * *', class: 'Maestrano::Connector::Rails::AllSynchronizationsJob')
@@ -0,0 +1,4 @@
1
+ ---
2
+ :queues:
3
+ - default
4
+ :concurrency: 5
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.3.13
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-08 00:00:00.000000000 Z
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/organizaztion_spec.rb
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: