Skip to content

Instantly share code, notes, and snippets.

@Paxa
Last active May 12, 2017 08:38
Show Gist options
  • Save Paxa/6b9765c63526960198e0b04f56f7b24f to your computer and use it in GitHub Desktop.
Save Paxa/6b9765c63526960198e0b04f56f7b24f to your computer and use it in GitHub Desktop.
Safe way to run threads on rails
module Async
##
# Run code in thread, handle exceptions, release DB connections
#
# Async(:send_email) { Mailer.send }
#
def self.run(name)
parent_t = Thread.current
working_thread = Thread.new do
begin
# copy thread variables
# Rails and some other libraries may save something in thread variables
# such as Timezone and locale
parent_t.keys.each do |key|
next if key =~ /activerecord|activesupport|__recursive_key__/i
Thread.current[key] = parent_t[key]
end
# make sure DB connection is closed
ActiveRecord::Base.connection_pool.with_connection do
yield
end
rescue => error
Rails.logger.info "Error in thread!"
Rails.logger.info(error.message)
Rails.logger.info(error.backtrace.join("\n"))
# Send exception to airbrake/sentry/raygun/newrelic/slack
end
end
# Wait for code to finish in testing environment
# to avoid race condition when you expect changes made by thread
if Rails.env.test?
working_thread.join
end
working_thread
end
end
## USAGE:
Async.run do
user.send_welcome_email!
user.update!(welcome_email_sent: true)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment