在我的 Ruby on Rails 应用程序中,我有如下所示的模型:
class Schema < ActiveRecord::Base
has_many :schema_items
def self.from_cache(schema_id)
schema = Rails.cache.read("schema_#{schema_id}")
unless schema
schema = Schema.where(id: schema_id).includes(:schema_items).first
Rails.cache.write("schema_#{schema_id}", schema) if schema
end
schema
end
end
我在 Sidekiq worker 调用的其他类中使用此类方法。它有时会返回以下错误:
NotImplementedError
使用谷歌我在 redis_store gem 中发现了这个问题:https://github.com/redis-store/redis-store/issues/74
但是他们修复了这个错误。我的应用程序托管在 Heroku 上,我使用的是 RedisCloud。有什么想法可以解决这个问题吗?
编辑:
这是完整的回溯:
NotImplementedError: NotImplementedError
from celluloid/tasks/task_fiber.rb:15:in `block in create'
from celluloid/tasks.rb:57:in `block in initialize'
from celluloid/actor.rb:357:in `block in task'
from celluloid/cell.rb:71:in `block in task'
from celluloid/cell.rb:60:in `block in invoke'
from celluloid/calls.rb:122:in `dispatch'
from celluloid/calls.rb:26:in `dispatch'
from celluloid/calls.rb:26:in `public_send'
from sidekiq/processor.rb:50:in `process'
from sidekiq/processor.rb:98:in `stats'
from sidekiq/processor.rb:51:in `block in process'
from sidekiq/middleware/chain.rb:132:in `invoke'
from sidekiq/middleware/chain.rb:132:in `call'
from sidekiq/middleware/chain.rb:129:in `block in invoke'
from sidekiq/middleware/server/logging.rb:11:in `call'
from sidekiq/logging.rb:30:in `with_context'
from sidekiq/middleware/server/logging.rb:15:in `block in call'
from sidekiq/middleware/chain.rb:129:in `block in invoke'
from sidekiq/failures/middleware.rb:9:in `call'
from sidekiq/middleware/chain.rb:129:in `block in invoke'
from sidekiq/middleware/server/retry_jobs.rb:74:in `call'
from sidekiq/middleware/chain.rb:129:in `block in invoke'
from sidekiq/middleware/server/active_record.rb:6:in `call'
from sidekiq/middleware/chain.rb:129:in `block in invoke'
from sidekiq/batch/middleware.rb:25:in `call'
from sidekiq/middleware/chain.rb:129:in `block in invoke'
from sidekiq_unique_jobs/middleware/server/unique_jobs.rb:16:in `call'
from sidekiq/middleware/chain.rb:129:in `block in invoke'
from sidetiq/middleware/history.rb:8:in `call'
from sidekiq/middleware/chain.rb:129:in `block in invoke'
from new_relic/agent/instrumentation/sidekiq.rb:29:in `call'
from new_relic/agent/instrumentation/controller_instrumentation.rb:352:in `perform_action_with_newrelic_trace'
from new_relic/agent/instrumentation/sidekiq.rb:33:in `block in call'
from sidekiq/middleware/chain.rb:127:in `block in invoke'
from sidekiq/processor.rb:52:in `block (2 levels) in process'
from sidekiq/processor.rb:75:in `execute_job'
from app/workers/response_processor_worker.rb:8:in `perform'
from app/services/import/response_processor.rb:28:in `process'
from app/models/import/importer/raw_response_validator.rb:17:in `validate'
from app/models/survey_schema.rb:51:in `from_cache'
from active_record/relation/finder_methods.rb:127:in `first'
from active_record/relation/finder_methods.rb:484:in `find_nth'
from active_record/relation/finder_methods.rb:500:in `find_nth_with_limit'
from active_record/relation.rb:243:in `to_a'
from active_record/relation.rb:514:in `load'
from active_record/relation.rb:643:in `exec_queries'
from active_record/relation.rb:643:in `each'
from active_record/relation.rb:644:in `block in exec_queries'
from active_record/associations/preloader.rb:102:in `preload'
from active_record/associations/preloader.rb:102:in `flat_map'
from active_record/associations/preloader.rb:102:in `each'
from active_record/associations/preloader.rb:103:in `block in preload'
from active_record/associations/preloader.rb:115:in `preloaders_on'
from active_record/associations/preloader.rb:143:in `preloaders_for_one'
from active_record/associations/preloader.rb:143:in `flat_map'
from active_record/associations/preloader.rb:143:in `each'
from active_record/associations/preloader.rb:144:in `block in preloaders_for_one'
from active_record/associations/preloader.rb:144:in `map'
from active_record/associations/preloader.rb:144:in `each'
from active_record/associations/preloader.rb:146:in `block (2 levels) in preloaders_for_one'
from active_record/associations/preloader/association.rb:20:in `run'
from active_record/associations/preloader/collection_association.rb:13:in `preload'
from active_record/associations/preloader/association.rb:78:in `associated_records_by_owner'
from active_record/associations/preloader/association.rb:60:in `owners_by_key'
from active_record/associations/preloader/association.rb:103:in `key_conversion_required?'
from active_record/associations/preloader/association.rb:107:in `association_key_type'
from active_record/associations/preloader/association.rb:45:in `association_key_name'
我的 worker 看起来像这样:
class ResponseCreatorWorker
include Sidekiq::Worker
sidekiq_options queue: :response_processing
def perform(schema_id)
# some not important code
schema = Schema.from_cache(schema_id) # this line throws the error
Response.create(schema: schema)
end
end
最佳答案
无法进入 Pro 代码的几个选项:
你发现的错误是redis-store相关的,试试memcached
尝试将缓存移动到 memcached,这应该是一个简单且无中断的操作,在简单计划上是免费的,看看问题是否消失或发生变化,这可能有助于找到核心错误
memcache 对于简单的键值对象来说是一个更好的缓存服务,
您链接的 worker 不是堆栈跟踪的一部分
您显示了 ResponseCreatorWorker
,但它没有出现在堆栈跟踪中。出现的是 ResponseProcessorWorker
,也许改为链接那个工作人员?
你确定你正在运行你正在运行的代码吗?
Mike Perham 说 Sidekiq
回溯与你给他的版本不匹配,堆栈跟踪中有错误的工作人员?您确定服务器正在更新吗?查看部署日志并使用 heroku run bash
登录到 worker 并检查几个关键文件,确保平台没有任何问题。
你能拯救它吗? :D
进行捕获 NotImplementedError
的救援应该是相当安全的,再试一次,并将它的记录记录到日志中。在适当的时候更新 gem ,当警告消失时打开威士忌并庆祝。
在你的模型中加入这样的东西:
def wrap_me_scotty
yield
rescue NotImplementedError => e
warn "#{e} :-("
yield # try once more, let it explode if no joy
end
然后包装Rails.cache
调用
def self.from_cache(schema_id)
schema = wrap_me_scotty{ Rails.cache.read("schema_#{schema_id}") }
unless schema
schema = Schema.where(id: schema_id).includes(:schema_items).first
wrap_me_scotty{ Rails.cache.write("schema_#{schema_id}", schema) } if schema
end
schema
end
关于ruby-on-rails - sidekiq 进程中的 Rails.cache.read,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34434745/