def fetch(key, ttl = nil, req_options = nil)
      req_options = req_options.nil? ? CACHE_NILS : req_options.merge(CACHE_NILS) if cache_nils
      val = get(key, req_options)
      return val unless block_given? && not_found?(val)

      new_val = yield
      add(key, new_val, ttl_or_default(ttl), req_options)
      new_val
    end
Fetch the value associated with the key.
If a value is found, then it is returned.

If a value is not found and no block is given, then nil is returned.

If a value is not found (or if the found value is nil and :cache_nils is false)
and a block is given, the block will be invoked and its return value
written to the cache and returned.