Class: ArCache::Table

Inherits:
Object
  • Object
show all
Includes:
Marshal
Defined in:
lib/ar_cache/table.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Marshal

#delete, #read, #write

Constructor Details

#initialize(table_name) ⇒ Table

Returns a new instance of Table.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/ar_cache/table.rb', line 27

def initialize(table_name)
  @name = table_name
  @primary_key = ::ActiveRecord::Base.connection.primary_key(@name)

  options = ArCache::Configuration.get_table_options(@name)
  @disabled = @primary_key.nil? ? true : options[:disabled] # ArCache can't work if primary key does not exist.
  @select_disabled = options[:select_disabled]

  columns = ::ActiveRecord::Base.connection.columns(@name)
  @unique_indexes = normalize_unique_indexes(options[:unique_indexes], columns).freeze
  @column_indexes = @unique_indexes.flatten.uniq.freeze
  @column_names = columns.map(&:name).freeze

  @identity_cache_key = "ar:cache:#{@name}"
  @short_sha1 = Digest::SHA1.hexdigest("#{@disabled}:#{columns.to_json}").first(7)

  # For avoid to skip Arcache read cache, must delete cache when disable Arcache.
  # For keep table's schema is consistent, must delete cache after modified the table.
  ArCache.delete(@identity_cache_key) if disabled? || !cache_key_prefix.start_with?("#{@identity_cache_key}:#{@short_sha1}") # rubocop:disable Layout/LineLength
end

Instance Attribute Details

#allObject (readonly)

Returns the value of attribute all.



7
8
9
# File 'lib/ar_cache/table.rb', line 7

def all
  @all
end

#column_indexesObject (readonly)

Returns the value of attribute column_indexes.



25
26
27
# File 'lib/ar_cache/table.rb', line 25

def column_indexes
  @column_indexes
end

#column_namesObject (readonly)

Returns the value of attribute column_names.



25
26
27
# File 'lib/ar_cache/table.rb', line 25

def column_names
  @column_names
end

#identity_cache_keyObject (readonly)

Returns the value of attribute identity_cache_key.



25
26
27
# File 'lib/ar_cache/table.rb', line 25

def identity_cache_key
  @identity_cache_key
end

#nameObject (readonly)

Returns the value of attribute name.



25
26
27
# File 'lib/ar_cache/table.rb', line 25

def name
  @name
end

#primary_keyObject (readonly)

Returns the value of attribute primary_key.



25
26
27
# File 'lib/ar_cache/table.rb', line 25

def primary_key
  @primary_key
end

#short_sha1Object (readonly)

Returns the value of attribute short_sha1.



25
26
27
# File 'lib/ar_cache/table.rb', line 25

def short_sha1
  @short_sha1
end

#unique_indexesObject (readonly)

Returns the value of attribute unique_indexes.



25
26
27
# File 'lib/ar_cache/table.rb', line 25

def unique_indexes
  @unique_indexes
end

Class Method Details

.new(table_name) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/ar_cache/table.rb', line 12

def self.new(table_name)
  @lock.synchronize do
    table = @all.find { |t| t.name == table_name }

    unless table
      table = super
      @all << table
    end

    table
  end
end

Instance Method Details

#cache_key(where_values_hash, index, multi_values_key = nil, key_value = nil) ⇒ Object



75
76
77
78
79
80
81
82
# File 'lib/ar_cache/table.rb', line 75

def cache_key(where_values_hash, index, multi_values_key = nil, key_value = nil)
  where_value = index.map do |column|
    value = column == multi_values_key ? key_value : where_values_hash[column]
    "#{column}=#{value}"
  end.sort.join('&')

  "#{cache_key_prefix}:#{where_value}"
end

#cache_key_prefixObject



56
57
58
59
60
# File 'lib/ar_cache/table.rb', line 56

def cache_key_prefix
  return '' if disabled?

  ArCache.read(identity_cache_key, raw: true) || update_cache
end

#disabled?Boolean

Returns:

  • (Boolean)


48
49
50
# File 'lib/ar_cache/table.rb', line 48

def disabled?
  @disabled
end

#primary_cache_key(id) ⇒ Object



71
72
73
# File 'lib/ar_cache/table.rb', line 71

def primary_cache_key(id)
  "#{cache_key_prefix}:#{primary_key}=#{id}"
end

#select_disabled?Boolean

Returns:

  • (Boolean)


52
53
54
# File 'lib/ar_cache/table.rb', line 52

def select_disabled?
  @select_disabled
end

#update_cacheObject

In order to avoid cache avalanche, we must set cache_key_prefix never expired.



63
64
65
66
67
68
69
# File 'lib/ar_cache/table.rb', line 63

def update_cache
  return '' if disabled?

  key = "#{identity_cache_key}:#{short_sha1}:#{Time.now.to_f}"
  ArCache.write(identity_cache_key, key, raw: true, expires_in: 20.years)
  key
end