Class: ActiveSupport::Cache::RedisStore

Inherits:
Store
  • Object
show all
Defined in:
lib/active_support/cache/redis_store.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*addresses) ⇒ RedisStore

Instantiate the store.

Example:

RedisStore.new
  # => host: localhost,   port: 6379,  db: 0

RedisStore.new "example.com"
  # => host: example.com, port: 6379,  db: 0

RedisStore.new "example.com:23682"
  # => host: example.com, port: 23682, db: 0

RedisStore.new "example.com:23682/1"
  # => host: example.com, port: 23682, db: 1

RedisStore.new "example.com:23682/1/theplaylist"
  # => host: example.com, port: 23682, db: 1, namespace: theplaylist

RedisStore.new "localhost:6379/0", "localhost:6380/0"
  # => instantiate a cluster

RedisStore.new "localhost:6379/0", "localhost:6380/0", pool_size: 5, pool_timeout: 10
  # => use a ConnectionPool

RedisStore.new "localhost:6379/0", "localhost:6380/0",
  pool: ::ConnectionPool.new(size: 1, timeout: 1) { ::Redis::Store::Factory.create("localhost:6379/0") })
  # => supply an existing connection pool (e.g. for use with redis-sentinel or redis-failover)


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/active_support/cache/redis_store.rb', line 36

def initialize(*addresses)
  @options = addresses.dup.extract_options!

  @data = if @options[:pool]
            raise "pool must be an instance of ConnectionPool" unless @options[:pool].is_a?(ConnectionPool)
            @pooled = true
            @options[:pool]
          elsif [:pool_size, :pool_timeout].any? { |key| @options.has_key?(key) }
            pool_options           = {}
            pool_options[:size]    = options[:pool_size] if options[:pool_size]
            pool_options[:timeout] = options[:pool_timeout] if options[:pool_timeout]
            @pooled = true
            ::ConnectionPool.new(pool_options) { ::Redis::Store::Factory.create(*addresses) }
          else
            ::Redis::Store::Factory.create(*addresses)
          end

  super(@options)
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



7
8
9
# File 'lib/active_support/cache/redis_store.rb', line 7

def data
  @data
end

Instance Method Details

#clearObject

Clear all the data from the store.



190
191
192
193
194
# File 'lib/active_support/cache/redis_store.rb', line 190

def clear
  instrument(:clear, nil, nil) do
    with(&:flushdb)
  end
end

#decrement(key, amount = 1) ⇒ Object

Decrement a key in the store

If the key doesn’t exist it will be initialized on 0. If the key exist but it isn’t a Fixnum it will be initialized on 0.

Example:

We have two objects in cache:
  counter # => 23
  rabbit  # => #<Rabbit:0x5eee6c>

cache.decrement "counter"
cache.read "counter", :raw => true      # => "22"

cache.decrement "counter", 2
cache.read "counter", :raw => true      # => "20"

cache.decrement "a counter"
cache.read "a counter", :raw => true    # => "-1"

cache.decrement "rabbit"
cache.read "rabbit", :raw => true       # => "-1"


178
179
180
181
182
183
# File 'lib/active_support/cache/redis_store.rb', line 178

def decrement(key, amount = 1)
  instrument(:decrement, key, :amount => amount) do
    with{|c| c.decrby key, amount}

  end
end

#delete_matched(matcher, options = nil) ⇒ Object

Delete objects for matched keys.

Performance note: this operation can be dangerous for large production databases, as it uses the Redis “KEYS” command, which is O(N) over the total number of keys in the database. Users of large Redis caches should avoid this method.

Example:

cache.delete_matched "rab*"


73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/active_support/cache/redis_store.rb', line 73

def delete_matched(matcher, options = nil)
  options = merged_options(options)
  instrument(:delete_matched, matcher.inspect) do
    matcher = key_matcher(matcher, options)
    begin
      with do |store|
        !(keys = store.keys(matcher)).empty? && store.del(*keys)
      end
    rescue Errno::ECONNREFUSED, Redis::CannotConnectError
      false
    end
  end
end

#exist?(name, options = nil) ⇒ Boolean

Returns:

  • (Boolean)


198
199
200
201
# File 'lib/active_support/cache/redis_store.rb', line 198

def exist?(name, options = nil)
  res = super(name, options)
  res || false
end

#expire(key, ttl) ⇒ Object



185
186
187
# File 'lib/active_support/cache/redis_store.rb', line 185

def expire(key, ttl)
  with { |c| c.expire key, ttl }
end

#fetch_multi(*names) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/active_support/cache/redis_store.rb', line 107

def fetch_multi(*names)
  results = read_multi(*names)
  options = names.extract_options!
  fetched = {}

  with do |c|
    c.multi do
      fetched = names.inject({}) do |memo, (name, _)|
        key = namespaced_key(name, options)
        memo[key] = results.fetch(key) do
          value = yield name
          write(name, value, options)
          value
        end

        memo
      end
    end
  end

  fetched
end

#increment(key, amount = 1) ⇒ Object

Increment a key in the store.

If the key doesn’t exist it will be initialized on 0. If the key exist but it isn’t a Fixnum it will be initialized on 0.

Example:

We have two objects in cache:
  counter # => 23
  rabbit  # => #<Rabbit:0x5eee6c>

cache.increment "counter"
cache.read "counter", :raw => true      # => "24"

cache.increment "counter", 6
cache.read "counter", :raw => true      # => "30"

cache.increment "a counter"
cache.read "a counter", :raw => true    # => "1"

cache.increment "rabbit"
cache.read "rabbit", :raw => true       # => "1"


151
152
153
154
155
# File 'lib/active_support/cache/redis_store.rb', line 151

def increment(key, amount = 1)
  instrument(:increment, key, :amount => amount) do
    with{|c| c.incrby key, amount}
  end
end

#read_multi(*names) ⇒ Object

Reads multiple keys from the cache using a single call to the servers for all keys. Options can be passed in the last argument.

Example:

cache.read_multi "rabbit", "white-rabbit"
cache.read_multi "rabbit", "white-rabbit", :raw => true


93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/active_support/cache/redis_store.rb', line 93

def read_multi(*names)
  options = names.extract_options!
  keys = names.map{|name| namespaced_key(name, options)}
  values = with { |c| c.mget(*keys) }
  values.map! { |v| v.is_a?(ActiveSupport::Cache::Entry) ? v.value : v }

  # Remove the options hash before mapping keys to values
  names.extract_options!

  result = Hash[keys.zip(values)]
  result.reject!{ |k,v| v.nil? }
  result
end

#reconnectObject



215
216
217
# File 'lib/active_support/cache/redis_store.rb', line 215

def reconnect
  @data.reconnect if @data.respond_to?(:reconnect)
end

#statsObject



203
204
205
# File 'lib/active_support/cache/redis_store.rb', line 203

def stats
  with(&:info)
end

#with(&block) ⇒ Object



207
208
209
210
211
212
213
# File 'lib/active_support/cache/redis_store.rb', line 207

def with(&block)
  if @pooled
    @data.with(&block)
  else
    block.call(@data)
  end
end

#write(name, value, options = nil) ⇒ Object



56
57
58
59
60
61
62
# File 'lib/active_support/cache/redis_store.rb', line 56

def write(name, value, options = nil)
  options = merged_options(options)
  instrument(:write, name, options) do |payload|
    entry = options[:raw].present? ? value : Entry.new(value, options)
    write_entry(namespaced_key(name, options), entry, options)
  end
end