Class: Dalli::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/dalli/client.rb

Instance Method Summary collapse

Constructor Details

#initialize(servers = nil, options = {}) ⇒ Client

Dalli::Client is the main class which developers will use to interact with the memcached server. Usage:

Dalli::Client.new(['localhost:11211:10', 'cache-2.example.com:11211:5', '192.168.0.1:22122:5'], 
                :threadsafe => true, :failover => true, :expires_in => 300)

servers is an Array of “host:port:weight” where weight allows you to distribute cache unevenly. Both weight and port are optional. If you pass in nil, Dalli will default to ‘localhost:11211’. Note that the MEMCACHE_SERVERS environment variable will override the servers parameter for use in managed environments like Heroku.

Options:

  • :failover - if a server is down, look for and store values on another server in the ring. Default: true.

  • :threadsafe - ensure that only one thread is actively using a socket at a time. Default: true.

  • :expires_in - default TTL in seconds if you do not pass TTL as a parameter to an individual operation, defaults to 0 or forever

  • :compression - defaults to false, if true Dalli will compress values larger than 100 bytes before

    sending them to memcached.
    


24
25
26
27
# File 'lib/dalli/client.rb', line 24

def initialize(servers=nil, options={})
  @servers = env_servers || servers || 'localhost:11211'
  @options = { :expires_in => 0 }.merge(options)
end

Instance Method Details

#add(key, value, ttl = nil, options = nil) ⇒ Object

Conditionally add a key/value pair, if the key does not already exist on the server. Returns true if the operation succeeded.



105
106
107
108
# File 'lib/dalli/client.rb', line 105

def add(key, value, ttl=nil, options=nil)
  ttl ||= @options[:expires_in]
  perform(:add, key, value, ttl, 0, options)
end

#append(key, value) ⇒ Object



122
123
124
# File 'lib/dalli/client.rb', line 122

def append(key, value)
  perform(:append, key, value.to_s)
end

#cas(key, ttl = nil, options = nil, &block) ⇒ Object

compare and swap values using optimistic locking. Fetch the existing value for key. If it exists, yield the value to the block. Add the block’s return value as the new value for the key. Add will fail if someone else changed the value.

Returns:

  • nil if the key did not exist.

  • false if the value was changed by someone else.

  • true if the value was successfully updated.



87
88
89
90
91
92
93
94
95
# File 'lib/dalli/client.rb', line 87

def cas(key, ttl=nil, options=nil, &block)
  ttl ||= @options[:expires_in]
  (value, cas) = perform(:cas, key)
  value = (!value || value == 'Not found') ? nil : value
  if value
    newvalue = block.call(value)
    perform(:add, key, newvalue, ttl, cas, options)
  end
end

#closeObject Also known as: reset

Close our connection to each server. If you perform another operation after this, the connections will be re-established.



182
183
184
185
186
187
# File 'lib/dalli/client.rb', line 182

def close
  if @ring
    @ring.servers.map { |s| s.close }
    @ring = nil
  end
end

#decr(key, amt = 1, ttl = nil, default = nil) ⇒ Object

Decr subtracts the given amount from the counter on the memcached server. Amt must be a positive value.

memcached counters are unsigned and cannot hold negative values. Calling decr on a counter which is 0 will just return 0.

If default is nil, the counter must already exist or the operation will fail and will return nil. Otherwise this method will return the new value for the counter.

Raises:

  • (ArgumentError)


166
167
168
169
170
# File 'lib/dalli/client.rb', line 166

def decr(key, amt=1, ttl=nil, default=nil)
  raise ArgumentError, "Positive values only: #{amt}" if amt < 0
  ttl ||= @options[:expires_in]
  perform(:decr, key, amt, ttl, default)
end

#delete(key) ⇒ Object



118
119
120
# File 'lib/dalli/client.rb', line 118

def delete(key)
  perform(:delete, key)
end

#fetch(key, ttl = nil, options = nil) ⇒ Object



66
67
68
69
70
71
72
73
74
# File 'lib/dalli/client.rb', line 66

def fetch(key, ttl=nil, options=nil)
  ttl ||= @options[:expires_in]
  val = get(key, options)
  if val.nil? && block_given?
    val = yield
    add(key, val, ttl, options)
  end
  val
end

#flush(delay = 0) ⇒ Object



130
131
132
133
# File 'lib/dalli/client.rb', line 130

def flush(delay=0)
  time = -delay
  ring.servers.map { |s| s.request(:flush, time += delay) }
end

#flush_all(delay = 0) ⇒ Object

deprecated, please use #flush.



136
137
138
# File 'lib/dalli/client.rb', line 136

def flush_all(delay=0)
  flush(delay)
end

#get(key, options = nil) ⇒ Object



45
46
47
48
# File 'lib/dalli/client.rb', line 45

def get(key, options=nil)
  resp = perform(:get, key)
  (!resp || resp == 'Not found') ? nil : resp
end

#get_multi(*keys) ⇒ Object

Fetch multiple keys efficiently. Returns a hash of { ‘key’ => ‘value’, ‘key2’ => ‘value1’ }



53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/dalli/client.rb', line 53

def get_multi(*keys)
  return {} if keys.empty?
  options = nil
  options = keys.pop if keys.last.is_a?(Hash) || keys.last.nil?
  ring.lock do
    keys.flatten.each do |key|
      perform(:getkq, key)
    end
    values = ring.servers.inject({}) { |hash, s| hash.merge!(s.request(:noop)); hash }
    values.inject(values) { |memo, (k,v)| memo[k] = v; memo }
  end
end

#incr(key, amt = 1, ttl = nil, default = nil) ⇒ Object

Incr adds the given amount to the counter on the memcached server. Amt must be a positive value.

memcached counters are unsigned and cannot hold negative values. Calling decr on a counter which is 0 will just return 0.

If default is nil, the counter must already exist or the operation will fail and will return nil. Otherwise this method will return the new value for the counter.

Raises:

  • (ArgumentError)


150
151
152
153
154
# File 'lib/dalli/client.rb', line 150

def incr(key, amt=1, ttl=nil, default=nil)
  raise ArgumentError, "Positive values only: #{amt}" if amt < 0
  ttl ||= @options[:expires_in]
  perform(:incr, key, amt, ttl, default)
end

#multiObject

Turn on quiet aka noreply support. All relevant operations within this block with be effectively pipelined as Dalli will use ‘quiet’ operations where possible. Currently supports the set, add, replace and delete operations.



38
39
40
41
42
43
# File 'lib/dalli/client.rb', line 38

def multi
  old, Thread.current[:dalli_multi] = Thread.current[:dalli_multi], true
  yield
ensure
  Thread.current[:dalli_multi] = old
end

#prepend(key, value) ⇒ Object



126
127
128
# File 'lib/dalli/client.rb', line 126

def prepend(key, value)
  perform(:prepend, key, value.to_s)
end

#replace(key, value, ttl = nil, options = nil) ⇒ Object

Conditionally add a key/value pair, only if the key already exists on the server. Returns true if the operation succeeded.



113
114
115
116
# File 'lib/dalli/client.rb', line 113

def replace(key, value, ttl=nil, options=nil)
  ttl ||= @options[:expires_in]
  perform(:replace, key, value, ttl, options)
end

#set(key, value, ttl = nil, options = nil) ⇒ Object



97
98
99
100
# File 'lib/dalli/client.rb', line 97

def set(key, value, ttl=nil, options=nil)
  ttl ||= @options[:expires_in]
  perform(:set, key, value, ttl, options)
end

#statsObject

Collect the stats for each server. Returns a hash like { ‘hostname:port’ => { ‘stat1’ => ‘value1’, … }, ‘hostname2:port’ => { … } }



175
176
177
# File 'lib/dalli/client.rb', line 175

def stats
  ring.servers.inject({}) { |memo, s| memo["#{s.hostname}:#{s.port}"] = s.request(:stats); memo }
end