Skip to content
Closed
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
a5ab633
Almost complete rewrite of cache filter
ravenblackx Jan 13, 2025
2c982ee
Spelling
ravenblackx Jan 13, 2025
a766637
Namespace
ravenblackx Jan 13, 2025
f83b3b5
Post headers to asyncclient rather than send, because can be off-thread
ravenblackx Jan 14, 2025
6c1ffcd
AsyncStreams are not done until either onComplete or onReset
ravenblackx Jan 14, 2025
1d04c63
Make cache function as upstream http filter
ravenblackx Jan 14, 2025
5bf9cbb
Revert "Make cache function as upstream http filter"
ravenblackx Jan 14, 2025
f284875
Small fixes, test fixes
ravenblackx Jan 17, 2025
2d0a94d
Beginnings of toggling back to cacheable after being marked uncacheable
ravenblackx Jan 21, 2025
9c833a4
cancelWrap sendHeaders
ravenblackx Jan 21, 2025
5668868
Make UpstreamRequest bound to single thread after create
ravenblackx Jan 22, 2025
9ae974c
Consistently use first subscriber for request
ravenblackx Jan 22, 2025
4c7554a
Change behavior of HEAD-with-validation to just pass through
ravenblackx Jan 22, 2025
178eed5
Extra cache behavior expectation
ravenblackx Jan 23, 2025
3bc6c8b
Fix an asan error during teardown, maybe
ravenblackx Jan 23, 2025
41dd93b
Fix overly sticky uncacheable state
ravenblackx Jan 23, 2025
cb02408
Remove uninitialized dispatcher
ravenblackx Jan 23, 2025
0616fae
Make gcc happy, shard to prevent asan timeout
ravenblackx Jan 24, 2025
45a5301
More debug logs on cache insert failure
ravenblackx Jan 24, 2025
38b1699
Re-add accidentally removed line
ravenblackx Jan 24, 2025
5dea2d3
redundant std::move
ravenblackx Jan 28, 2025
b6343a7
Improve validation behavior
ravenblackx Jan 28, 2025
3d8ad86
Remove unused function
ravenblackx Jan 28, 2025
6762da0
Add test for cacheabilityreset
ravenblackx Jan 28, 2025
64e8fd9
Make cache filter useable as upstream
ravenblackx Jan 30, 2025
569a4b6
Merge branch 'main' into cache_stream
ravenblackx Jan 30, 2025
8ab502e
Make integration test mount the filter as an upstream filter
ravenblackx Jan 31, 2025
ec44bfd
Revert "Make integration test mount the filter as an upstream filter"
ravenblackx Feb 3, 2025
fd1dc74
Revert "Make cache filter useable as upstream"
ravenblackx Feb 3, 2025
53674bb
Optimize the common case of only one reader
ravenblackx Feb 3, 2025
d642a99
Finer-grained stats
ravenblackx Feb 4, 2025
afc46a9
Add more stats, fix invalidation
ravenblackx Feb 14, 2025
9f58973
Format
ravenblackx Feb 14, 2025
d35b96b
Revert accidental free-field update
ravenblackx Feb 14, 2025
8965ad9
Add override_upstream_cluster to support using an internal listener
ravenblackx Feb 18, 2025
b1cd455
Fix eviction
ravenblackx Mar 4, 2025
aa85b4d
Merge branch 'main' into cache_stream
ravenblackx Mar 18, 2025
7ed6add
Streamed -> Follower
ravenblackx Mar 18, 2025
ebdbd94
Describe ActiveCache
ravenblackx Mar 18, 2025
9af8e6c
Separate counter for failed validation
ravenblackx Mar 18, 2025
fa9e8b7
Merge branch 'main' into cache_stream
ravenblackx Apr 10, 2025
f744159
Cache key cluster name should be the original cluster name not the ov…
ravenblackx Apr 10, 2025
8f04e09
Merge branch 'main' into cache_stream
ravenblackx Apr 10, 2025
59c5484
Work with internal listener that resolves cluster after the cache
ravenblackx Apr 15, 2025
63d05ce
Big renames, more comments
ravenblackx May 8, 2025
55825f8
Format
ravenblackx May 9, 2025
aa3f2ea
Remove unused HttpSourceFactory
ravenblackx May 12, 2025
0e3200d
CacheFilterConfig descriptive comment
ravenblackx May 12, 2025
f8896f4
Oops, re-add HttpSourcePtr
ravenblackx May 12, 2025
7f7b6fb
Clarify range request edge case
ravenblackx May 14, 2025
dbd8011
Treat responses with Vary header as uncacheable for now
ravenblackx Jun 5, 2025
19da023
Reduce readability to improve coverage
ravenblackx Jun 5, 2025
88ccd12
Improve coverage of upstream_request
ravenblackx Jun 5, 2025
530db1b
Improve range_utils coverage
ravenblackx Jun 5, 2025
a79461d
More coverage of pass-through upstream wrappers
ravenblackx Jun 5, 2025
8374cef
Log noise, to be reverted, trying to diagnose CI
ravenblackx Jun 6, 2025
c27c6f1
Remove unused requestCacheControl() accessor
ravenblackx Jun 6, 2025
b0bf569
Improve cache_sessions coverage
ravenblackx Jun 6, 2025
e4b6673
Revert "Log noise, to be reverted, trying to diagnose CI"
ravenblackx Jun 6, 2025
77f9a13
Noisy logs part 2, to be reverted
ravenblackx Jun 6, 2025
7a95d1b
Even more noisy logs, to be reverted
ravenblackx Jun 6, 2025
ef866ad
Even noisier, and with fixed integration test framework
ravenblackx Jun 9, 2025
bf78b76
Moar debug
ravenblackx Jun 9, 2025
e570629
More dispatcher exits
ravenblackx Jun 10, 2025
2c54ecf
Merge branch 'main' into cache_stream
ravenblackx Jun 11, 2025
09c9a34
Fix late-trailers on unknown-size responses
ravenblackx Jun 13, 2025
d85e551
Remove debug prints
ravenblackx Jun 13, 2025
2f90e9c
Merge branch 'main' into cache_stream
ravenblackx Jul 21, 2025
078adc2
Test coverage for cache implementations
ravenblackx Jul 21, 2025
31ca2ab
Assert instead of check, and fail harder on a bug
ravenblackx Jul 21, 2025
e99fa82
Coverage for cache_filter.cc's rangeFromHeaders
ravenblackx Jul 22, 2025
9926e4b
Revert accidental change to dns_cache_manager_impl
ravenblackx Jul 22, 2025
0cf22a6
Revert whitespace-only change to fake_upstream.cc
ravenblackx Jul 22, 2025
7172515
Test coverage for unlikely bad upstream response case
ravenblackx Jul 22, 2025
0b184d9
Update docs
ravenblackx Jul 22, 2025
5f1938f
Indent @type under typed_config
ravenblackx Jul 23, 2025
5c5b9d2
Merge remote-tracking branch 'upstream/main' into cache_stream
ravenblackx Jul 23, 2025
9ee59c2
changelog
ravenblackx Jul 23, 2025
bca8b92
Improve error logging
ravenblackx Sep 11, 2025
67f6ec6
Make unexpected path non-crashing because it happens
ravenblackx Sep 11, 2025
215a048
Older absl doesn't have message on StatusOr. Also avoid logging faile…
ravenblackx Sep 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion api/envoy/extensions/filters/http/cache/v3/cache.proto
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE;
// [#protodoc-title: HTTP Cache Filter]

// [#extension: envoy.filters.http.cache]
// [#next-free-field: 7]
// [#next-free-field: 8]
message CacheConfig {
option (udpa.annotations.versioning).previous_message_type =
"envoy.config.filter.http.cache.v2alpha.CacheConfig";
Expand Down Expand Up @@ -93,4 +93,16 @@ message CacheConfig {
// causes the cache to validate with its upstream even if the lookup is a hit. Setting this
// to true will ignore these headers.
bool ignore_request_cache_control_header = 6;

// If this is set, requests sent upstream to populate the cache will go to the
// specified cluster rather than the cluster selected by the vhost and route.
//
// If you have actions to be taken by the router filter - either
// ``upstream_http_filters`` or one of the ``RouteConfiguration`` actions such as
// ``response_headers_to_add`` - then the cache's side-channel going directly to the
// routed cluster will bypass these actions. You can set ``override_upstream_cluster``
// to an internal listener which duplicates the relevant ``RouteConfiguration``, to
// replicate the desired behavior on the side-channel upstream request issued by the
// cache.
string override_upstream_cluster = 7;
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ absl::StatusOr<DnsCacheSharedPtr> DnsCacheManagerImpl::getCache(
auto cache_or_status = DnsCacheImpl::createDnsCacheImpl(context_, config);
RETURN_IF_NOT_OK_REF(cache_or_status.status());
DnsCacheSharedPtr new_cache = std::move(cache_or_status.value());
caches_.emplace(config.name(), ActiveCache{config, new_cache});
caches_.emplace(config.name(), CacheSessions{config, new_cache});
return new_cache;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,18 @@ class DnsCacheManagerImpl : public DnsCacheManager, public Singleton::Instance {
DnsCacheSharedPtr lookUpCacheByName(absl::string_view cache_name) override;

private:
struct ActiveCache {
ActiveCache(const envoy::extensions::common::dynamic_forward_proxy::v3::DnsCacheConfig& config,
DnsCacheSharedPtr cache)
struct CacheSessions {
CacheSessions(
const envoy::extensions::common::dynamic_forward_proxy::v3::DnsCacheConfig& config,
DnsCacheSharedPtr cache)
: config_(config), cache_(cache) {}

const envoy::extensions::common::dynamic_forward_proxy::v3::DnsCacheConfig config_;
DnsCacheSharedPtr cache_;
};

Server::GenericFactoryContextImpl context_;
absl::flat_hash_map<std::string, ActiveCache> caches_;
absl::flat_hash_map<std::string, CacheSessions> caches_;
};

class DnsCacheManagerFactoryImpl : public DnsCacheManagerFactory {
Expand Down
107 changes: 86 additions & 21 deletions source/extensions/filters/http/cache/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,87 @@ licenses(["notice"]) # Apache 2

envoy_extension_package()

envoy_cc_library(
name = "http_source_interface",
hdrs = ["http_source.h"],
deps = [
"//envoy/buffer:buffer_interface",
"//envoy/http:header_map_interface",
"//source/extensions/filters/http/cache:range_utils_lib",
"@com_google_absl//absl/functional:any_invocable",
],
)

envoy_cc_library(
name = "upstream_request_lib",
srcs = ["upstream_request_impl.cc"],
hdrs = [
"upstream_request.h",
"upstream_request_impl.h",
],
deps = [
":http_source_interface",
":range_utils_lib",
":stats",
"//source/common/buffer:watermark_buffer_lib",
"//source/common/common:cancel_wrapper_lib",
"//source/common/common:logger_lib",
"@com_google_absl//absl/types:variant",
],
)

envoy_cc_library(
name = "cache_sessions_lib",
srcs = [
"cache_sessions.cc",
],
hdrs = [
"cache_sessions.h",
],
deps = [
":http_cache_lib",
":stats",
":upstream_request_lib",
"//source/common/http:utility_lib",
],
)

envoy_cc_library(
name = "cache_sessions_impl_lib",
srcs = [
"cache_sessions_impl.cc",
],
hdrs = [
"cache_sessions_impl.h",
],
deps = [
":cache_sessions_lib",
":cacheability_utils_lib",
":upstream_request_lib",
"//source/common/common:cancel_wrapper_lib",
],
)

envoy_cc_library(
name = "cache_filter_lib",
srcs = [
"cache_filter.cc",
"upstream_request.cc",
],
hdrs = [
"cache_filter.h",
"filter_state.h",
"upstream_request.h",
],
deps = [
":cache_custom_headers",
":cache_entry_utils_lib",
":cache_filter_logging_info_lib",
":cache_headers_utils_lib",
":cache_insert_queue_lib",
":cache_sessions_impl_lib",
":cache_sessions_lib",
":cacheability_utils_lib",
":http_cache_lib",
":stats",
":upstream_request_lib",
"//source/common/buffer:buffer_lib",
"//source/common/common:cancel_wrapper_lib",
"//source/common/common:enum_to_int",
"//source/common/common:logger_lib",
"//source/common/common:macros",
Expand Down Expand Up @@ -65,24 +127,13 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "cache_insert_queue_lib",
srcs = ["cache_insert_queue.cc"],
hdrs = ["cache_insert_queue.h"],
deps = [
":http_cache_lib",
"//source/common/buffer:buffer_lib",
],
)

envoy_cc_library(
name = "cache_policy_lib",
hdrs = ["cache_policy.h"],
deps = [
":cache_headers_utils_lib",
":http_cache_lib",
"//source/common/http:header_map_lib",
"//source/common/stream_info:filter_state_lib",
],
)

Expand All @@ -91,6 +142,15 @@ envoy_proto_library(
srcs = ["key.proto"],
)

envoy_cc_library(
name = "cache_progress_receiver_interface",
hdrs = ["cache_progress_receiver.h"],
deps = [
"//envoy/http:header_map_interface",
"//source/extensions/filters/http/cache:range_utils_lib",
],
)

envoy_cc_library(
name = "http_cache_lib",
srcs = ["http_cache.cc"],
Expand All @@ -99,6 +159,8 @@ envoy_cc_library(
":cache_custom_headers",
":cache_entry_utils_lib",
":cache_headers_utils_lib",
":cache_progress_receiver_interface",
":http_source_interface",
":key_cc_proto",
":range_utils_lib",
"//envoy/buffer:buffer_interface",
Expand Down Expand Up @@ -137,6 +199,7 @@ envoy_cc_library(
hdrs = ["cache_headers_utils.h"],
deps = [
":cache_custom_headers",
":key_cc_proto",
"//envoy/common:time_interface",
"//envoy/http:header_map_interface",
"//source/common/common:matchers_lib",
Expand All @@ -159,12 +222,12 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "cache_filter_logging_info_lib",
srcs = ["cache_filter_logging_info.cc"],
hdrs = ["cache_filter_logging_info.h"],
envoy_cc_extension(
name = "stats",
srcs = ["stats.cc"],
hdrs = ["stats.h"],
deps = [
"//source/common/stream_info:filter_state_lib",
":cache_entry_utils_lib",
],
)

Expand All @@ -174,6 +237,8 @@ envoy_cc_extension(
hdrs = ["config.h"],
deps = [
":cache_filter_lib",
":cache_sessions_lib",
":stats",
"//source/extensions/filters/http/common:factory_base_lib",
"@envoy_api//envoy/extensions/filters/http/cache/v3:pkg_cc_proto",
],
Expand Down
22 changes: 16 additions & 6 deletions source/extensions/filters/http/cache/cache_entry_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,26 @@ namespace Cache {

absl::string_view cacheEntryStatusString(CacheEntryStatus s) {
switch (s) {
case CacheEntryStatus::Ok:
return "Ok";
case CacheEntryStatus::Unusable:
return "Unusable";
case CacheEntryStatus::RequiresValidation:
return "RequiresValidation";
case CacheEntryStatus::Hit:
return "Hit";
case CacheEntryStatus::Miss:
return "Miss";
case CacheEntryStatus::Follower:
return "Follower";
case CacheEntryStatus::Uncacheable:
return "Uncacheable";
case CacheEntryStatus::Validated:
return "Validated";
case CacheEntryStatus::ValidatedFree:
return "ValidatedFree";
case CacheEntryStatus::FailedValidation:
return "FailedValidation";
case CacheEntryStatus::FoundNotModified:
return "FoundNotModified";
case CacheEntryStatus::LookupError:
return "LookupError";
case CacheEntryStatus::UpstreamReset:
return "UpstreamReset";
}
IS_ENVOY_BUG(absl::StrCat("Unexpected CacheEntryStatus: ", s));
return "UnexpectedCacheEntryStatus";
Expand Down
30 changes: 22 additions & 8 deletions source/extensions/filters/http/cache/cache_entry_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,37 @@ struct ResponseMetadata {
// calculations at: https://httpwg.org/specs/rfc7234.html#age.calculations
Envoy::SystemTime response_time_;
};
using ResponseMetadataPtr = std::unique_ptr<ResponseMetadata>;

// Whether a given cache entry is good for the current request.
enum class CacheEntryStatus {
// This entry is fresh, and an appropriate response to the request.
Ok,
// No usable entry was found. If this was generated for a cache entry, the
// cache should delete that entry.
Unusable,
// This entry is stale, but appropriate for validating
RequiresValidation,
Hit,
// The request was cacheable and was not already in the cache. This also means
// the cache was populated by this request.
Miss,
// The entry was being inserted when this request was made - it's like a
// hit, but streamed from the same request as the original "Miss", so still
// potentially subject to upstream reset because the cache entry isn't fully
// populated yet.
Follower,
// The request was not cacheable. All matching requests will go to the
// upstream.
Uncacheable,
// This entry required validation, and validated successfully.
Validated,
// This entry required validation while another entry was already validating,
// so it validated successfully without its own lookup.
ValidatedFree,
// This entry required validation, and did not validate.
FailedValidation,
// This entry is fresh, and an appropriate basis for a 304 Not Modified
// response.
FoundNotModified,
// The cache lookup failed, e.g. because the cache was unreachable or an RPC
// timed out. The caller shouldn't use this lookup's context for an insert.
// timed out. Mostly behaves the same as Uncacheable but may retry each time.
LookupError,
// The cache attempted to read from upstream for insert, but upstream reset.
UpstreamReset,
};

absl::string_view cacheEntryStatusString(CacheEntryStatus s);
Expand Down
Loading