maestrano-connector-rails 0.3.13 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: