diff --git a/relay-server/src/services/project_redis.rs b/relay-server/src/services/project_redis.rs index 7013e5eee5..edee03a829 100644 --- a/relay-server/src/services/project_redis.rs +++ b/relay-server/src/services/project_redis.rs @@ -91,25 +91,36 @@ impl RedisProjectSource { .query(&mut connection) .map_err(RedisError::Redis)?; - let response = match raw_response_opt { - Some(response) => { - metric!( - counter(RelayCounters::ProjectStateRedis) += 1, - hit = "project_config" - ); - let parsed = parse_redis_response(response.as_slice())?; - ProjectState::from(parsed) - } - None => { - metric!( - counter(RelayCounters::ProjectStateRedis) += 1, - hit = "false" - ); - ProjectState::Pending - } + let Some(response) = raw_response_opt else { + metric!( + counter(RelayCounters::ProjectStateRedis) += 1, + hit = "false" + ); + return Ok(Some(ProjectState::Pending)); }; - Ok(Some(response)) + let response = ProjectState::from(parse_redis_response(response.as_slice())?); + + // If we were passed a revision, check if we just loaded the same revision from Redis. + // + // We always want to keep the old revision alive if possible, since the already loaded + // version has already initialized caches. + // + // While this is theoretically possible this should always been handled using the above revision + // check using the additional Redis key. + if revision.is_some() && response.revision() == revision { + metric!( + counter(RelayCounters::ProjectStateRedis) += 1, + hit = "project_config_revision" + ); + Ok(None) + } else { + metric!( + counter(RelayCounters::ProjectStateRedis) += 1, + hit = "project_config" + ); + Ok(Some(response)) + } } fn get_redis_project_config_key(&self, key: ProjectKey) -> String { diff --git a/relay-server/src/statsd.rs b/relay-server/src/statsd.rs index 85b55dab76..1113d528fc 100644 --- a/relay-server/src/statsd.rs +++ b/relay-server/src/statsd.rs @@ -651,6 +651,8 @@ pub enum RelayCounters { /// - `hit`: One of: /// - `revision`: the cached version was validated to be up to date using its revision. /// - `project_config`: the request was handled by the cache. + /// - `project_config_revision`: the request was handled by the cache and the revision did + /// not change. /// - `false`: the request will be sent to the sentry endpoint. #[cfg(feature = "processing")] ProjectStateRedis,