FiberError - 跨线程调用的光纤

Ale*_*son 7 ruby ruby-on-rails fiber

我正在尝试在Rails应用程序中编写一个小功能,该应用程序使用随机词gem生成随机名词,然后将其复数.我第一次访问开发中的页面时能够让它工作,但是我想让脚本在每次加载页面时再次运行.现在,后续页面加载(直到我反弹服务器)给我FiberError in WelcomeController#randomwords,fiber called across threads.我试图自己解决这个问题,但我对编程很陌生,并不太了解Fibers的工作原理.我尝试使用Queue,但无法弄清楚如何让它工作,再次因为我不完全理解这个类.我该如何解决这个具体问题?

资料来源:welcome_helper.rb

def random
  noun = RandomWord.nouns.next.split('_').sample.pluralize
  if noun.include? "_"
    noun = noun.split("_").join.pluralize
  else
    noun.pluralize!
  end      
  return noun
end
Run Code Online (Sandbox Code Playgroud)

vin*_*aki 4

正如您现在可能已经发现的那样,问题在于 gemrandom-word不是线程安全的。更准确地说,RandomWord.nouns是一个模块级的 Enumerator跨线程访问枚举器是不安全的

但是,egQueue是线程安全的,因此对于此功能的线程安全替代方案,您可以nouns.dat从随机单词 gem 中获取,并Queue在初始化应用程序时将其所有单词随机洗牌到一个对象中。random_words_queue现在,假设可以在您的方法范围内访问该队列random。然后你可以将该random方法实现为

def random
  unless random_words_queue.empty?
    noun = random_words_queue.pop
    if noun.include? "_"
      noun = noun.split("_").join.pluralize
    else
      noun.pluralize!
    end      
    return noun
  end
end
Run Code Online (Sandbox Code Playgroud)

请注意,当前它仅在nil队列为空时返回,而您可能不希望出现这种情况。在这种情况下,您希望它如何表现取决于您的要求:

  • 如果有些可预测的单词不是安全问题,并且不太可能惹恼您的用户,那么我会noun在弹出它后立即将其推到队列后面。
  • 否则,你应该重新排列单词。

(无论如何,返回nil可能不是任何人想要的。)