MongoDB Mongoid 升级之后 Mongoid::QueryCache::Middleware 问题

easyhappy · 2014年03月04日 · 8189 次阅读

前言

由于最近在将项目升级到 Rails,顺便将 Mongoid 从也从 3.1.4 升到 3.1.6,至于为什么,可以点击这里 升级 Mongoid 的一些配置 被除掉了, IndentityMap 就是之一, 然后官方给出的替代方式是使用 Query::Cache Middleware.

在配置文件添加 config.middleware.use(Mongoid::QueryCache::Middleware);

问题来了

假如 我执行下面的操作:

def index
  @users = UserMongo.all
end

然后其他的地方

if @users.present?       #----> 标记A
   ...其他操作
   @users.each do |p|    #-----> 标记B
       ....
   end
end

执行的'标记 B'的时候,会抛出异常

QUERY CACHE  database=tianji collection=users selector={}
TypeError: no implicit conversion of String into Integer
from /home/andy/Documents/mongoid/lib/mongoid/factory.rb:40:in `[]'

问题追踪

通过 pry 追踪源码

module Mongoid
  module QueryCache
    module Cacheable
      def with_cache
        return yield unless QueryCache.enabled?
        return yield if system_collection?
        key = cache_key
        if QueryCache.cache_table.has_key?(key)
          instrument(key) { QueryCache.cache_table[key] }
        else
          value = yield
          QueryCache.cache_table[key] = value
        end
      end
  end
end

发现 在执行'标记 A' @users.present?, QueryCache.cache_table[key] 的值已经被设置上了

puts QueryCache.cache_table -->
{["tianji", "users", {}]=>{"_id"=>158}}

然后在 执行'标记 B’的时候 其实 是对 'A'的结果 进行遍历,所以 就会报错。

我的观点:

我认为 这是 QueryCache 的一个 bug,没有很好区分好 QueryCache.cache_table 的 key。

补充一下 key 的选取是这样子的:

def cache_key
    [ operation.database, operation.collection, operation.selector ]
end

SOS

大家在升级 Mongoid 的过程中,有没有遇到同样的问题; 实在不行,我可能会先覆盖部分 Mongoid 源码。

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请 注册新账号