mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-09 21:26:14 +03:00
Use SystemClock
in EventCoalescer
(#8317)
This PR updates the `EventCoalescer` to use the `SystemClock` trait to abstract over the clock. This allows us to test the advancement of time without relying on the caller passing in the current time. Release Notes: - N/A
This commit is contained in:
parent
9b44ba9382
commit
e06ff5f507
@ -96,7 +96,7 @@ impl Telemetry {
|
|||||||
log_file: None,
|
log_file: None,
|
||||||
is_staff: None,
|
is_staff: None,
|
||||||
first_event_date_time: None,
|
first_event_date_time: None,
|
||||||
event_coalescer: EventCoalescer::new(),
|
event_coalescer: EventCoalescer::new(clock.clone()),
|
||||||
max_queue_size: MAX_QUEUE_LEN,
|
max_queue_size: MAX_QUEUE_LEN,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
use chrono::{DateTime, Duration, Utc};
|
use std::sync::Arc;
|
||||||
use std::time;
|
use std::time;
|
||||||
|
|
||||||
|
use chrono::{DateTime, Duration, Utc};
|
||||||
|
use clock::SystemClock;
|
||||||
|
|
||||||
const COALESCE_TIMEOUT: time::Duration = time::Duration::from_secs(20);
|
const COALESCE_TIMEOUT: time::Duration = time::Duration::from_secs(20);
|
||||||
const SIMULATED_DURATION_FOR_SINGLE_EVENT: time::Duration = time::Duration::from_millis(1);
|
const SIMULATED_DURATION_FOR_SINGLE_EVENT: time::Duration = time::Duration::from_millis(1);
|
||||||
|
|
||||||
@ -12,30 +15,20 @@ struct PeriodData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventCoalescer {
|
pub struct EventCoalescer {
|
||||||
|
clock: Arc<dyn SystemClock>,
|
||||||
state: Option<PeriodData>,
|
state: Option<PeriodData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventCoalescer {
|
impl EventCoalescer {
|
||||||
pub fn new() -> Self {
|
pub fn new(clock: Arc<dyn SystemClock>) -> Self {
|
||||||
Self { state: None }
|
Self { clock, state: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log_event(
|
pub fn log_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
environment: &'static str,
|
environment: &'static str,
|
||||||
) -> Option<(DateTime<Utc>, DateTime<Utc>, &'static str)> {
|
) -> Option<(DateTime<Utc>, DateTime<Utc>, &'static str)> {
|
||||||
self.log_event_with_time(Utc::now(), environment)
|
let log_time = self.clock.utc_now();
|
||||||
}
|
|
||||||
|
|
||||||
// pub fn close_current_period(&mut self) -> Option<(DateTime<Utc>, DateTime<Utc>)> {
|
|
||||||
// self.environment.map(|env| self.log_event(env)).flatten()
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn log_event_with_time(
|
|
||||||
&mut self,
|
|
||||||
log_time: DateTime<Utc>,
|
|
||||||
environment: &'static str,
|
|
||||||
) -> Option<(DateTime<Utc>, DateTime<Utc>, &'static str)> {
|
|
||||||
let coalesce_timeout = Duration::from_std(COALESCE_TIMEOUT).unwrap();
|
let coalesce_timeout = Duration::from_std(COALESCE_TIMEOUT).unwrap();
|
||||||
|
|
||||||
let Some(state) = &mut self.state else {
|
let Some(state) = &mut self.state else {
|
||||||
@ -78,18 +71,22 @@ impl EventCoalescer {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use chrono::TimeZone;
|
use chrono::TimeZone;
|
||||||
|
use clock::FakeSystemClock;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_same_context_exceeding_timeout() {
|
fn test_same_context_exceeding_timeout() {
|
||||||
|
let clock = Arc::new(FakeSystemClock::new(
|
||||||
|
Utc.with_ymd_and_hms(1990, 4, 12, 0, 0, 0).unwrap(),
|
||||||
|
));
|
||||||
let environment_1 = "environment_1";
|
let environment_1 = "environment_1";
|
||||||
let mut event_coalescer = EventCoalescer::new();
|
let mut event_coalescer = EventCoalescer::new(clock.clone());
|
||||||
|
|
||||||
assert_eq!(event_coalescer.state, None);
|
assert_eq!(event_coalescer.state, None);
|
||||||
|
|
||||||
let period_start = Utc.with_ymd_and_hms(1990, 4, 12, 0, 0, 0).unwrap();
|
let period_start = clock.utc_now();
|
||||||
let period_data = event_coalescer.log_event_with_time(period_start, environment_1);
|
let period_data = event_coalescer.log_event(environment_1);
|
||||||
|
|
||||||
assert_eq!(period_data, None);
|
assert_eq!(period_data, None);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -102,12 +99,12 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let within_timeout_adjustment = Duration::from_std(COALESCE_TIMEOUT / 2).unwrap();
|
let within_timeout_adjustment = Duration::from_std(COALESCE_TIMEOUT / 2).unwrap();
|
||||||
let mut period_end = period_start;
|
|
||||||
|
|
||||||
// Ensure that many calls within the timeout don't start a new period
|
// Ensure that many calls within the timeout don't start a new period
|
||||||
for _ in 0..100 {
|
for _ in 0..100 {
|
||||||
period_end += within_timeout_adjustment;
|
clock.advance(within_timeout_adjustment);
|
||||||
let period_data = event_coalescer.log_event_with_time(period_end, environment_1);
|
let period_data = event_coalescer.log_event(environment_1);
|
||||||
|
let period_end = clock.utc_now();
|
||||||
|
|
||||||
assert_eq!(period_data, None);
|
assert_eq!(period_data, None);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -120,10 +117,12 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let period_end = clock.utc_now();
|
||||||
let exceed_timeout_adjustment = Duration::from_std(COALESCE_TIMEOUT * 2).unwrap();
|
let exceed_timeout_adjustment = Duration::from_std(COALESCE_TIMEOUT * 2).unwrap();
|
||||||
// Logging an event exceeding the timeout should start a new period
|
// Logging an event exceeding the timeout should start a new period
|
||||||
let new_period_start = period_end + exceed_timeout_adjustment;
|
clock.advance(exceed_timeout_adjustment);
|
||||||
let period_data = event_coalescer.log_event_with_time(new_period_start, environment_1);
|
let new_period_start = clock.utc_now();
|
||||||
|
let period_data = event_coalescer.log_event(environment_1);
|
||||||
|
|
||||||
assert_eq!(period_data, Some((period_start, period_end, environment_1)));
|
assert_eq!(period_data, Some((period_start, period_end, environment_1)));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -138,13 +137,16 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_different_environment_under_timeout() {
|
fn test_different_environment_under_timeout() {
|
||||||
|
let clock = Arc::new(FakeSystemClock::new(
|
||||||
|
Utc.with_ymd_and_hms(1990, 4, 12, 0, 0, 0).unwrap(),
|
||||||
|
));
|
||||||
let environment_1 = "environment_1";
|
let environment_1 = "environment_1";
|
||||||
let mut event_coalescer = EventCoalescer::new();
|
let mut event_coalescer = EventCoalescer::new(clock.clone());
|
||||||
|
|
||||||
assert_eq!(event_coalescer.state, None);
|
assert_eq!(event_coalescer.state, None);
|
||||||
|
|
||||||
let period_start = Utc.with_ymd_and_hms(1990, 4, 12, 0, 0, 0).unwrap();
|
let period_start = clock.utc_now();
|
||||||
let period_data = event_coalescer.log_event_with_time(period_start, environment_1);
|
let period_data = event_coalescer.log_event(environment_1);
|
||||||
|
|
||||||
assert_eq!(period_data, None);
|
assert_eq!(period_data, None);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -157,8 +159,9 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let within_timeout_adjustment = Duration::from_std(COALESCE_TIMEOUT / 2).unwrap();
|
let within_timeout_adjustment = Duration::from_std(COALESCE_TIMEOUT / 2).unwrap();
|
||||||
let period_end = period_start + within_timeout_adjustment;
|
clock.advance(within_timeout_adjustment);
|
||||||
let period_data = event_coalescer.log_event_with_time(period_end, environment_1);
|
let period_end = clock.utc_now();
|
||||||
|
let period_data = event_coalescer.log_event(environment_1);
|
||||||
|
|
||||||
assert_eq!(period_data, None);
|
assert_eq!(period_data, None);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -170,10 +173,12 @@ mod tests {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
clock.advance(within_timeout_adjustment);
|
||||||
|
|
||||||
// Logging an event within the timeout but with a different environment should start a new period
|
// Logging an event within the timeout but with a different environment should start a new period
|
||||||
let period_end = period_end + within_timeout_adjustment;
|
let period_end = clock.utc_now();
|
||||||
let environment_2 = "environment_2";
|
let environment_2 = "environment_2";
|
||||||
let period_data = event_coalescer.log_event_with_time(period_end, environment_2);
|
let period_data = event_coalescer.log_event(environment_2);
|
||||||
|
|
||||||
assert_eq!(period_data, Some((period_start, period_end, environment_1)));
|
assert_eq!(period_data, Some((period_start, period_end, environment_1)));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -188,13 +193,16 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_switching_environment_while_within_timeout() {
|
fn test_switching_environment_while_within_timeout() {
|
||||||
|
let clock = Arc::new(FakeSystemClock::new(
|
||||||
|
Utc.with_ymd_and_hms(1990, 4, 12, 0, 0, 0).unwrap(),
|
||||||
|
));
|
||||||
let environment_1 = "environment_1";
|
let environment_1 = "environment_1";
|
||||||
let mut event_coalescer = EventCoalescer::new();
|
let mut event_coalescer = EventCoalescer::new(clock.clone());
|
||||||
|
|
||||||
assert_eq!(event_coalescer.state, None);
|
assert_eq!(event_coalescer.state, None);
|
||||||
|
|
||||||
let period_start = Utc.with_ymd_and_hms(1990, 4, 12, 0, 0, 0).unwrap();
|
let period_start = clock.utc_now();
|
||||||
let period_data = event_coalescer.log_event_with_time(period_start, environment_1);
|
let period_data = event_coalescer.log_event(environment_1);
|
||||||
|
|
||||||
assert_eq!(period_data, None);
|
assert_eq!(period_data, None);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -207,9 +215,10 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let within_timeout_adjustment = Duration::from_std(COALESCE_TIMEOUT / 2).unwrap();
|
let within_timeout_adjustment = Duration::from_std(COALESCE_TIMEOUT / 2).unwrap();
|
||||||
let period_end = period_start + within_timeout_adjustment;
|
clock.advance(within_timeout_adjustment);
|
||||||
|
let period_end = clock.utc_now();
|
||||||
let environment_2 = "environment_2";
|
let environment_2 = "environment_2";
|
||||||
let period_data = event_coalescer.log_event_with_time(period_end, environment_2);
|
let period_data = event_coalescer.log_event(environment_2);
|
||||||
|
|
||||||
assert_eq!(period_data, Some((period_start, period_end, environment_1)));
|
assert_eq!(period_data, Some((period_start, period_end, environment_1)));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -221,22 +230,26 @@ mod tests {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// // 0 20 40 60
|
|
||||||
// // |-------------------|-------------------|-------------------|-------------------
|
// 0 20 40 60
|
||||||
// // |--------|----------env change
|
// |-------------------|-------------------|-------------------|-------------------
|
||||||
// // |-------------------
|
// |--------|----------env change
|
||||||
// // |period_start |period_end
|
// |-------------------
|
||||||
// // |new_period_start
|
// |period_start |period_end
|
||||||
|
// |new_period_start
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_switching_environment_while_exceeding_timeout() {
|
fn test_switching_environment_while_exceeding_timeout() {
|
||||||
|
let clock = Arc::new(FakeSystemClock::new(
|
||||||
|
Utc.with_ymd_and_hms(1990, 4, 12, 0, 0, 0).unwrap(),
|
||||||
|
));
|
||||||
let environment_1 = "environment_1";
|
let environment_1 = "environment_1";
|
||||||
let mut event_coalescer = EventCoalescer::new();
|
let mut event_coalescer = EventCoalescer::new(clock.clone());
|
||||||
|
|
||||||
assert_eq!(event_coalescer.state, None);
|
assert_eq!(event_coalescer.state, None);
|
||||||
|
|
||||||
let period_start = Utc.with_ymd_and_hms(1990, 4, 12, 0, 0, 0).unwrap();
|
let period_start = clock.utc_now();
|
||||||
let period_data = event_coalescer.log_event_with_time(period_start, environment_1);
|
let period_data = event_coalescer.log_event(environment_1);
|
||||||
|
|
||||||
assert_eq!(period_data, None);
|
assert_eq!(period_data, None);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -249,9 +262,10 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let exceed_timeout_adjustment = Duration::from_std(COALESCE_TIMEOUT * 2).unwrap();
|
let exceed_timeout_adjustment = Duration::from_std(COALESCE_TIMEOUT * 2).unwrap();
|
||||||
let period_end = period_start + exceed_timeout_adjustment;
|
clock.advance(exceed_timeout_adjustment);
|
||||||
|
let period_end = clock.utc_now();
|
||||||
let environment_2 = "environment_2";
|
let environment_2 = "environment_2";
|
||||||
let period_data = event_coalescer.log_event_with_time(period_end, environment_2);
|
let period_data = event_coalescer.log_event(environment_2);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
period_data,
|
period_data,
|
||||||
@ -270,6 +284,7 @@ mod tests {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0 20 40 60
|
// 0 20 40 60
|
||||||
// |-------------------|-------------------|-------------------|-------------------
|
// |-------------------|-------------------|-------------------|-------------------
|
||||||
// |--------|----------------------------------------env change
|
// |--------|----------------------------------------env change
|
||||||
|
Loading…
Reference in New Issue
Block a user