【问题标题】:Rails Job loses reference to module randomlyRails Job 随机丢失对模块的引用
【发布时间】:2021-04-05 08:29:00
【问题描述】:

编辑:当我手动分叉一个进程时也会发生同样的事情......
我在 Rails 作业中遇到了一些奇怪的行为,该作业调用了我的一个名为 RedisService 的模块。
我已将lib/modules 添加到我的autoload_paths 中,但调用RedisServiceTextService 模块失去了对它的引用,有时是立即,有时是3 或4 个工作调用...
我什至要求我的 TextService 中的模块无济于事,甚至添加了一些 put 来检查是否始终显示模块已定义并响应我正在调用的方法...!
有什么东西逃过了我... Here's a gist to the backtrace
回购:https://gitlab.com/thomasbromehead/snmp-simulator-ruby-managerruby --version: 2.6.5 rails version: 6.1.3.1

我的“服务”对象: 调用 RedisService 的模块

require_relative 'redis_service'

module TextService
  def self.write_to_file(dataObject, redis, path: "./")
    begin
      file_with_path = path + dataObject.filename
      # Store all lines prior to the one being modified, File.read closes the file
      f = File.read(file_with_path)
      new_content = f.gsub(dataObject.old_set_value, dataObject.new_set_value)
      # File.open closes the file when passed a block
      File.open(file_with_path, "w") { |file| file.puts new_content }
      puts "Redis is: #{redis}"                                    ======> RedisService
      puts "Redis responds to multi: #{redis.respond_to?(:multi)}" ======> true
      redis.multi do
        redis.zrem("#{dataObject.name}-sorted-set", dataObject.old_set_value)
        redis.hset("#{dataObject.name}-offsets", "#{dataObject.start_index}:#{dataObject.oid}:#{dataObject.end_index}", dataObject.new_set_value)
        redis.zadd("#{dataObject.name}-sorted-set", dataObject.start_index, dataObject.new_set_value)
      end
    rescue EOFError
    end
  end

从 VariateJob 调用的变体类

require_relative '../../../lib/modules/redis_service'

module Snmp
  class Variation
    include ActiveModel::Model

    attr_reader :oid, :type, :duration, :to, :from, :filename, :redis

    def initialize(oid:nil, duration:nil, type:nil, to:nil, filename: nil, from:nil)
      @to = to
      @from = from
      @oid = oid
      @type = type
      @filename = filename
      @redis = RedisService
    end

    def run(data)
      current_value, new_set_value, start_index, end_index  = prepare_values(JSON.parse(data))
      transferData = Snmp::TransferData.new({
        filename: @filename,
        old_set_value: current_value,
        new_set_value: new_set_value,
        start_index: start_index,
        end_index: end_index,
        name: @name,
        oid: oid
      })
      TextService.write_to_file(transferData, @redis)
    end

VariateJob

class VariateJob < ApplicationJob
  queue_as :default
  def perform(dumped_variation, data)
    Marshal.load(dumped_variation).run(Marshal.load(data))
  end
end

VariationsController

class VariationsController < ApplicationController
  before_action :set_file_name, only: :start

  def start
    if params["linear"]
      type = :linear
    elsif params["random"]
      type = :random
    end
    data = redis.hscan_each("#@name-offsets", match: "*:#{params["snmp_variation"]["oid"]}*")
    # data is an Enumerator, transform it to an array and dump to JSON
    variation = Snmp::Variation.new(params_to_keywords(params["snmp_variation"]).merge({type: type}))
    VariateJob.perform_later(Marshal.dump(variation), Marshal.dump(JSON.generate(data.to_a.first)))
  end

RedisService

require 'redis'

module RedisService
  include GlobalID::Identification

[...]
  def self.multi(&block)
    @redis.multi { block.call() }
  end
[...]
end

【问题讨论】:

  • 你的 RedisService 是什么样子的——尤其是这一行:/usr/src/snmpapp/lib/modules/redis_service.rb:102:in multi'? Because to me, it looks like the error is actually in the RedisService in that line. Is it possible that you call multi` 也在那一行?
  • 嗨@spickermann,我添加了RedisService的sn-p。我删除了 redis.multi 包装器并得到与redis.zrem 相同的错误,即使定义了 RedisService...

标签: ruby-on-rails ruby rails-activejob


【解决方案1】:

您没有丢失对 RedisService 的引用,而是丢失了 RedisService 中的 Redis。可能是因为你使用了一个 fork 新进程的服务器或 worker,并且你没有在 fork 之后初始化一个新的连接。

为了解决这个问题,我会替换这个方法

def self.start(host,port)
  @redis ||= Redis.new(host: host, port: port)
  self
end

def self.redis
  @redis ||= Redis.new(host: ::Snmpapp.redis_config[:host], port: ::Snmpapp.redis_config[:port])
end

然后我会将所有对@redis 的调用替换为对新方法的redis 调用。

【讨论】:

  • 嗨@spickermann,非常感谢,我不习惯工作,这是有道理的,因为进程不与其父进程共享内存,我失去了与我的redis容器的连接。非常感谢您花时间深入研究我的 gitlab 中的代码,这对像我这样的大三学生来说意义重大。如果您愿意,我很乐意将一些基本注意令牌发送给 pubkey。 Vielen danke
  • 非常感谢。但是你不需要给我任何代币。我很高兴回答有关 StackOverflow 信誉积分的问题。 ;-)
  • 哈哈,好精神 ;) 如果您想了解更多,请随时查看我在此处发布的另一个问题:stackoverflow.com/questions/42989462/…
  • 看起来您发布了新问题作为对另一个问题的回答。这不是在 StackOverflow 上应该这样做的方式,因此您的问题可能很快就会被删除。只需提出一个新问题即可。
猜你喜欢
  • 2021-05-22
  • 2017-06-05
  • 2016-08-29
  • 1970-01-01
  • 2013-05-15
  • 1970-01-01
  • 2011-04-23
  • 2012-06-01
  • 1970-01-01
相关资源
最近更新 更多