Skip to content

Commit 0e791da

Browse files
authored
feat: Add retry_missing_after_public config setting (#1623)
This adds a setting retry_missing_after_public to downloaded and derived cache configs. The effect of this setting is to control the time after which negative (missing, failed download, &c.) cache entries from public sources. Whether a file comes from a public source is determined by reading its metadata, which we added in #1617 and started writing in #1618. The default value for this setting is 24h. This means that each Symbolicator only makes one request per day to public symbol sources for each missing debug file, as opposed to one per hour like before.
1 parent ac01729 commit 0e791da

File tree

5 files changed

+248
-64
lines changed

5 files changed

+248
-64
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
### Various fixes & improvements
66

7-
fix: rectify symsorter `--ignore-errors` handling for ZIP archives. ([#1621](https://github.com/getsentry/symbolicator/pull/1621)
7+
fix: rectify symsorter `--ignore-errors` handling for ZIP archives. ([#1621](https://github.com/getsentry/symbolicator/pull/1621))
8+
feat: Added a setting `retry_missing_after_public` to downloaded and derived cache configs.
9+
The effect of this setting is to control the time after which negative (missing, failed download, &c.)
10+
cache entries from public sources. The default value is 24h. ([#1623](https://github.com/getsentry/symbolicator/pull/1623))
811

912
### Dependencies
1013

crates/symbolicator-native/src/caches/symcaches.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ mod tests {
382382
object_type: ObjectType::Macho,
383383
identifier,
384384
sources: Arc::new([source]),
385-
scope: Scope::Global,
385+
scope: Scope::Scoped("12345".into()),
386386
};
387387

388388
let symcache_actor = symcache_actor(cache_dir.path().to_owned(), TIMEOUT).await;

crates/symbolicator-service/src/caching/fs.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use symbolic::common::ByteView;
1010
use tempfile::NamedTempFile;
1111

1212
use crate::config::{CacheConfig, Config};
13+
use crate::types::Scope;
1314

1415
use super::cache_error::cache_contents_from_bytes;
1516
use super::{CacheContents, CacheEntry, CacheError, CacheName, Metadata};
@@ -133,14 +134,18 @@ impl Cache {
133134
let bv = ByteView::open(path)?;
134135
let contents = cache_contents_from_bytes(bv);
135136

137+
// A cache entry is considered "public" if it came from a request with global scope.
138+
let is_public = external_metadata
139+
.as_ref()
140+
.is_some_and(|md| md.scope == Scope::Global);
136141
// States a cache item can be in:
137142
// * negative/empty: An empty file. Represents a failed download. ctime is used to indicate
138143
// when the failed download happened (when the file was created)
139144
// * malformed: A file with the content `b"malformed"`. Represents a failed symcache
140145
// conversion. ctime indicates when we attempted to convert.
141146
// * ok (don't really have a name): File has any other content, mtime is used to keep track
142147
// of last use.
143-
let expiration_time = self.compute_expiration_time(&contents, atime, ctime)?;
148+
let expiration_time = self.compute_expiration_time(&contents, atime, ctime, is_public)?;
144149

145150
Ok((
146151
CacheEntry {
@@ -157,12 +162,17 @@ impl Cache {
157162
/// The returned `ExpirationTime` determines when the cache contents should
158163
/// be touched to keep them alive or recomputed entirely.
159164
///
165+
/// Negative cache entries for "public" files have a different (typically longer)
166+
/// lifetime than "private" (project-specific) ones. This is because public symbol
167+
/// sources are expected to change much more slowly.
168+
///
160169
/// If the file is expired, this returns [`io::ErrorKind::NotFound`].
161170
fn compute_expiration_time<T>(
162171
&self,
163172
contents: &CacheContents<T>,
164173
atime: SystemTime,
165174
ctime: SystemTime,
175+
is_public: bool,
166176
) -> io::Result<ExpirationTime> {
167177
let atime_elapsed = atime.elapsed().unwrap_or_default();
168178
let ctime_elapsed = ctime.elapsed().unwrap_or_default();
@@ -180,10 +190,15 @@ impl Cache {
180190
Ok(ExpirationTime::TouchIn(touch_in))
181191
}
182192
ExpirationStrategy::Negative => {
183-
let retry_misses_after = self
184-
.cache_config
185-
.retry_misses_after()
186-
.unwrap_or(Duration::MAX);
193+
let retry_misses_after = if is_public {
194+
self.cache_config
195+
.retry_misses_after_public()
196+
.unwrap_or(Duration::MAX)
197+
} else {
198+
self.cache_config
199+
.retry_misses_after()
200+
.unwrap_or(Duration::MAX)
201+
};
187202

188203
let expires_in = retry_misses_after.saturating_sub(ctime_elapsed);
189204

0 commit comments

Comments
 (0)