Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

set a default TTL for query plans #4588

Merged
merged 28 commits into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
683fda4
use : as separator
Geal Feb 2, 2024
825ff8f
reduce the key size
Geal Feb 2, 2024
c502475
add the federation version to the query plan cache key
Geal Feb 2, 2024
42c14b9
move cache insertion to a separate task
Geal Feb 2, 2024
4fb5a20
move to non experimental
Geal Feb 2, 2024
2ed4ac8
migration
Geal Feb 2, 2024
d47f266
fix snapshots and docs
Geal Feb 2, 2024
8d8dcac
fix tests
Geal Feb 2, 2024
baa478c
snapshot
Geal Feb 2, 2024
c15217c
fix the changeset
Geal Feb 2, 2024
b8ef982
lint
Geal Feb 2, 2024
c810f49
lint
Geal Feb 2, 2024
4192237
Merge branch 'dev' into geal/query-plan-cache-prod
Geal Feb 2, 2024
c923d07
Update .changesets/feat_geal_query_plan_cache_prod.md
Geal Feb 5, 2024
ca2e15e
Merge branch 'dev' into geal/query-plan-cache-prod
Geal Feb 5, 2024
fa7e641
set a default TTL for query plans
Geal Feb 2, 2024
e88bbbf
Merge branch 'dev' into geal/query-plan-cache-default-ttl
Geal Feb 6, 2024
e2389ac
Merge branch 'dev' into geal/query-plan-cache-default-ttl
Geal Feb 22, 2024
bbf2c9a
missing field
Geal Feb 22, 2024
c490554
Merge branch 'dev' into geal/query-plan-cache-default-ttl
Geal Mar 7, 2024
e79ca75
Merge branch 'dev' into geal/query-plan-cache-default-ttl
Geal Mar 13, 2024
2d77e1a
changeset
Geal Mar 13, 2024
acfb764
Merge branch 'dev' into geal/query-plan-cache-default-ttl
Geal Mar 15, 2024
f1e617a
Merge branch 'dev' into geal/query-plan-cache-default-ttl
Geal Mar 26, 2024
c7a4225
Merge branch 'dev' into geal/query-plan-cache-default-ttl
Geal Apr 2, 2024
008565e
document the new default
Geal Apr 2, 2024
c402837
Merge branch 'dev' into geal/query-plan-cache-default-ttl
Geal Apr 4, 2024
2c76956
Merge branch 'dev' into geal/query-plan-cache-default-ttl
Geal Apr 5, 2024
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
5 changes: 5 additions & 0 deletions .changesets/feat_geal_query_plan_cache_default_ttl.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### set a default TTL for query plans ([Issue #4473](https://github.com/apollographql/router/issues/4473))

This sets a default TTL of 30 days for query plan caches, because the previous default was to store query plans indefinitely, which does not make sense because they change with schema updates.

By [@Geal](https://github.com/Geal) in https://github.com/apollographql/router/pull/4588
83 changes: 82 additions & 1 deletion apollo-router/src/configuration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,7 @@ impl Default for Apq {
#[serde(deny_unknown_fields, default)]
pub(crate) struct QueryPlanning {
/// Cache configuration
pub(crate) cache: Cache,
pub(crate) cache: QueryPlanCache,
/// Warms up the cache on reloads by running the query plan over
/// a list of the most used queries (from the in memory cache)
/// Configures the number of queries warmed up. Defaults to 1/3 of
Expand Down Expand Up @@ -926,6 +926,62 @@ pub(crate) struct QueryPlanning {
pub(crate) experimental_reuse_query_plans: bool,
}

/// Cache configuration
#[derive(Debug, Clone, Default, Deserialize, Serialize, JsonSchema)]
#[serde(deny_unknown_fields, default)]
pub(crate) struct QueryPlanCache {
/// Configures the in memory cache (always active)
pub(crate) in_memory: InMemoryCache,
/// Configures and activates the Redis cache
pub(crate) redis: Option<QueryPlanRedisCache>,
}

#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(deny_unknown_fields)]
/// Redis cache configuration
pub(crate) struct QueryPlanRedisCache {
/// List of URLs to the Redis cluster
pub(crate) urls: Vec<url::Url>,

/// Redis username if not provided in the URLs. This field takes precedence over the username in the URL
pub(crate) username: Option<String>,
/// Redis password if not provided in the URLs. This field takes precedence over the password in the URL
pub(crate) password: Option<String>,

#[serde(deserialize_with = "humantime_serde::deserialize", default)]
#[schemars(with = "Option<String>", default)]
/// Redis request timeout (default: 2ms)
pub(crate) timeout: Option<Duration>,

#[serde(
deserialize_with = "humantime_serde::deserialize",
default = "default_query_plan_cache_ttl"
)]
#[schemars(with = "Option<String>", default = "default_query_plan_cache_ttl")]
/// TTL for entries
pub(crate) ttl: Duration,

/// namespace used to prefix Redis keys
pub(crate) namespace: Option<String>,

#[serde(default)]
/// TLS client configuration
pub(crate) tls: Option<TlsClient>,

#[serde(default = "default_required_to_start")]
/// Prevents the router from starting if it cannot connect to Redis
pub(crate) required_to_start: bool,

#[serde(default = "default_reset_ttl")]
/// When a TTL is set on a key, reset it when reading the data from that key
pub(crate) reset_ttl: bool,
}

fn default_query_plan_cache_ttl() -> Duration {
// Default TTL set to 30 days
Duration::from_secs(86400 * 30)
}

/// Cache configuration
#[derive(Debug, Clone, Default, Deserialize, Serialize, JsonSchema)]
#[serde(deny_unknown_fields, default)]
Expand All @@ -936,6 +992,15 @@ pub(crate) struct Cache {
pub(crate) redis: Option<RedisCache>,
}

impl From<QueryPlanCache> for Cache {
fn from(value: QueryPlanCache) -> Self {
Cache {
in_memory: value.in_memory,
redis: value.redis.map(Into::into),
}
}
}

#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(deny_unknown_fields)]
/// In memory cache configuration
Expand Down Expand Up @@ -994,6 +1059,22 @@ fn default_required_to_start() -> bool {
false
}

impl From<QueryPlanRedisCache> for RedisCache {
fn from(value: QueryPlanRedisCache) -> Self {
RedisCache {
urls: value.urls,
username: value.username,
password: value.password,
timeout: value.timeout,
ttl: Some(value.ttl),
namespace: value.namespace,
tls: value.tls,
required_to_start: value.required_to_start,
reset_ttl: value.reset_ttl,
}
}
}

fn default_reset_ttl() -> bool {
true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2808,7 +2808,10 @@ expression: "&schema"
},
"ttl": {
"description": "TTL for entries",
"default": null,
"default": {
"secs": 2592000,
"nanos": 0
},
"type": "string",
"nullable": true
},
Expand Down
2 changes: 1 addition & 1 deletion apollo-router/src/query_planner/caching_query_planner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ where
) -> Result<CachingQueryPlanner<T>, BoxError> {
let cache = Arc::new(
DeduplicatingCache::from_configuration(
&configuration.supergraph.query_planning.cache,
&configuration.supergraph.query_planning.cache.clone().into(),
"query planner",
)
.await?,
Expand Down
4 changes: 2 additions & 2 deletions docs/source/configuration/distributed-caching.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ supergraph:
username: admin/123 # Optional, can be part of the urls directly, mainly useful if you have special character like '/' in your password that doesn't work in url. This field takes precedence over the username in the URL
password: admin # Optional, can be part of the urls directly, mainly useful if you have special character like '/' in your password that doesn't work in url. This field takes precedence over the password in the URL
timeout: 5ms # Optional, by default: 2ms
ttl: 24h # Optional, by default no expiration
ttl: 24h # Optional
namespace: "prefix" # Optional
#tls:
required_to_start: false # Optional, defaults to false
Expand All @@ -146,7 +146,7 @@ Connecting and sending commands to Redis are subject to a timeout, set by defaul

#### TTL

The `ttl` option defines the default global expiration for Redis entries.
The `ttl` option defines the default global expiration for Redis entries. For APQ caching, the default is no expiration, while for query plan caching, the default expiration is set to 30 days.

### Namespace

Expand Down
Loading