Class: SynCache::RemoteCache

Inherits:
Object
  • Object
show all
Defined in:
lib/syncache/remote.rb

Overview

Connects to a remote SynCache instance over DRb at the provided URI and replaces the remote fetch_or_add method with a slightly less bullet-proof version that invokes the supplied block locally (instead of sending it over DRb to the cache and then back to a different local thread via a local DRb service).

If another RemoteCache client is already working on the same key, this client will wait, using randomly increasing intervals. When a configured timeout runs out (counting from the time the other client has put a placeholder in the cache), the client will give up, discard the other client’s placeholder and start working on the key itself.

Mixing access to the same cache entries from direct and RemoteCache clients is not recommended.

Instance Method Summary collapse

Constructor Details

#initialize(uri, timeout = REMOTE_TIMEOUT, first_delay = REMOTE_FIRST_DELAY) ⇒ RemoteCache

Returns a new instance of RemoteCache.



49
50
51
52
53
# File 'lib/syncache/remote.rb', line 49

def initialize(uri, timeout=REMOTE_TIMEOUT, first_delay=REMOTE_FIRST_DELAY)
  @timeout = timeout
  @first_delay = first_delay
  @cache = DRbObject.new_with_uri(uri)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args) ⇒ Object



55
56
57
# File 'lib/syncache/remote.rb', line 55

def method_missing(method, *args)
  @cache.send(method, *args)
end

Instance Method Details

#fetch_or_add(key) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/syncache/remote.rb', line 59

def fetch_or_add(key)
  placeholder = Placeholder.new
  value = @cache.fetch_or_add(key) { placeholder }

  case value
  when placeholder
    # our placeholder
    value = @cache[key] = yield

  when Placeholder
    # someone else's placeholder
    delay = @first_delay
    while value.kind_of?(Placeholder) and Time.now < value.timestamp + @timeout
      sleep(delay)
      delay *= 1 + rand
      value = @cache[key]
    end

    if value.kind_of?(Placeholder) or value.nil?
      # the other client timed out or got flushed;
      # reset the placeholder ttl and do it ourselves
      @cache[key] = Placeholder.new
      value = @cache[key] = yield
    end
  end

  value
end