class IOPromise::Dalli::Client

Public Class Methods

new(servers = nil, options = {}) click to toggle source

General note: There is no need for explicit get_multi or batching, as requests are sent as soon as the IOPromise is created, multiple can be awaiting response at any time, and responses are automatically demuxed.

# File lib/iopromise/dalli/client.rb, line 14
def initialize(servers = nil, options = {})
  @cache_nils = !!options[:cache_nils]
  options[:iopromise_async] = true
  @options = options
  @client = ::Dalli::Client.new(servers, options)
end

Public Instance Methods

add(key, value, ttl = nil, options = nil) click to toggle source

Conditionally sets the key to the value specified. Returns a promise that resolves to a IOPromise::Dalli::Response.

# File lib/iopromise/dalli/client.rb, line 64
def add(key, value, ttl = nil, options = nil)
  @client.perform(:add, key, value, ttl_or_default(ttl), options)
end
append(key, value) click to toggle source

Appends a value to the specified key, resolving the promise when complete. Appending only works for values stored with :raw => true.

# File lib/iopromise/dalli/client.rb, line 82
def append(key, value)
  value.then do |resolved_value|
    @client.perform(:append, key, resolved_value.to_s)
  end
end
decr(key, amt = 1, ttl = nil, default = nil) click to toggle source

Decr subtracts the given amount from the counter on the memcached server. Amt must be a positive integer 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.

Note that the ttl will only apply if the counter does not already exist. To decrease an existing counter and update its TTL, use cas.

# File lib/iopromise/dalli/client.rb, line 126
def decr(key, amt = 1, ttl = nil, default = nil)
  raise ArgumentError, "Positive values only: #{amt}" if amt < 0
  @client.perform(:decr, key, amt.to_i, ttl_or_default(ttl), default)
end
delete(key) click to toggle source

Deletes the specified key, resolving the promise when complete.

# File lib/iopromise/dalli/client.rb, line 76
def delete(key)
  @client.perform(:delete, key, 0)
end
fetch(key, ttl = nil, options = nil, &block) click to toggle source

Convenience function that attempts to fetch the given key, or set the key with a dynamically generated value if it does not exist. Either way, the returned promise will resolve to the cached or computed value.

If the value does not exist then the provided block is run to generate the value (which can also be a promise), after which the value is set if it still doesn't exist.

# File lib/iopromise/dalli/client.rb, line 35
def fetch(key, ttl = nil, options = nil, &block)
  # match the Dalli behaviour exactly
  options = options.nil? ? ::Dalli::Client::CACHE_NILS : options.merge(::Dalli::Client::CACHE_NILS) if @cache_nils
  get(key, options).then do |response|
    not_found = @options[:cache_nils] ?
      !response.exist? :
      response.value.nil?
    if not_found && !block.nil?
      block.call.then do |new_val|
        # delay the final resolution here until after the add succeeds,
        # to guarantee errors are caught. we could potentially allow
        # the add to resolve once it's sent (without confirmation), but
        # we do need to wait on the add promise to ensure it's sent.
        add(key, new_val, ttl, options).then { new_val }
      end
    else
      response.value
    end
  end
end
get(key, options = nil) click to toggle source

Returns a promise that resolves to a IOPromise::Dalli::Response with the value for the given key, or nil if the key is not found.

# File lib/iopromise/dalli/client.rb, line 23
def get(key, options = nil)
  @client.perform(:get, key, options)
end
incr(key, amt = 1, ttl = nil, default = nil) click to toggle source

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

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.

Note that the ttl will only apply if the counter does not already exist. To increase an existing counter and update its TTL, use cas.

# File lib/iopromise/dalli/client.rb, line 107
def incr(key, amt = 1, ttl = nil, default = nil)
  raise ArgumentError, "Positive values only: #{amt}" if amt < 0
  @client.perform(:incr, key, amt.to_i, ttl_or_default(ttl), default)
end
prepend(key, value) click to toggle source

Prepend a value to the specified key, resolving the promise when complete. Prepending only works for values stored with :raw => true.

# File lib/iopromise/dalli/client.rb, line 90
def prepend(key, value)
  value.then do |resolved_value|
    @client.perform(:prepend, key, resolved_value.to_s)
  end
end
replace(key, value, ttl = nil, options = nil) click to toggle source

Conditionally sets the key to the value specified only if the key already exists. Returns a promise that resolves to a IOPromise::Dalli::Response.

# File lib/iopromise/dalli/client.rb, line 71
def replace(key, value, ttl = nil, options = nil)
  @client.perform(:replace, key, value, ttl_or_default(ttl), 0, options)
end
set(key, value, ttl = nil, options = nil) click to toggle source

Unconditionally sets the key to the value specified. Returns a promise that resolves to a IOPromise::Dalli::Response.

# File lib/iopromise/dalli/client.rb, line 58
def set(key, value, ttl = nil, options = nil)
  @client.perform(:set, key, value, ttl_or_default(ttl), 0, options)
end

Private Instance Methods

ttl_or_default(ttl) click to toggle source

TODO: touch, gat, CAS operations

# File lib/iopromise/dalli/client.rb, line 135
def ttl_or_default(ttl)
  (ttl || @options[:expires_in]).to_i
rescue NoMethodError
  raise ArgumentError, "Cannot convert ttl (#{ttl}) to an integer"
end