【问题标题】:When block finishes executing, ruby interpreter does not continue to next instruction当块完成执行时,ruby 解释器不会继续执行下一条指令
【发布时间】:2018-04-13 05:42:26
【问题描述】:

我有以下执行顺序。当 import 被调用时,它会依次调用 perform_tasks,然后在 on_complete 上进入 redis 订阅循环:

class Record < ActiveRecord::Base
  def self.import(params)
    peform_tasks params[:record]
    on_complete
  end

  def self.peform_tasks(record_params)
    record_params.each do |param|
      AddressWorker.perform_async param
    end
  end

  def self.on_complete
    redis.subscribe('address_notifier') do |payload|
      on_post_execute payload
    end
    puts 'BUT WE NEVER GET HERE'
  end

  def self.on_post_execute(payload)
   puts 'Yes we get here'
  end
end

问题是当块完成执行,并且 on_post_execute 运行时,执行不会离开块。而且我们从不排队:

puts 'BUT WE NEVER GET HERE'

我们为什么不到达块后面的那一行?

请注意,使用 ruby​​ redis gem 中的redis.subscribe 在这里应该无关紧要,因为我到达了块,它是一个常规的 ruby​​ 块。

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    正如您所指出的,redis.subscribe 的使用在这里并不是完全不相关的。

    此方法是 loop,在您 unsubscribe 之前不会中断。因此,在这种情况下,我认为您实际上并没有退出该块,因此您的 puts 行不会被执行。

      def self.on_complete
        redis.subscribe_with_timeout(5, 'address_notifier') do |payload|
          on_post_execute payload
    
          redis.unsubscribe
        end
        puts 'Should get here now'
      end
    
      def self.on_post_execute(payload)
        puts 'Yes we get here'
      end
    

    或者使用subscribe_with_timeout:

      def self.on_complete
        redis.subscribe_with_timeout(5, 'address_notifier') do |payload|
          on_post_execute payload
        end
        puts 'Should get here now'
      end
    
      def self.on_post_execute(payload)
        puts 'Yes we get here'
      end
    

    【讨论】:

    • 我应该如何退订?我应该如何摆脱困境?
    • @Donato 应该能够在您拨打on_post_execute 之后从该块内拨打redis.unsubscribe
    • redis.unsubscribe 还不够!我不得不使用 break 关键字来打破障碍!
    • @Donato break 不是一个好主意,因为它会强制破坏块,即使它没有按照您的需要完成。 subscribe 方法中已经有条件中断子句。这需要保持条件,否则您将覆盖该方法的功能。你的是一个基本的用例,所以它可能不是问题,但如果你需要更复杂的逻辑,那会导致错误。相反,请尝试使用Redis#subscribe_with_timeout,这将在 5 秒后没有收到任何消息时优雅地退出块。我已经用一个例子更新了答案。
    • 我知道发生了什么。 Redis.current.get("address_validation_key") 返回一个字符串,我认为它返回一个整数。所以消息没有被发布。
    猜你喜欢
    • 2012-02-26
    • 2023-01-20
    • 2020-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多