docs: def fallback(cache):
      """
      Caches content retrieved by the client, thus allowing the cached
      content to be used later if the live content cannot be retrieved.
  
      """
  
      log_filter = ThrottlingFilter(cache=cache)
      logger.filters = []
      logger.addFilter(log_filter)
  
      def get_cache_response(cache_key):
          content = cache.get(cache_key)
          if content:
              response = CacheResponse()
              response.__setstate__({
                  'status_code': 200,
                  '_content': content,
              })
              return response
  
      def get_cache_control(etag_cache_key):
          etag = cache.get(etag_cache_key)
          if etag:
              return ETagCacheControl(etag)
  
      def closure(func):
          @wraps(func)
          def wrapper(client, url, params={}, *args, **kwargs):
              cache_key = canonicalize_url(url + '?' + urlencode(params))
              etag_cache_key = 'etag-' + cache_key
              try:
                  remote_response = func(
                      client,
                      url=url,
                      params=params,
                      cache_control=get_cache_control(etag_cache_key),
                      *args,
                      **kwargs,
                  )
              except RequestException:
                  # Failed to create the request e.g., the remote server is down,
                  # perhaps a timeout occurred, or even connection closed by
                  # remote, etc.
                  response = get_cache_response(cache_key)
                  if response:
                      logger.error(MESSAGE_CACHE_HIT, extra={'url': url})
                  else:
                      raise
              else:
                  log_context = {
                      'status_code': remote_response.status_code, 'url': url
                  }
                  if remote_response.status_code == 404:
                      logger.error(MESSAGE_NOT_FOUND, extra=log_context)
                      return LiveResponse.from_response(remote_response)
                  elif remote_response.status_code == 304:
                      response = get_cache_response(cache_key)
                  elif not remote_response.ok:
                      # Successfully requested the content, but the response is
                      # not OK (e.g., 500, 403, etc)
                      response = get_cache_response(cache_key)
                      if response:
                          logger.error(MESSAGE_CACHE_HIT, extra=log_context)
                      else:
                          logger.exception(MESSAGE_CACHE_MISS, extra=log_context)
                          response = FailureResponse.from_response(
                              remote_response
                          )
                  else:
                      cache.set_many({
                          cache_key: remote_response.content,
                          etag_cache_key: remote_response.headers.get('ETag'),
                      }, settings.DIRECTORY_CLIENT_CORE_CACHE_EXPIRE_SECONDS)
                      response = LiveResponse.from_response(remote_response)
              return response
          return wrapper
      return closure