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

feat: Add possibility to configure key prefix (Redis, MemCached) #2084

Merged
merged 6 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
42 changes: 41 additions & 1 deletion docs/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,38 @@ cache_to = "sccache-latest"
cache_from = "sccache-"

[cache.memcached]
url = "..."
url = "127.0.0.1:11211"
# Entry expiration time in seconds. Default is 86400 (24 hours)
expiration = 3600
key_prefix = "/custom/prefix/if/need"

[cache.redis]
url = "redis://user:passwd@1.2.3.4:6379/?db=1"
# Entry expiration time in seconds. Default is 0 (never expire)
expiration = 3600
key_prefix = "/custom/prefix/if/need"

[cache.s3]
bucket = "name"
endpoint = "s3-us-east-1.amazonaws.com"
use_ssl = true
key_prefix = "s3prefix"
server_side_encryption = false

[cache.webdav]
endpoint = "http://192.168.10.42:80/some/webdav.php"
key_prefix = "/custom/webdav/subfolder/if/need"
# Basic HTTP authentication credentials.
username = "alice"
password = "secret12"
# Mutually exclusive with username & password. Bearer token value
token = "token123"

[cache.oss]
bucket = "name"
endpoint = "oss-us-east-1.aliyuncs.com"
key_prefix = "ossprefix"
no_credentials = true
```

sccache looks for its configuration file at the path indicated by env variable `SCCACHE_CONF`.
Expand All @@ -77,6 +98,8 @@ If no such env variable is set, sccache looks at default locations as below:
- macOS: `~/Library/Application Support/Mozilla.sccache/config`
- Windows: `%APPDATA%\Mozilla\sccache\config\config`

The latest `cache.XXX` entries may be found here: https://github.com/mozilla/sccache/blob/ffe3070f77ef3301c8ff718316e4ab017ec83042/src/config.rs#L300.

## env

Whatever is set by a file based configuration, it is overruled by the env
Expand Down Expand Up @@ -147,3 +170,20 @@ The full url appears then as `redis://user:passwd@1.2.3.4:6379/?db=1`.
* `SCCACHE_GHA_RUNTIME_TOKEN` / `ACTIONS_RUNTIME_TOKEN` GitHub Actions access token
* `SCCACHE_GHA_CACHE_TO` cache key to write
* `SCCACHE_GHA_CACHE_FROM` comma separated list of cache keys to read from

#### webdav

* `SCCACHE_WEBDAV_ENDPOINT`
* `SCCACHE_WEBDAV_KEY_PREFIX`
* `SCCACHE_WEBDAV_USERNAME`
* `SCCACHE_WEBDAV_PASSWORD`
* `SCCACHE_WEBDAV_TOKEN`

#### OSS

* `SCCACHE_OSS_BUCKET`
* `SCCACHE_OSS_ENDPOINT`
* `SCCACHE_OSS_KEY_PREFIX`
* `ALIBABA_CLOUD_ACCESS_KEY_ID`
* `ALIBABA_CLOUD_ACCESS_KEY_SECRET`
* `SCCACHE_OSS_NO_CREDENTIALS`
11 changes: 8 additions & 3 deletions src/cache/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -602,17 +602,22 @@ pub fn storage_from_config(
CacheType::Memcached(config::MemcachedCacheConfig {
ref url,
ref expiration,
ref key_prefix,
}) => {
debug!("Init memcached cache with url {url}");

let storage = MemcachedCache::build(url, *expiration)
let storage = MemcachedCache::build(url, key_prefix, *expiration)
.map_err(|err| anyhow!("create memcached cache failed: {err:?}"))?;
return Ok(Arc::new(storage));
}
#[cfg(feature = "redis")]
CacheType::Redis(config::RedisCacheConfig { ref url, ref ttl }) => {
CacheType::Redis(config::RedisCacheConfig {
ref url,
ref ttl,
ref key_prefix,
}) => {
debug!("Init redis cache with url {url}");
let storage = RedisCache::build(url, *ttl)
let storage = RedisCache::build(url, key_prefix, *ttl)
.map_err(|err| anyhow!("create redis cache failed: {err:?}"))?;
return Ok(Arc::new(storage));
}
Expand Down
5 changes: 3 additions & 2 deletions src/cache/memcached.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ use crate::errors::*;
pub struct MemcachedCache;

impl MemcachedCache {
pub fn build(url: &str, expiration: u32) -> Result<Operator> {
pub fn build(url: &str, key_prefix: &str, expiration: u32) -> Result<Operator> {
let mut builder = Memcached::default();
builder.endpoint(url);
builder.default_ttl(Duration::from_secs(expiration as u64));
builder.root(key_prefix);
builder.default_ttl(Duration::from_secs(expiration.into()));

let op = Operator::new(builder)?
.layer(LoggingLayer::default())
Expand Down
3 changes: 2 additions & 1 deletion src/cache/redis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ pub struct RedisCache;

impl RedisCache {
/// Create a new `RedisCache`.
pub fn build(url: &str, ttl: u64) -> Result<Operator> {
pub fn build(url: &str, key_prefix: &str, ttl: u64) -> Result<Operator> {
let parsed = Url::parse(url)?;

let mut builder = Redis::default();
builder.endpoint(parsed.as_str());
builder.username(parsed.username());
builder.password(parsed.password().unwrap_or_default());
builder.root(key_prefix);
if ttl != 0 {
builder.default_ttl(Duration::from_secs(ttl));
}
Expand Down
52 changes: 41 additions & 11 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,15 +224,24 @@ pub struct GHACacheConfig {
/// Please change this value freely if we have a better choice.
const DEFAULT_MEMCACHED_CACHE_EXPIRATION: u32 = 86400;

fn default_memcached_cache_expiration() -> u32 {
DEFAULT_MEMCACHED_CACHE_EXPIRATION
}

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct MemcachedCacheConfig {
pub url: String,

/// the expiration time in seconds.
///
/// Default to 24 hours (86400)
/// Up to 30 days (2592000)
#[serde(default = "default_memcached_cache_expiration")]
pub expiration: u32,

#[serde(default)]
pub key_prefix: String,
}

/// redis has no default TTL - all caches live forever
Expand All @@ -245,17 +254,22 @@ const DEFAULT_REDIS_CACHE_TTL: u64 = 0;
#[serde(deny_unknown_fields)]
pub struct RedisCacheConfig {
pub url: String,
/// the ttl time in seconds.

/// the ttl (expiration) time in seconds.
///
/// Default to infinity (0)
#[serde(default)]
#[serde(default, alias = "expiration")]
pub ttl: u64,

#[serde(default)]
pub key_prefix: String,
}

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct WebdavCacheConfig {
pub endpoint: String,
#[serde(default)]
pub key_prefix: String,
pub username: Option<String>,
pub password: Option<String>,
Expand All @@ -267,6 +281,7 @@ pub struct WebdavCacheConfig {
pub struct S3CacheConfig {
pub bucket: String,
pub region: Option<String>,
#[serde(default)]
pub key_prefix: String,
pub no_credentials: bool,
pub endpoint: Option<String>,
Expand All @@ -278,6 +293,7 @@ pub struct S3CacheConfig {
#[serde(deny_unknown_fields)]
pub struct OSSCacheConfig {
pub bucket: String,
#[serde(default)]
pub key_prefix: String,
pub endpoint: Option<String>,
pub no_credentials: bool,
Expand Down Expand Up @@ -610,9 +626,11 @@ fn config_from_env() -> Result<EnvConfig> {
.map_err(|err| anyhow!("SCCACHE_REDIS_TTL value is invalid: {err:?}"))?,
Err(_) => DEFAULT_REDIS_CACHE_TTL,
};
let redis = env::var("SCCACHE_REDIS")
.ok()
.map(|url| RedisCacheConfig { url, ttl });
let redis = env::var("SCCACHE_REDIS").ok().map(|url| RedisCacheConfig {
url,
ttl,
key_prefix: String::new(),
});

// ======= memcached =======
let expiration = match env::var("SCCACHE_MEMCACHED_EXPIRATION").ok() {
Expand All @@ -624,7 +642,11 @@ fn config_from_env() -> Result<EnvConfig> {

let memcached = env::var("SCCACHE_MEMCACHED")
.ok()
.map(|url| MemcachedCacheConfig { url, expiration });
.map(|url| MemcachedCacheConfig {
url,
expiration,
key_prefix: String::new(),
});

// ======= GCP/GCS =======
if (env::var("SCCACHE_GCS_CREDENTIALS_URL").is_ok()
Expand Down Expand Up @@ -1180,6 +1202,7 @@ fn config_overrides() {
redis: Some(RedisCacheConfig {
url: "myotherredisurl".to_owned(),
ttl: 24 * 3600,
key_prefix: String::new(),
}),
..Default::default()
},
Expand All @@ -1196,10 +1219,12 @@ fn config_overrides() {
memcached: Some(MemcachedCacheConfig {
url: "memurl".to_owned(),
expiration: 24 * 3600,
key_prefix: String::new(),
}),
redis: Some(RedisCacheConfig {
url: "myredisurl".to_owned(),
ttl: 24 * 3600,
key_prefix: String::new(),
}),
..Default::default()
},
Expand All @@ -1213,6 +1238,7 @@ fn config_overrides() {
cache: Some(CacheType::Redis(RedisCacheConfig {
url: "myotherredisurl".to_owned(),
ttl: 24 * 3600,
key_prefix: String::new(),
}),),
fallback_cache: DiskCacheConfig {
dir: "/env-cache".into(),
Expand Down Expand Up @@ -1373,12 +1399,14 @@ enabled = true
version = "sccache"

[cache.memcached]
url = "..."
expiration = 86400
url = "127.0.0.1:11211"
expiration = 90000
key_prefix = "/custom/prefix/if/need"

[cache.redis]
url = "redis://user:passwd@1.2.3.4:6379/1"
ttl = 86400
expiration = 86400
key_prefix = "/my/redis/cache"

[cache.s3]
bucket = "name"
Expand Down Expand Up @@ -1430,10 +1458,12 @@ no_credentials = true
redis: Some(RedisCacheConfig {
url: "redis://user:passwd@1.2.3.4:6379/1".to_owned(),
ttl: 24 * 3600,
key_prefix: "/my/redis/cache".into(),
}),
memcached: Some(MemcachedCacheConfig {
url: "...".to_owned(),
expiration: 24 * 3600
url: "127.0.0.1:11211".to_owned(),
expiration: 25 * 3600,
key_prefix: "/custom/prefix/if/need".into(),
}),
s3: Some(S3CacheConfig {
bucket: "name".to_owned(),
Expand Down
Loading