Ruby 升级到Rails 5后,活动记录回调始终停止工作

Ruby 升级到Rails 5后,活动记录回调始终停止工作,ruby,callback,ruby-on-rails-5,Ruby,Callback,Ruby On Rails 5,我最近将一个应用程序从Rails 4.2升级到了5.2。该应用程序包括几个活动记录回调,用户输入一个值或单击一个按钮,然后发出回调以继续程序。升级后,这些回调不再在生产中持续工作。本地工作正常,但一旦部署(使用capistrano),通常需要3-6次尝试才能通过回调。这是我的回调类: module CallAfterCommit def self.included(base) base.after_commit :notify_commit # piggyback off activ

我最近将一个应用程序从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,现在一切正常。

这最终成为puma workers的一个问题。我在deploy.rb文件中将puma_workers设置为1,现在一切正常