| /* |
| * Copyright 2011 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| // Author: sligocki@google.com (Shawn Ligocki) |
| |
| #ifndef NET_INSTAWEB_HTTP_PUBLIC_CACHE_URL_ASYNC_FETCHER_H_ |
| #define NET_INSTAWEB_HTTP_PUBLIC_CACHE_URL_ASYNC_FETCHER_H_ |
| |
| #include "net/instaweb/http/public/url_async_fetcher.h" |
| #include "pagespeed/kernel/base/basictypes.h" |
| #include "pagespeed/kernel/base/string.h" |
| |
| namespace net_instaweb { |
| |
| class AsyncFetch; |
| class Hasher; |
| class Histogram; |
| class HTTPCache; |
| class MessageHandler; |
| class NamedLockManager; |
| class Variable; |
| |
| // Composes an asynchronous URL fetcher with an http cache, to |
| // generate an asynchronous caching URL fetcher. |
| // |
| // This fetcher will asynchronously check the cache. If the url |
| // is found in cache and is still valid, the fetch's callback will be |
| // called right away. This includes any cached failures or that URL |
| // is uncacheable, unless set_ignore_recent_fetch_failed(true) is called. |
| // Otherwise (if fetcher != NULL) an async fetch will be performed in the |
| // fetcher, the result of which will be written into the cache. In case the |
| // fetch fails and there is a stale response in the cache, we serve the stale |
| // response. |
| // |
| // If fetcher == NULL, this will only perform a cache lookup and then call |
| // the callback immediately. |
| // |
| // In case of cache hit and resource is about to expire (80% of TTL or 5 mins |
| // which ever is minimum), it will trigger background fetch to freshen the value |
| // in cache. Background fetch only be triggered only if async_op_hooks_ != NULL, |
| // otherwise, fetcher object accessed by BackgroundFreshenFetch may be deleted |
| // by the time origin fetch finishes. |
| // |
| // TODO(sligocki): In order to use this for fetching resources for rewriting |
| // we'd need to integrate resource locking in this class. Do we want that? |
| class CacheUrlAsyncFetcher : public UrlAsyncFetcher { |
| public: |
| // Interface for managing async operations in CacheUrlAsyncFetcher. It helps |
| // to protect the lifetime of the injected objects. |
| class AsyncOpHooks { |
| public: |
| AsyncOpHooks() {} |
| virtual ~AsyncOpHooks(); |
| |
| // Called when CacheUrlAsyncFetcher is about to start async operation. |
| virtual void StartAsyncOp() = 0; |
| // Called when async operation is ended. |
| virtual void FinishAsyncOp() = 0; |
| }; |
| |
| // None of these are owned by CacheUrlAsyncFetcher. |
| CacheUrlAsyncFetcher(const Hasher* lock_hasher, |
| NamedLockManager* lock_manager, |
| HTTPCache* cache, |
| const GoogleString& fragment, |
| AsyncOpHooks* async_op_hooks, |
| UrlAsyncFetcher* fetcher); |
| virtual ~CacheUrlAsyncFetcher(); |
| |
| virtual bool SupportsHttps() const { return fetcher_->SupportsHttps(); } |
| |
| virtual void Fetch(const GoogleString& url, |
| MessageHandler* message_handler, |
| AsyncFetch* base_fetch); |
| |
| // HTTP status code used to indicate that we failed the Fetch because |
| // result was not found in cache. (Only happens if fetcher_ == NULL). |
| static const int kNotInCacheStatus; |
| |
| HTTPCache* http_cache() const { return http_cache_; } |
| UrlAsyncFetcher* fetcher() const { return fetcher_; } |
| |
| void set_backend_first_byte_latency_histogram(Histogram* x) { |
| backend_first_byte_latency_ = x; |
| } |
| |
| Histogram* backend_first_byte_latency_histogram() const { |
| return backend_first_byte_latency_; |
| } |
| |
| void set_fallback_responses_served(Variable* x) { |
| fallback_responses_served_ = x; |
| } |
| |
| Variable* fallback_responses_served() const { |
| return fallback_responses_served_; |
| } |
| |
| void set_fallback_responses_served_while_revalidate(Variable* x) { |
| fallback_responses_served_while_revalidate_ = x; |
| } |
| |
| Variable* fallback_responses_served_while_revalidate() const { |
| return fallback_responses_served_while_revalidate_; |
| } |
| |
| void set_num_conditional_refreshes(Variable* x) { |
| num_conditional_refreshes_ = x; |
| } |
| |
| Variable* num_conditional_refreshes() const { |
| return num_conditional_refreshes_; |
| } |
| |
| void set_num_proactively_freshen_user_facing_request(Variable* x) { |
| num_proactively_freshen_user_facing_request_ = x; |
| } |
| |
| Variable* num_proactively_freshen_user_facing_request() const { |
| return num_proactively_freshen_user_facing_request_; |
| } |
| |
| void set_respect_vary(bool x) { respect_vary_ = x; } |
| bool respect_vary() const { return respect_vary_; } |
| |
| void set_ignore_recent_fetch_failed(bool x) { |
| ignore_recent_fetch_failed_ = x; |
| } |
| bool ignore_recent_fetch_failed() const { |
| return ignore_recent_fetch_failed_; |
| } |
| |
| void set_serve_stale_if_fetch_error(bool x) { |
| serve_stale_if_fetch_error_ = x; |
| } |
| |
| bool serve_stale_if_fetch_error() const { |
| return serve_stale_if_fetch_error_; |
| } |
| |
| void set_serve_stale_while_revalidate_threshold_sec(int64 x) { |
| serve_stale_while_revalidate_threshold_sec_ = x; |
| } |
| |
| int64 serve_stale_while_revalidate_threshold_sec() const { |
| return serve_stale_while_revalidate_threshold_sec_; |
| } |
| |
| void set_default_cache_html(bool x) { default_cache_html_ = x; } |
| bool default_cache_html() const { return default_cache_html_; } |
| |
| void set_proactively_freshen_user_facing_request(bool x) { |
| proactively_freshen_user_facing_request_ = x; |
| } |
| bool proactively_freshen_user_facing_request() const { |
| return proactively_freshen_user_facing_request_; |
| } |
| |
| void set_own_fetcher(bool x) { own_fetcher_ = x; } |
| |
| private: |
| // Not owned by CacheUrlAsyncFetcher. |
| const Hasher* lock_hasher_; |
| NamedLockManager* lock_manager_; |
| HTTPCache* http_cache_; |
| GoogleString fragment_; |
| UrlAsyncFetcher* fetcher_; // may be NULL. |
| AsyncOpHooks* async_op_hooks_; |
| |
| Histogram* backend_first_byte_latency_; // may be NULL. |
| Variable* fallback_responses_served_; // may be NULL. |
| Variable* fallback_responses_served_while_revalidate_; // may be NULL. |
| Variable* num_conditional_refreshes_; // may be NULL. |
| Variable* num_proactively_freshen_user_facing_request_; // may be NULL. |
| |
| bool respect_vary_; |
| bool ignore_recent_fetch_failed_; |
| bool serve_stale_if_fetch_error_; |
| bool default_cache_html_; |
| bool proactively_freshen_user_facing_request_; |
| bool own_fetcher_; // set true to transfer ownership of fetcher to this. |
| int64 serve_stale_while_revalidate_threshold_sec_; |
| |
| DISALLOW_COPY_AND_ASSIGN(CacheUrlAsyncFetcher); |
| }; |
| |
| } // namespace net_instaweb |
| |
| #endif // NET_INSTAWEB_HTTP_PUBLIC_CACHE_URL_ASYNC_FETCHER_H_ |