Skip to content

Instantly share code, notes, and snippets.

@jonsgreen
Created March 10, 2015 20:40
Show Gist options
  • Save jonsgreen/9cc19a9bdb0eeb2cda59 to your computer and use it in GitHub Desktop.
Save jonsgreen/9cc19a9bdb0eeb2cda59 to your computer and use it in GitHub Desktop.
Mailchimp integration with locking
def sync
loop do
User.transaction do
@supporter_batch = supporter_batch_relation.lock
@supporters = @supporter_batch.to_a
break if @supporters.size <= MIN_BATCH_SIZE
@supporter_batch.update_all(mail_service_identifier: 'pending')
end
@supporters.map do |supporter|
sync_supporter(supporter)
end
end
rescue Exception => e
User.where(id: @supporters.map(&:id), mail_service_identifier: 'pending')
.update_all(mail_service_identifier: nil)
raise e
end
def supporter_batch_relation
User.where(mail_service_identifier: nil).limit(BATCH_SIZE)
end
def sync_supporter(supporter)
supporter.language ||= supporter.movement.default_language
result = call_api(:subscribe, { email: { email: supporter.email },
merge_vars: {
COUNTRY: supporter.language.iso_code,
SOURCE: 'Purpose'},
double_optin: false,
update_existing: true})
supporter.mail_service_identifier = result['euid']
supporter.save!
result
rescue Gibbon::MailChimpError => e
if e.message.match(/(Signup disabled|invalid)/)
supporter.update_attribute(:mail_service_identifier, 'invalid')
else
Honeybadger.notify(e)
end
end
fit 'locks pending supporters to avoid deadlocks', type: :concurrent do
expect(User.where(mail_service_identifier: nil).count).to eq(3)
ActiveRecord::Base.connection.disconnect!
pid = Process.fork do
ActiveRecord::Base.establish_connection
Apartment::Tenant.switch 'test'
original_update = User::ActiveRecord_Relation.instance_method(:update_all)
expect_any_instance_of(User::ActiveRecord_Relation)
.to receive(:update_all) do |relation, conditions|
puts 'first'
sleep 2
original_update.bind(relation).call(conditions)
end
mailchimp.sync
end
sleep 1
puts 'second'
ActiveRecord::Base.establish_connection
Apartment::Tenant.switch 'test'
expect(User.update_all(mail_service_identifier: 'pending')).to eq(1)
sleep 5
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment