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.



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

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"


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

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
86
# 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, Errno::EHOSTUNREACH, Redis::CannotConnectError => e
      raise if raise_errors?
      false
    end
  end
end

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

Returns:

  • (Boolean)


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

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

#expire(key, ttl) ⇒ Object



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

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

#fetch_multi(*names) ⇒ Object



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

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"


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

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


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

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



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

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

#statsObject



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

def stats
  with(&:info)
end

#with(&block) ⇒ Object



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

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