【问题标题】:How could I use Redis calls in trap context in Ruby?如何在 Ruby 的陷阱上下文中使用 Redis 调用?
【发布时间】:2015-03-02 04:10:27
【问题描述】:

我的脚本从 redis 数据库中获取元素并对其进行一些处理。我需要确保如果脚本以 ^C 或其他信号结束,则该元素将返回到数据库中。 我正在努力做到这一点

require "redis"

class Test
  attr_reader :quit

  def initialize
    @redis = Redis.new
  end

  def trap_signal
    trap("INT") {
      puts "get ready to exit"
      @redis.rpush "TestQueue", @elem # I need to be sure that @emelent always puts back in the database 
      @quit = true}
  end

  def run!
    trap_signal
    @elem = "test string"
    @redis.rpush "TestQueue", @elem
    while !quit
      @redis.blpop "TestQueue", @elem
      # Do some work whith @element
      sleep 1
      # And put it back in the database 
      @redis.rpush "TestQueue", @elem
    end
  end

end

Test.new.run!

但得到这个错误

^Cget ready to exit
/usr/lib/ruby/2.1.0/monitor.rb:185:in `lock': can't be called from trap context (ThreadError)
    from /usr/lib/ruby/2.1.0/monitor.rb:185:in `mon_enter'
    from /usr/lib/ruby/2.1.0/monitor.rb:209:in `mon_synchronize'
    from /home/kusayu/.gem/ruby/2.1.0/gems/redis-3.2.0/lib/redis.rb:37:in `synchronize'
    from /home/kusayu/.gem/ruby/2.1.0/gems/redis-3.2.0/lib/redis.rb:991:in `rpush'
    from test.rb:13:in `block in trap_signal'
    from test.rb:24:in `call'
    from test.rb:24:in `sleep'
    from test.rb:24:in `run!'
    from test.rb:32:in `<main>'

【问题讨论】:

  • 你指的是事务锁定吗?如果是,您应该阅读redis.io/topics/transactions
  • @kiddorails 我不使用事务,我只需要在中断时将我的应用程序的当前状态保存到 redis 结构中。这个错误似乎令人沮丧,我不知道为什么会发生。

标签: ruby redis


【解决方案1】:

您的代码已经正常工作,只需从信号处理程序中删除 @redis.rpush

您不应该在信号处理程序中运行“繁重”操作(无论如何您都会因此而得到异常)。最好使用像@quit = true 这样的变量来通知主循环该结束了,然后让主循环处理适当的清理工作。

因此,如果您只是从 INT 信号处理程序中删除 @redis.rpush,那么您将确保将元素返回到数据库中,因为主循环只会在 @quittrue 时完成。

【讨论】:

  • 我没有足够的声誉来支持您的回答,但我想说声谢谢。你真的把我从更多的不眠之夜中拯救了出来。
猜你喜欢
  • 1970-01-01
  • 2010-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-10
  • 2011-03-27
  • 2011-02-06
  • 1970-01-01
相关资源
最近更新 更多