Module: Kasket::ReadMixin
- Defined in:
- lib/kasket/read_mixin.rb
Class Method Summary collapse
Instance Method Summary collapse
- #find_by_sql_with_kasket(sql, binds = [], *restargs, **kwargs, &blk) ⇒ Object
- #find_by_sql_with_kasket_on_id_array(keys, &blk) ⇒ Object
Class Method Details
.extended(base) ⇒ Object
4 5 6 7 8 9 |
# File 'lib/kasket/read_mixin.rb', line 4 def self.extended(base) class << base alias_method :find_by_sql_without_kasket, :find_by_sql alias_method :find_by_sql, :find_by_sql_with_kasket end end |
Instance Method Details
#find_by_sql_with_kasket(sql, binds = [], *restargs, **kwargs, &blk) ⇒ Object
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/kasket/read_mixin.rb', line 11 def find_by_sql_with_kasket(sql, binds = [], *restargs, **kwargs, &blk) if use_kasket? query = if sql.respond_to?(:to_kasket_query) if ActiveRecord::VERSION::STRING < '5.2' sql.to_kasket_query(self, binds.map(&:value_for_database)) else sql.to_kasket_query(self) end else kasket_parser.parse(sanitize_sql(sql)) end end if query && has_kasket_index_on?(query[:index]) if query[:key].is_a?(Array) filter_pending_records(find_by_sql_with_kasket_on_id_array(query[:key]), &blk) else if value = Kasket.cache.read(query[:key]) # Identified a specific edge case where memcached server returns 0x00 binary protocol response with no data # when the node is being rebooted which causes the Dalli memcached client to return a TrueClass object instead of nil # see: https://github.com/petergoldstein/dalli/blob/31dabf19d3dd94b348a00a59fe5a7b8fa80ce3ad/lib/dalli/server.rb#L520 # and: https://github.com/petergoldstein/dalli/issues/390 # # The code in this first condition of TrueClass === true will # skip the kasket cache for these specific objects and go directly to SQL for retrieval. result_set = if value.is_a?(TrueClass) find_by_sql_without_kasket(sql, binds, *restargs, **kwargs, &blk) elsif value.is_a?(Array) # The data from the Kasket cache is a list of keys to other Kasket entries. # This usually happens when we're trying to load a collection association, # e.g. a list of comments using their post_id in the query. # Do not report a cache hit yet, and defer it until we've verified that at # least one of the retrieved keys is actually in the cache. filter_pending_records(find_by_sql_with_kasket_on_id_array(value)) else # Direct cache hit for the key. Events.report("cache_hit", self) filter_pending_records(Array.wrap(value).collect { |record| instantiate(record.dup, &blk) }) end payload = { record_count: result_set.length, class_name: to_s } ActiveSupport::Notifications.instrument('instantiation.active_record', payload) { result_set } else store_in_kasket(query[:key], find_by_sql_without_kasket(sql, binds, *restargs, **kwargs, &blk)) end end else find_by_sql_without_kasket(sql, binds, *restargs, **kwargs, &blk) end end |
#find_by_sql_with_kasket_on_id_array(keys, &blk) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/kasket/read_mixin.rb', line 66 def find_by_sql_with_kasket_on_id_array(keys, &blk) key_attributes_map = Kasket.cache.read_multi(*keys) found_keys, missing_keys = keys.partition {|k| key_attributes_map[k] } # Only report a cache hit if at least some keys were found in the cache. Events.report("cache_hit", self) if found_keys.any? found_keys.each {|k| key_attributes_map[k] = instantiate(key_attributes_map[k].dup, &blk) } key_attributes_map.merge!(missing_records_from_db(missing_keys)) key_attributes_map.values.compact end |