Skip to content

Commit

Permalink
Make invite polling throttling customizable for CLI tests
Browse files Browse the repository at this point in the history
  • Loading branch information
touilleMan authored and vxgmichel committed Sep 3, 2024
1 parent d5448b7 commit 6716242
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 9 deletions.
3 changes: 3 additions & 0 deletions cli/tests/integration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ fn set_env(tmp_dir: &str, url: &ParsecAddr) {
std::env::set_var(PARSEC_BASE_HOME_DIR, format!("{tmp_dir}/cache"));
std::env::set_var(PARSEC_BASE_DATA_DIR, format!("{tmp_dir}/share"));
std::env::set_var(PARSEC_BASE_CONFIG_DIR, format!("{tmp_dir}/config"));
// Hidden environ variable only used for CLI testing to customize the throttling time
// in invitation polling, without that the tests would be much slower for no reason.
std::env::set_var("_PARSEC_INVITE_POLLING_THROTTLE_MS", "10");
}

fn unique_org_id() -> OrganizationID {
Expand Down
38 changes: 29 additions & 9 deletions libparsec/crates/client/src/invite/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,52 @@

use libparsec_types::prelude::*;

// The throttle duration is defined to 100 ms.
// The default throttle duration is too slow when testing the CLI, hence this environ
// variable than allows us to customize it (typically setting it to 10ms during tests)
//
// Note the `_` prefix and the fact this environ variable is not documented: it is only
// here for testing the CLI.
// This is because the CLI's tests run the default CLI binary (i.e. the test code is
// first compiled and run by `cargo test`, and in turn runs the CLI binary to do the tests).
// That means we cannot use time provider to mock time (since the CLI binary is not
// compiled in debug, and since the test code cannot communicate with a time provider
// in the CLI binary).
//
// Also note we don't use a feature-flag given this would further add complexity to
// the steps to obtain a valid CLI binary and do the CLI tests.
const CUSTOMIZE_THROTTLE_ENVIRON_VARIABLE: &str = "_PARSEC_INVITE_POLLING_THROTTLE_MS";

// The throttle duration is defined to 1 second.
// This value limits the amount of polling done by the peer
// to 10 requests per second. This is deliberately fast in order
// improve user experience and to accelerate the tests. However,
// this might be too much for the server and this value might need
// to be adjusted for production. In this case, a decoupling between
// testing and production might be necessary. This could be achieved
// by mocking the time provider passed to the throttler.
static THROTTLE_DURATION: Duration = Duration::milliseconds(100);
// to 1 requests per second.
const THROTTLE_DEFAULT_DURATION: Duration = Duration::milliseconds(1000);

pub struct Throttle<'a> {
time_provider: &'a TimeProvider,
last_call: Option<DateTime>,
throttle_duration: Duration,
}

impl<'a> Throttle<'a> {
pub fn new(time_provider: &'a TimeProvider) -> Self {
let throttle_duration = std::env::var(CUSTOMIZE_THROTTLE_ENVIRON_VARIABLE)
.ok()
// Parse as u32 to avoid corner cases with negative numbers
// and overflow when converting to i64.
.and_then(|raw| raw.parse::<u32>().ok())
.map(|raw| Duration::milliseconds(raw as i64))
.unwrap_or(THROTTLE_DEFAULT_DURATION);

Self {
time_provider,
last_call: None,
throttle_duration,
}
}

pub async fn throttle(&mut self) {
if let Some(last_call) = self.last_call {
let duration = last_call + THROTTLE_DURATION - self.time_provider.now();
let duration = last_call + self.throttle_duration - self.time_provider.now();
self.time_provider.sleep(duration).await;
}
self.last_call = Some(self.time_provider.now());
Expand Down

0 comments on commit 6716242

Please sign in to comment.