我有一个Rails应用程序,其中我有一个Rake任务,它使用concurrent-ruby gem提供的多线程函数.
我不时会遇到Circular dependency detected while autoloading constant错误.
在谷歌搜索了一下后,我发现这与使用线程结合加载Rails常量有关.
我偶然发现了以下GitHub问题:https://github.com/ruby-concurrency/concurrent-ruby/issues/585和https://github.com/rails/rails/issues/26847
正如这里所解释的,你需要包装从一个Rails.application.reloader.wrap do或一个Rails.application.executor.wrap do块中的新线程调用的任何代码,这就是我所做的.但是,这会导致死锁.
然后建议ActiveSupport::Dependencies.interlock.permit_concurrent_loads用于在主线程上包装另一个阻塞调用.但是,我不确定应该用哪个代码包装.
这是我尝试过的,但这仍然会导致死锁:
@beanstalk = Beaneater.new("#{ENV.fetch("HOST", "host")}:#{ENV.fetch("BEANSTALK_PORT", "11300")}")
tube_name = ENV.fetch("BEANSTALK_QUEUE_NAME", "queue")
pool = Concurrent::FixedThreadPool.new(Concurrent.processor_count * 2)
# Process jobs from tube, the body of this block gets executed on each message received
@beanstalk.jobs.register(tube_name) do |job|
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
@logger.info "Received job: #{job.id}"
Concurrent::Future.execute(executor: pool) do
Rails.application.reloader.wrap do
# Stuff that references Rails constants etc
process_beanstalk_message(job.body) …Run Code Online (Sandbox Code Playgroud) 当我尝试在配备 Apple Silicon (M3) 的 MacBook Pro 上为新的 Rails 应用程序构建 Docker 映像时,遇到了分段错误问题。该错误具体发生在RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompileDocker构建过程中的步骤。
一些关键点:
这个问题发生在我配备 Apple Silicon (M3) 的 MacBook 上;我无法再使用 Intel Apple 机器了。
仅构建图像amd64工作正常,表明该问题可能与 ARM 架构有关。
从 Gemfile 和代码库中删除 bootsnap 并没有解决问题。
我看到一些段错误问题表明旧版本的 Docker (4.18) 可以解决该问题,但事实并非如此。
同样,在关闭虚拟化框架的情况下切换到 gRPC FUSE 并不能解决问题。
然而,切换到 Ruby 3.2.2 解决了这个问题。
Rails 应用程序非常简单,使用rails new ohanami -a propshaft -c tailwind. 您可以在此处查看失败的应用程序:https://github.com/miharekar/ohanami/tree/d2170a657a8e6e3d591436b9371e7b1f444220d5
我猜测问题出在 Ruby 3.3.0 或并发 ruby 或 propshaft 中。不知道如何进一步调查,或者向哪里举报。
你建议我做什么?
这是回溯:
#16 [build 5/5] RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails …Run Code Online (Sandbox Code Playgroud) 如何处理并发ruby线程池中的异常(http://ruby-concurrency.github.io/concurrent-ruby/file.thread_pools.html)?
例:
pool = Concurrent::FixedThreadPool.new(5)
pool.post do
raise 'something goes wrong'
end
# how to rescue this exception here
Run Code Online (Sandbox Code Playgroud)
更新:
这是我的代码的简化版本:
def process
pool = Concurrent::FixedThreadPool.new(5)
products.each do |product|
new_product = generate_new_product
pool.post do
store_in_db(new_product) # here exception is raised, e.g. connection to db failed
end
end
pool.shutdown
pool.wait_for_terminaton
end
Run Code Online (Sandbox Code Playgroud)
所以我想要实现的是在任何异常的情况下停止处理(中断循环).
此异常也在更高级别的应用程序中获救,并且执行了一些清理作业(例如将模型状态设置为失败并发送一些通知).
我有一个进程,它使用concurrent-ruby gem来同时处理大量的API调用Concurrent::Future.execute,并且在一段时间后它会死掉:
ERROR -- : can't create Thread (11) (ThreadError)
/current/vendor/bundler_gems/ruby/2.0.0/bundler/gems/concurrent-ruby-cba3702c4e1e/lib/concurrent/executor/ruby_thread_pool_executor.rb:280:in `initialize'
Run Code Online (Sandbox Code Playgroud)
有没有一种简单的方法可以告诉Concurrent它限制它产生的线程数,因为我无法预先知道它需要进行多少次API调用?
或者这是我需要在我的应用程序中明确编码的东西?
我正在使用Ruby 2.0.0(唉目前没有选择改变它)