在升级到Rails5之后,活动记录回调一直停止工作



我最近将一个应用程序从Rails 4.2升级到5.2。该应用程序包括几个活动记录回调,用户在其中输入值或单击按钮,然后发出回调以继续执行程序。升级后,这些回调在生产中不再持续工作。在本地,一切都很好,但一旦部署(使用capistrano(,通常需要3-6次尝试才能完成回调。这是我的回调类:

module CallAfterCommit
def self.included(base)
base.after_commit :notify_commit # piggyback off active_record hook.
base.include(InstanceMethods)
base.extend(ClassMethods)
end
##
# Instance methods for CallAfterCommit mixin.
module InstanceMethods
##
# Takes a callback that will be called whenever any instance of this model with the same id is committed. The instance
# this method is called on must have an id set.
def add_after_commit_callback(&block)
raise "#{self} does not have an id yet, so it could not add callback" if id.nil?
self.class.add_after_commit_callback(id, &block)
end
##
# Removes instances of callback to be called when a model with this id is committed.
def remove_after_commit_callback(callback)
self.class.remove_after_commit_callback(id, callback)
end
##
# Returns true if the callback is registered for the model's id, and returns false otherwise.
def after_commit_callback?(callback)
self.class.after_commit_callback?(id, callback)
end
private
def notify_commit
self.class._notify_commit(id)
end
end
##
# Class methods for CallAfterCommit mixin.
module ClassMethods
##
# Add a callback to a set of callbacks for the given id. to be called after any instance with that id is committed.
# Returns the callback as a proc, which can be used to remove the after commit callback
def add_after_commit_callback(id, &block)
raise ArgumentError, "Cannot add callback. No record of id #{id} exists for #{self}." unless exists?(id)
raise ArgumentError, "Cannot add callback. Callback already exists for #{id}." if after_commit_callback?(id, block)
registered_callbacks[id] ||= []
registered_callbacks[id] |= [block]
block
end
##
#  Removes the callback for a given id. Raises an error if the callback cannot be removed.
def remove_after_commit_callback(id, callback)
raise "Could not remove callback because it is not registered for id #{id}" unless after_commit_callback?(id, callback)
registered_callbacks[id].delete(callback)
# Remove the hash entry to the empty array, so we don't collect every id ever listened to.
registered_callbacks.delete(id) if registered_callbacks[id].empty?
end
##
# Returns true if the callback is registered for the given id, and returns false otherwise.
def after_commit_callback?(id, callback)
!registered_callbacks[id].nil? && registered_callbacks[id].include?(callback)
end
##
#  Execute all the callbacks registered for this id.
def _notify_commit(id)
registered_callbacks[id]&.each(&:call)
end
private
##
# Returns a hash of ids to an array of callbacks
def registered_callbacks
# hash of ids to an array of callbacks
@registered_callbacks ||= {}
end
end
end

这里是使用上述回调的地方之一:

module WaitForUserSimple
def self.included(base)
base.after_initialize :setup_new_instance, if: :new_record? # piggyback off active_record hook.
end
##
# Receive message from the user. Expects params to have a key for :user_choice and looks for 'ok' or 'quit'
def receive_user_data(params)
logger.info 'received user data'
details.user_choice = params[:user_choice]
details.save!
end
def stop
logger.info 'Stopping simple user step'
receive_user_data(user_choice: 'quit')
end
private
def setup_new_instance
# We need this detail when we initialize, because we watch it when waiting for the user.
self.details ||= SimpleUserStepDetail.new(test_step: self)
end
def run_test_step
event = Concurrent::Event.new # Use this to let us know if there has been a save since we reloaded the details.
callback = details.add_after_commit_callback do
logger.info("Callback called. Setting event for #{self}")
event.set
end
while details.reload.user_choice.nil?
logger.info("#{self} waiting for details to be saved")
event.wait
event.reset
logger.info("#{self} notified that event was saved. Checking details.")
end
details.remove_after_commit_callback(callback)
logger.info("Got user choice: #{details.user_choice}")
details.user_choice == 'ok'
end
end

没有错误消息或日志记录语句来显示发生了什么。有人对可能出现的问题有任何建议吗?

这最终成为美洲狮工人的问题。我在deploy.rb文件中将puma_workers设置为1,现在一切正常。

最新更新