tunables: optionify tunables and remove get_ prefix

Summary: Currently fetching a tunable (except by repo ones) returns the default value when the tunable is not set. This can be error prune as it doesn't enforce handling the not set case and makes it awkward to set default values, it's also not consistent with the by repo tunables which return an option instead. This diff changes tunable fetching to make it return an option, and adds a .unwrap_or_default() at every callsite to maintain the current behaviour.

Reviewed By: yancouto

Differential Revision: D43123305

fbshipit-source-id: 32cb69ba78d52bc22979250c6e16edd1800cd1de
This commit is contained in:
Youssef Ibrahim 2023-02-09 08:43:11 -08:00 committed by Facebook GitHub Bot
parent 61d640517e
commit 0c5939f6a7
72 changed files with 597 additions and 364 deletions

View File

@ -131,7 +131,9 @@ pub fn record_get_stats(
match result {
Ok(Some(data)) => {
let size = data.as_bytes().len();
let size_logging_threshold = tunables().get_blobstore_read_size_logging_threshold();
let size_logging_threshold = tunables()
.blobstore_read_size_logging_threshold()
.unwrap_or_default();
if size_logging_threshold > 0 && size > size_logging_threshold as usize {
scuba.unsampled();
}

View File

@ -138,8 +138,8 @@ impl MemcacheOps {
backing_store_params.to_string()
);
let sitever = if tunables().get_blobstore_memcache_sitever() > 0 {
tunables().get_blobstore_memcache_sitever() as u32
let sitever = if tunables().blobstore_memcache_sitever().unwrap_or_default() > 0 {
tunables().blobstore_memcache_sitever().unwrap_or_default() as u32
} else {
MC_SITEVER
};

View File

@ -170,7 +170,8 @@ impl<T: Blobstore> RedactedBlobstoreInner<T> {
pub fn to_scuba_redacted_blob_accessed(&self, ctx: &CoreContext, key: &str, operation: &str) {
let sampling_rate = tunables()
.get_redacted_logging_sampling_rate()
.redacted_logging_sampling_rate()
.unwrap_or_default()
.try_into()
.ok()
.and_then(NonZeroU64::new);

View File

@ -344,7 +344,8 @@ fn report_deduplicated_put(ctx: &CoreContext, key: &str) {
let mut scuba = ctx.scuba().clone();
if let Ok(Some(v)) = tunables()
.get_deduplicated_put_sampling_rate()
.deduplicated_put_sampling_rate()
.unwrap_or_default()
.try_into()
.map(NonZeroU64::new)
{

View File

@ -399,7 +399,10 @@ impl BlobstoreWal for SqlBlobstoreWal {
}
async fn delete_by_key(&self, ctx: &CoreContext, entries: &[BlobstoreWalEntry]) -> Result<()> {
if !tunables().get_wal_disable_rendezvous_on_deletes() {
if !tunables()
.wal_disable_rendezvous_on_deletes()
.unwrap_or_default()
{
self.delete_rendezvous
.dispatch(ctx.fb, entries.iter().cloned().collect(), || {
let connections = self.write_connections.clone();
@ -429,7 +432,7 @@ impl SqlShardedConstruct for SqlBlobstoreWal {
mut read_master_connections,
mut write_connections,
} = connections;
if !tunables().get_disable_wal_read_committed() {
if !tunables().disable_wal_read_committed().unwrap_or_default() {
for conn in read_master_connections
.iter_mut()
.chain(write_connections.iter_mut())

View File

@ -166,8 +166,8 @@ impl CachingBonsaiHgMapping {
fn create_key_gen() -> KeyGen {
let key_prefix = "scm.mononoke.bonsai_hg_mapping";
let sitever = if tunables().get_bonsai_hg_mapping_sitever() > 0 {
tunables().get_bonsai_hg_mapping_sitever() as u32
let sitever = if tunables().bonsai_hg_mapping_sitever().unwrap_or_default() > 0 {
tunables().bonsai_hg_mapping_sitever().unwrap_or_default() as u32
} else {
thrift::MC_SITEVER as u32
};

View File

@ -164,12 +164,18 @@ impl AffectedChangesets {
future::ready(!exists)
});
let limit = match tunables().get_hooks_additional_changesets_limit() {
let limit = match tunables()
.hooks_additional_changesets_limit()
.unwrap_or_default()
{
limit if limit > 0 => limit as usize,
_ => std::usize::MAX,
};
let additional_changesets = if tunables().get_run_hooks_on_additional_changesets() {
let additional_changesets = if tunables()
.run_hooks_on_additional_changesets()
.unwrap_or_default()
{
let bonsais = range
.and_then({
let mut count = 0;
@ -407,7 +413,8 @@ impl AffectedChangesets {
if (kind == BookmarkKind::Publishing || kind == BookmarkKind::PullDefaultPublishing)
&& should_run_hooks(authz, reason)
{
if reason == BookmarkUpdateReason::Push && tunables().get_disable_hooks_on_plain_push()
if reason == BookmarkUpdateReason::Push
&& tunables().disable_hooks_on_plain_push().unwrap_or_default()
{
// Skip running hooks for this plain push.
return Ok(());

View File

@ -72,7 +72,10 @@ pub async fn run_hooks(
push_authored_by: PushAuthoredBy,
) -> Result<(), BookmarkMovementError> {
if cross_repo_push_source == CrossRepoPushSource::PushRedirected {
if tunables().get_disable_running_hooks_in_pushredirected_repo() {
if tunables()
.disable_running_hooks_in_pushredirected_repo()
.unwrap_or_default()
{
let cs_ids = take_n_changeset_ids(changesets, 10);
ctx.scuba()
.clone()

View File

@ -48,7 +48,8 @@ async fn should_check_repo_lock(
.check_if_read_only_bypass_allowed(idents)
.await;
let enforce_acl_check = tunables().get_enforce_bypass_readonly_acl();
let enforce_acl_check =
tunables().enforce_bypass_readonly_acl().unwrap_or_default();
if !bypass_allowed && enforce_acl_check {
return true;

View File

@ -26,7 +26,9 @@ use crate::Repo;
pub(crate) fn should_run_hooks(authz: &AuthorizationContext, reason: BookmarkUpdateReason) -> bool {
if authz.is_service() {
reason == BookmarkUpdateReason::Pushrebase
&& tunables().get_enable_hooks_on_service_pushrebase()
&& tunables()
.enable_hooks_on_service_pushrebase()
.unwrap_or_default()
} else {
true
}

View File

@ -107,7 +107,11 @@ impl SqlBookmarksSubscription {
}
fn has_aged_out(&self) -> bool {
let max_age_ms = match tunables().get_bookmark_subscription_max_age_ms().try_into() {
let max_age_ms = match tunables()
.bookmark_subscription_max_age_ms()
.unwrap_or_default()
.try_into()
{
Ok(duration) if duration > 0 => duration,
_ => DEFAULT_SUBSCRIPTION_MAX_AGE_MS,
};
@ -169,7 +173,10 @@ impl BookmarksSubscription for SqlBookmarksSubscription {
self.bookmarks.insert(book, value);
}
None => {
if tunables().get_bookmark_subscription_protect_master() {
if tunables()
.bookmark_subscription_protect_master()
.unwrap_or_default()
{
if book.as_str() == "master" {
warn!(
ctx.logger(),

View File

@ -115,7 +115,11 @@ pub struct CachedBookmarks {
}
fn ttl() -> Option<Duration> {
let ttl_ms = match tunables().get_bookmarks_cache_ttl_ms().try_into() {
let ttl_ms = match tunables()
.bookmarks_cache_ttl_ms()
.unwrap_or_default()
.try_into()
{
Ok(0) => 2000, // 0 means default.
Ok(duration) => duration, // Use provided duration.
Err(_) => return None, // Negative values mean no cache.

View File

@ -736,7 +736,10 @@ impl BookmarksCoordinator {
let cur_bookmarks = self.bookmarks.with_read(|bookmarks| bookmarks.clone());
let new_bookmarks = if tunables().get_warm_bookmark_cache_disable_subscription() {
let new_bookmarks = if tunables()
.warm_bookmark_cache_disable_subscription()
.unwrap_or_default()
{
let books = self
.repo
.bookmarks()
@ -864,7 +867,8 @@ impl BookmarksCoordinator {
}
let delay_ms = match tunables()
.get_warm_bookmark_cache_poll_interval_ms()
.warm_bookmark_cache_poll_interval_ms()
.unwrap_or_default()
.try_into()
{
Ok(duration) if duration > 0 => duration,

View File

@ -67,7 +67,9 @@ impl ScubaLoggingArgs {
let maybe_scuba = match self.warm_bookmark_cache_scuba_dataset.clone() {
Some(scuba) => {
let hostname = hostname::get_hostname()?;
let sampling_pct = tunables().get_warm_bookmark_cache_logging_sampling_pct() as u64;
let sampling_pct = tunables()
.warm_bookmark_cache_logging_sampling_pct()
.unwrap_or_default() as u64;
let mut hasher = DefaultHasher::new();
hostname.hash(&mut hasher);

View File

@ -517,7 +517,9 @@ fn create_warm_bookmark_cache_scuba_sample_builder(
{
Some(scuba) => {
let hostname = hostname::get_hostname()?;
let sampling_pct = tunables().get_warm_bookmark_cache_logging_sampling_pct() as u64;
let sampling_pct = tunables()
.warm_bookmark_cache_logging_sampling_pct()
.unwrap_or_default() as u64;
let mut hasher = DefaultHasher::new();
hostname.hash(&mut hasher);

View File

@ -204,7 +204,7 @@ pub async fn subcommand_blobstore_fetch<'a>(
let maybe_redacted_blobs_fut = async {
match redaction {
Redaction::Enabled => {
let redacted_blobs = if tunables().get_redaction_config_from_xdb() {
let redacted_blobs = if tunables().redaction_config_from_xdb().unwrap_or_default() {
let redacted_blobs_db = args::not_shardmanager_compatible::open_sql::<
SqlRedactedContentStore,
>(fb, config_store, matches)?;

View File

@ -1078,9 +1078,9 @@ async fn get_batch_ctx(ctx: &CoreContext, limit_qps: bool) -> CoreContext {
// create new context so each derivation batch has its own trace
// and is rate-limited
let session = SessionContainer::builder(ctx.fb)
.blobstore_maybe_read_qps_limiter(tunables().get_backfill_read_qps())
.blobstore_maybe_read_qps_limiter(tunables().backfill_read_qps().unwrap_or_default())
.await
.blobstore_maybe_write_qps_limiter(tunables().get_backfill_write_qps())
.blobstore_maybe_write_qps_limiter(tunables().backfill_write_qps().unwrap_or_default())
.await
.build();
session.new_context(

View File

@ -774,7 +774,11 @@ where
Ok(())
};
if tunables().get_xrepo_disable_commit_sync_lease() || disable_lease {
if tunables()
.xrepo_disable_commit_sync_lease()
.unwrap_or_default()
|| disable_lease
{
sync().await?;
} else {
run_with_lease(ctx, &self.x_repo_sync_lease, lease_key, checker, sync).await?;
@ -1631,7 +1635,10 @@ where
maybe_target_bcs_id: Option<ChangesetId>,
version_name: CommitSyncConfigVersion,
) -> Result<(), Error> {
if tunables().get_xrepo_sync_disable_all_syncs() {
if tunables()
.xrepo_sync_disable_all_syncs()
.unwrap_or_default()
{
return Err(ErrorKind::XRepoSyncDisabled.into());
}
@ -1731,7 +1738,10 @@ pub async fn update_mapping_with_version<'a, M: SyncedCommitMapping + Clone + 's
syncer: &'a CommitSyncer<M, R>,
version_name: &CommitSyncConfigVersion,
) -> Result<(), Error> {
if tunables().get_xrepo_sync_disable_all_syncs() {
if tunables()
.xrepo_sync_disable_all_syncs()
.unwrap_or_default()
{
return Err(ErrorKind::XRepoSyncDisabled.into());
}
@ -1860,7 +1870,10 @@ where
break;
}
let leased = if tunables().get_xrepo_disable_commit_sync_lease() {
let leased = if tunables()
.xrepo_disable_commit_sync_lease()
.unwrap_or_default()
{
true
} else {
let result = lease.try_add_put_lease(&lease_key).await;

View File

@ -96,7 +96,10 @@ impl PushrebaseTransactionHook for CrossRepoSyncTransactionHook {
_ctx: &CoreContext,
txn: Transaction,
) -> Result<Transaction, BookmarkTransactionError> {
if tunables().get_xrepo_sync_disable_all_syncs() {
if tunables()
.xrepo_sync_disable_all_syncs()
.unwrap_or_default()
{
let e: Error = ErrorKind::XRepoSyncDisabled.into();
return Err(e.into());
}

View File

@ -70,7 +70,10 @@ pub fn log_rewrite(
duration: Duration,
sync_result: &Result<Option<ChangesetId>, Error>,
) {
if !tunables().get_enable_logging_commit_rewrite_data() {
if !tunables()
.enable_logging_commit_rewrite_data()
.unwrap_or_default()
{
return;
}

View File

@ -112,7 +112,10 @@ pub async fn get_mapping_change_version(
repo: &(impl RepoDerivedDataRef + Send + Sync),
source_cs_id: ChangesetId,
) -> Result<Option<CommitSyncConfigVersion>, Error> {
if tunables::tunables().get_allow_change_xrepo_mapping_extra() {
if tunables::tunables()
.allow_change_xrepo_mapping_extra()
.unwrap_or_default()
{
let cs_info = ChangesetInfo::derive(ctx, repo, source_cs_id).await?;
let maybe_mapping = cs_info

View File

@ -95,7 +95,8 @@ impl RendezVousController for ConfigurableRendezVousController {
fn max_delay() -> Duration {
Duration::from_millis(
::tunables::tunables()
.get_rendezvous_dispatch_delay_ms()
.rendezvous_dispatch_delay_ms()
.unwrap_or_default()
.try_into()
.unwrap_or(0),
)
@ -103,7 +104,8 @@ fn max_delay() -> Duration {
fn max_threshold() -> usize {
::tunables::tunables()
.get_rendezvous_dispatch_max_threshold()
.rendezvous_dispatch_max_threshold()
.unwrap_or_default()
.try_into()
.unwrap_or(0)
}

View File

@ -413,7 +413,7 @@ where
T: Send + 'static,
Fut: Future<Output = Result<T>>,
{
if tunables().get_disable_sql_auto_retries() {
if tunables().disable_sql_auto_retries().unwrap_or_default() {
return do_query().await;
}
Ok(retry(
@ -440,7 +440,7 @@ where
T: Send + Abomonation + MemcacheEntity + Clone + 'static,
Fut: Future<Output = Result<T>> + Send,
{
if tunables().get_disable_sql_auto_cache() {
if tunables().disable_sql_auto_cache().unwrap_or_default() {
return query_with_retry_no_cache(&do_query).await;
}
let fetch = || query_with_retry_no_cache(&do_query);

View File

@ -189,7 +189,11 @@ impl MononokeScubaSampleBuilder {
self.inner.add("log_tag", log_tag);
if let Some(mut msg) = msg.into() {
match tunables().get_max_scuba_msg_length().try_into() {
match tunables()
.max_scuba_msg_length()
.unwrap_or_default()
.try_into()
{
Ok(size) if size > 0 && msg.len() > size => {
msg.truncate(size);
msg.push_str(" (...)");

View File

@ -623,7 +623,9 @@ impl<Root: RootDeletedManifestIdCommon> RootDeletedManifestDeriver<Root> {
.into_iter()
.map(|bonsai| (bonsai.get_changeset_id(), bonsai))
.collect();
let use_new_parallel = !tunables().get_deleted_manifest_disable_new_parallel_derivation();
let use_new_parallel = !tunables()
.deleted_manifest_disable_new_parallel_derivation()
.unwrap_or_default();
borrowed!(id_to_bonsai);
// Map of ids to derived values.
// We need to be careful to use this for self-references, since the intermediate derived

View File

@ -45,7 +45,10 @@ pub async fn derive_filenodes(
derivation_ctx: &DerivationContext,
bcs: BonsaiChangeset,
) -> Result<FilenodesOnlyPublic> {
if tunables::tunables().get_filenodes_disabled() {
if tunables::tunables()
.filenodes_disabled()
.unwrap_or_default()
{
return Ok(FilenodesOnlyPublic::Disabled);
}
let (_, public_filenode, non_roots) =
@ -60,7 +63,10 @@ pub async fn derive_filenodes(
}
}
// In case it got updated while deriving
if tunables::tunables().get_filenodes_disabled() {
if tunables::tunables()
.filenodes_disabled()
.unwrap_or_default()
{
return Ok(FilenodesOnlyPublic::Disabled);
}
Ok(public_filenode)

View File

@ -187,7 +187,10 @@ impl BonsaiDerivable for FilenodesOnlyPublic {
derivation_ctx: &DerivationContext,
changeset_id: ChangesetId,
) -> Result<Option<Self>> {
if tunables::tunables().get_filenodes_disabled() {
if tunables::tunables()
.filenodes_disabled()
.unwrap_or_default()
{
return Ok(Some(FilenodesOnlyPublic::Disabled));
}
let filenode_res = fetch_root_filenode(ctx, derivation_ctx, changeset_id).await?;

View File

@ -494,17 +494,17 @@ impl DerivedDataManager {
let mut attempt = 0;
let started = Instant::now();
let fallback_timeout = get_duration_from_tunable_or(
MononokeTunables::get_remote_derivation_fallback_timeout_secs,
MononokeTunables::remote_derivation_fallback_timeout_secs,
Duration::from_secs,
FALLBACK_TIMEOUT_SECS,
);
let retry_delay = get_duration_from_tunable_or(
MononokeTunables::get_derivation_request_retry_delay,
MononokeTunables::derivation_request_retry_delay,
Duration::from_millis,
RETRY_DELAY_MS,
);
while let Some(true) =
tunables::tunables().get_by_repo_enable_remote_derivation(self.repo_name())
tunables::tunables().by_repo_enable_remote_derivation(self.repo_name())
{
if started.elapsed() >= fallback_timeout {
self.derived_data_scuba::<Derivable>(&None)
@ -964,7 +964,7 @@ pub(super) struct DerivationOutcome<Derivable> {
fn emergency_disabled(repo_name: &str, derivable_name: &str) -> bool {
let disabled_for_repo = tunables::tunables()
.get_by_repo_all_derived_data_disabled(repo_name)
.by_repo_all_derived_data_disabled(repo_name)
.unwrap_or(false);
if disabled_for_repo {
@ -972,7 +972,7 @@ fn emergency_disabled(repo_name: &str, derivable_name: &str) -> bool {
}
let disabled_for_type = tunables::tunables()
.get_by_repo_derived_data_types_disabled(repo_name)
.by_repo_derived_data_types_disabled(repo_name)
.unwrap_or_else(Vec::new);
if disabled_for_type
@ -988,7 +988,7 @@ fn emergency_disabled(repo_name: &str, derivable_name: &str) -> bool {
async fn derivation_disabled_watcher(repo_name: &str, derivable_name: &'static str) {
let delay_duration = get_duration_from_tunable_or(
MononokeTunables::get_derived_data_disabled_watcher_delay_secs,
MononokeTunables::derived_data_disabled_watcher_delay_secs,
Duration::from_secs,
10,
);

View File

@ -153,7 +153,9 @@ impl DerivedDataManager {
}
pub(super) fn should_log_slow_derivation(&self, duration: Duration) -> bool {
let threshold = tunables::tunables().get_derived_data_slow_derivation_threshold_secs();
let threshold = tunables::tunables()
.derived_data_slow_derivation_threshold_secs()
.unwrap_or_default();
let threshold = match threshold.try_into() {
Ok(t) if t > 0 => t,
_ => return false,

View File

@ -37,7 +37,7 @@ impl DerivedDataManager {
/// the one that should be used for derivation.
pub(super) fn set_derivation_session_class(&self, mut ctx: CoreContext) -> CoreContext {
if tunables::tunables()
.get_by_repo_derived_data_use_background_session_class(self.repo_name())
.by_repo_derived_data_use_background_session_class(self.repo_name())
.unwrap_or(false)
{
ctx.session_mut()
@ -79,7 +79,9 @@ impl DerivedDataManager {
}
pub(super) fn max_parallel_derivations(&self) -> usize {
let buffer_size = tunables::tunables().get_derived_data_parallel_derivation_buffer();
let buffer_size = tunables::tunables()
.derived_data_parallel_derivation_buffer()
.unwrap_or_default();
if buffer_size > 0 {
buffer_size
.try_into()

View File

@ -173,7 +173,7 @@ macro_rules! impl_bonsai_derived_via_manager {
pub fn override_ctx(mut ctx: CoreContext, repo: impl RepoIdentityRef) -> CoreContext {
let use_bg_class = tunables::tunables()
.get_by_repo_derived_data_use_background_session_class(repo.repo_identity().name());
.by_repo_derived_data_use_background_session_class(repo.repo_identity().name());
if let Some(true) = use_bg_class {
ctx.session_mut()
.override_session_class(SessionClass::BackgroundUnlessTooSlow);

View File

@ -402,7 +402,7 @@ async fn create_unode_file(
// But we consider this case is rare enough to not worry about it.
fn can_reuse(unode_version: UnodeVersion) -> bool {
unode_version == UnodeVersion::V2 || tunables::tunables().get_force_unode_v2()
unode_version == UnodeVersion::V2 || tunables::tunables().force_unode_v2().unwrap_or_default()
}
async fn reuse_manifest_parent(

View File

@ -693,7 +693,7 @@ impl EdenApiHandler for CommitMutationsHandler {
_query: Self::QueryStringExtractor,
request: Self::Request,
) -> HandlerResult<'async_trait, Self::Response> {
if !tunables().get_mutation_generate_for_draft() {
if !tunables().mutation_generate_for_draft().unwrap_or_default() {
return Ok(stream::empty().boxed());
}
let commits = request

View File

@ -136,7 +136,11 @@ impl RequestDumperMiddleware {
impl Middleware for RequestDumperMiddleware {
async fn inbound(&self, state: &mut State) -> Option<Response<Body>> {
let logger = &RequestContext::borrow_from(state).logger;
let sample_ratio: u64 = match tunables().get_edenapi_req_dumper_sample_ratio().try_into() {
let sample_ratio: u64 = match tunables()
.edenapi_req_dumper_sample_ratio()
.unwrap_or_default()
.try_into()
{
Ok(n) => n,
Err(e) => {
warn!(

View File

@ -298,7 +298,7 @@ pub async fn list_file_history<'a>(
mut order: TraversalOrder,
) -> Result<impl NewStream<Item = Result<ChangesetId, Error>> + 'a, FastlogError> {
if tunables::tunables()
.get_by_repo_fastlog_disable_mutable_renames(repo.repo_identity().name())
.by_repo_fastlog_disable_mutable_renames(repo.repo_identity().name())
.unwrap_or(false)
{
follow_mutable_renames = FollowMutableFileHistory::ImmutableCommitParents;
@ -1032,7 +1032,7 @@ async fn try_continue_traversal_when_no_parents(
}
if !tunables::tunables()
.get_by_repo_fastlog_disable_mutable_renames(repo.repo_identity().name())
.by_repo_fastlog_disable_mutable_renames(repo.repo_identity().name())
.unwrap_or(follow_mutable_renames == FollowMutableFileHistory::ImmutableCommitParents)
{
return find_mutable_renames(ctx, repo, (cs_id, path), history_graph, mutable_renames)

View File

@ -262,7 +262,8 @@ fn log_stats<H: ScubaHandler>(state: &mut State, status_code: &StatusCode) -> Op
if let Some(duration) = info.duration {
// If tunables say we should, log high values unsampled
if let Ok(threshold) = tunables::tunables()
.get_edenapi_unsampled_duration_threshold_ms()
.edenapi_unsampled_duration_threshold_ms()
.unwrap_or_default()
.try_into()
{
if duration.as_millis_unchecked() > threshold {

View File

@ -81,7 +81,7 @@ impl LandService for LandServiceThriftImpl {
land_changesets.clone(),
);
if tunables().get_batching_to_land_service() {
if tunables().batching_to_land_service().unwrap_or_default() {
let (sender, receiver) =
oneshot::channel::<Result<LandChangesetsResponse, LandChangesetsError>>();

View File

@ -511,7 +511,10 @@ pub trait MegarepoOp {
for (src_path, entry) in entries {
match (src_path, entry) {
(Some(src_path), Entry::Leaf(leaf)) => {
if tunables().get_megarepo_api_dont_set_file_mutable_renames() {
if tunables()
.megarepo_api_dont_set_file_mutable_renames()
.unwrap_or_default()
{
continue;
}
@ -534,7 +537,10 @@ pub trait MegarepoOp {
}
}
(src_path, Entry::Tree(tree)) => {
if tunables().get_megarepo_api_dont_set_directory_mutable_renames() {
if tunables()
.megarepo_api_dont_set_directory_mutable_renames()
.unwrap_or_default()
{
continue;
}

View File

@ -75,15 +75,15 @@ pub enum MergeMode {
fn get_squashing_overrides(repo_name: &str, target_bookmark: &str) -> (Option<i64>, Option<bool>) {
let targets = tunables::tunables()
.get_by_repo_megarepo_squashing_config_override_targets(repo_name)
.by_repo_megarepo_squashing_config_override_targets(repo_name)
.unwrap_or_default();
if targets
.iter()
.any(|target| target.as_str() == target_bookmark)
{
(
tunables::tunables().get_by_repo_megarepo_override_squashing_limit(repo_name),
tunables::tunables().get_by_repo_megarepo_override_author_check(repo_name),
tunables::tunables().by_repo_megarepo_override_squashing_limit(repo_name),
tunables::tunables().by_repo_megarepo_override_author_check(repo_name),
)
} else {
(None, None)

View File

@ -315,7 +315,9 @@ where
builder.add_mparam("category", "manifests")?;
let mut buffer_size = tunables::tunables().get_repo_client_gettreepack_buffer_size();
let mut buffer_size = tunables::tunables()
.repo_client_gettreepack_buffer_size()
.unwrap_or_default();
if buffer_size <= 0 {
buffer_size = 1000
}

View File

@ -147,8 +147,8 @@ impl CachedHgMutationStore {
fn create_key_gen() -> KeyGen {
let key_prefix = "scm.mononoke.hg_mutation_store";
let sitever = if tunables().get_hg_mutation_store_sitever() > 0 {
tunables().get_hg_mutation_store_sitever() as u32
let sitever = if tunables().hg_mutation_store_sitever().unwrap_or_default() > 0 {
tunables().hg_mutation_store_sitever().unwrap_or_default() as u32
} else {
thrift::MC_SITEVER as u32
};
@ -240,8 +240,14 @@ impl EntityStore<HgMutationCacheEntry> for CacheRequest<'_> {
}
fn cache_determinator(&self, _: &HgMutationCacheEntry) -> CacheDisposition {
let ttl = if tunables().get_hg_mutation_store_caching_ttl_secs() > 0 {
tunables().get_hg_mutation_store_caching_ttl_secs() as u64
let ttl = if tunables()
.hg_mutation_store_caching_ttl_secs()
.unwrap_or_default()
> 0
{
tunables()
.hg_mutation_store_caching_ttl_secs()
.unwrap_or_default() as u64
} else {
DEFAULT_TTL_SECS
};

View File

@ -99,7 +99,7 @@ pub async fn lookup_filenode_id<B: Blobstore>(
blobstore: &B,
key: FileNodeIdPointer,
) -> Result<Option<HgFileNodeId>> {
let filenode_lookup_timeout_ms = tunables().get_filenode_lookup_timeout_ms();
let filenode_lookup_timeout_ms = tunables().filenode_lookup_timeout_ms().unwrap_or_default();
let fut = blobstore.get(ctx, &key.0);
let blob = if filenode_lookup_timeout_ms > 0 {
let maybe_timed_out = timeout(

View File

@ -655,7 +655,7 @@ impl ChangesetContext {
/// own ancestor for the purpose of this call.
pub async fn is_ancestor_of(&self, other_commit: ChangesetId) -> Result<bool, MononokeError> {
let new_commit_graph_rollout_pct = tunables()
.get_by_repo_new_commit_graph_is_ancestor_percentage(self.repo().name())
.by_repo_new_commit_graph_is_ancestor_percentage(self.repo().name())
.unwrap_or(0);
let use_new_commit_graph =
((rand::random::<usize>() % 100) as i64) < new_commit_graph_rollout_pct;
@ -1199,9 +1199,11 @@ impl ChangesetContext {
};
Ok(match basenames_and_suffixes {
Some(basenames_and_suffixes)
if !tunables().get_disable_basename_suffix_skeleton_manifest()
if !tunables()
.disable_basename_suffix_skeleton_manifest()
.unwrap_or_default()
&& (!basenames_and_suffixes.has_right()
|| tunables().get_enable_bssm_suffix_query()) =>
|| tunables().enable_bssm_suffix_query().unwrap_or_default()) =>
{
self.find_files_with_bssm(prefixes, basenames_and_suffixes, ordering)
.await?

View File

@ -280,7 +280,7 @@ async fn maybe_push_redirector(
repo: &Arc<Repo>,
repos: &MononokeRepos<Repo>,
) -> Result<Option<PushRedirector<Repo>>, MononokeError> {
if tunables().get_disable_scs_pushredirect() {
if tunables().disable_scs_pushredirect().unwrap_or_default() {
return Ok(None);
}
let base = match repo.repo_handler_base().maybe_push_redirector_base.as_ref() {

View File

@ -41,7 +41,10 @@ impl RepoContext {
) -> CreateBookmarkOp<'a> {
let mut op = CreateBookmarkOp::new(bookmark, target, BookmarkUpdateReason::ApiRequest)
.with_pushvars(pushvars);
if !tunables().get_disable_commit_scribe_logging_scs() {
if !tunables()
.disable_commit_scribe_logging_scs()
.unwrap_or_default()
{
op = op.log_new_public_commits_to_scribe();
}
op

View File

@ -76,7 +76,10 @@ impl RepoContext {
BookmarkUpdateReason::ApiRequest,
)
.with_pushvars(pushvars);
if !tunables().get_disable_commit_scribe_logging_scs() {
if !tunables()
.disable_commit_scribe_logging_scs()
.unwrap_or_default()
{
op = op.log_new_public_commits_to_scribe();
}
op

View File

@ -654,7 +654,10 @@ async fn commit_find_files_impl(fb: FacebookInit) -> Result<(), Error> {
.try_collect()
.await?;
// BSSM have different but consistent orders
let expected_files = if tunables().get_disable_basename_suffix_skeleton_manifest() {
let expected_files = if tunables()
.disable_basename_suffix_skeleton_manifest()
.unwrap_or_default()
{
vec![
MononokePath::try_from("1")?,
MononokePath::try_from("dir1/file_1_in_dir1")?,
@ -690,7 +693,10 @@ async fn commit_find_files_impl(fb: FacebookInit) -> Result<(), Error> {
.await?
.try_collect()
.await?;
let expected_files = if tunables().get_disable_basename_suffix_skeleton_manifest() {
let expected_files = if tunables()
.disable_basename_suffix_skeleton_manifest()
.unwrap_or_default()
{
vec![
MononokePath::try_from("dir1/subdir1/subsubdir2/file_1")?,
MononokePath::try_from("dir2/file_1_in_dir2")?,

View File

@ -59,7 +59,8 @@ impl CacheHandlers {
let memcache = MemcacheClient::new(fb)?.into();
let presence_cachelib = pool.clone().into();
let sitever = tunables::tunables()
.get_mutable_renames_sitever()
.mutable_renames_sitever()
.unwrap_or_default()
.try_into()
.context("While converting from i64 to u32 sitever")?;
let presence_keygen = KeyGen::new("scm.mononoke.mutable_renames.present", CODEVER, sitever);

View File

@ -250,7 +250,9 @@ impl FilenodesReader {
}
}
let ratio = tunables().get_filenodes_master_fallback_ratio();
let ratio = tunables()
.filenodes_master_fallback_ratio()
.unwrap_or_default();
if ratio > 0 {
let mut rng = thread_rng();
let n = rng.gen_range(0..ratio);
@ -416,7 +418,7 @@ async fn select_filenode_from_sql(
filenode: HgFileNodeId,
recorder: &PerfCounterRecorder<'_>,
) -> Result<FilenodeResult<Option<CachedFilenode>>, ErrorKind> {
if tunables().get_filenodes_disabled() {
if tunables().filenodes_disabled().unwrap_or_default() {
STATS::gets_disabled.add_value(1);
return Ok(FilenodeResult::Disabled);
}
@ -500,7 +502,7 @@ async fn select_history_from_sql(
recorder: &PerfCounterRecorder<'_>,
limit: Option<u64>,
) -> Result<FilenodeRangeResult<CachedHistory>, Error> {
if tunables().get_filenodes_disabled() {
if tunables().filenodes_disabled().unwrap_or_default() {
STATS::range_gets_disabled.add_value(1);
return Ok(FilenodeRangeResult::Disabled);
}

View File

@ -108,7 +108,7 @@ impl FilenodesWriter {
filenodes: Vec<(PathHash, PreparedFilenode)>,
replace: bool,
) -> Result<FilenodeResult<()>, Error> {
if tunables().get_filenodes_disabled() {
if tunables().filenodes_disabled().unwrap_or_default() {
STATS::adds_disabled.add_value(1);
return Ok(FilenodeResult::Disabled);
}

View File

@ -480,7 +480,10 @@ async fn maybe_validate_commit(
bcs_id: &ChangesetId,
retry_num: PushrebaseRetryNum,
) -> Result<(), PushrebaseError> {
if tunables().get_pushrebase_disable_rebased_commit_validation() {
if tunables()
.pushrebase_disable_rebased_commit_validation()
.unwrap_or_default()
{
return Ok(());
}

View File

@ -144,7 +144,10 @@ impl SqlConstructFromMetadataDatabaseConfig for SqlPushrebaseMutationMappingConn
#[async_trait]
impl PushrebaseMutationMapping for SqlPushrebaseMutationMapping {
fn get_hook(&self) -> Option<Box<dyn PushrebaseHook>> {
if tunables().get_disable_save_mapping_pushrebase_hook() {
if tunables()
.disable_save_mapping_pushrebase_hook()
.unwrap_or_default()
{
None
} else {
Some(SaveMappingPushrebaseHook::new(self.repo_id))

View File

@ -449,7 +449,10 @@ struct SkiplistLoader {
#[async_trait]
impl Loader<SkiplistEdgeMapping> for SkiplistLoader {
async fn load(&mut self) -> Result<Option<SkiplistEdgeMapping>> {
if tunables::tunables().get_skiplist_reload_disabled() {
if tunables::tunables()
.skiplist_reload_disabled()
.unwrap_or_default()
{
return Ok(None);
}
info!(self.ctx.logger(), "Fetching skiplist");
@ -509,9 +512,11 @@ impl SkiplistIndex {
ctx.clone(),
move || {
std::time::Duration::from_secs(
NonZeroI64::new(tunables.get_skiplist_reload_interval())
.and_then(|n| u64::try_from(n.get()).ok())
.unwrap_or(60 * 15),
NonZeroI64::new(
tunables.skiplist_reload_interval().unwrap_or_default(),
)
.and_then(|n| u64::try_from(n.get()).ok())
.unwrap_or(60 * 15),
)
},
loader,
@ -870,7 +875,9 @@ async fn process_frontier(
max_gen: Generation,
trace: &Option<&SkiplistTraversalTrace>,
) -> Result<NodeFrontier, Error> {
let max_skips_without_yield = tunables::tunables().get_skiplist_max_skips_without_yield();
let max_skips_without_yield = tunables::tunables()
.skiplist_max_skips_without_yield()
.unwrap_or_default();
let mut skips_without_yield = 0;
let mut node_frontier = node_frontier;

View File

@ -77,7 +77,7 @@ impl ChangesetsCommitGraphCompat {
css: Vec1<(ChangesetId, ChangesetParents)>,
) {
if !tunables()
.get_by_repo_enable_writing_to_new_commit_graph(&self.repo_name)
.by_repo_enable_writing_to_new_commit_graph(&self.repo_name)
.unwrap_or(false)
{
return;
@ -91,7 +91,9 @@ impl ChangesetsCommitGraphCompat {
scuba.add("changeset_count", css.len());
scuba.add("repo_name", self.repo_name.as_str());
let write_timeout = tunables().get_commit_graph_writes_timeout_ms() as u64;
let write_timeout = tunables()
.commit_graph_writes_timeout_ms()
.unwrap_or_default() as u64;
// We use add_recursive because some parents might be missing
// from the new commit graph.

View File

@ -81,8 +81,8 @@ pub trait RepoPermissionChecker: Send + Sync + 'static {
ctx: &CoreContext,
identities: &MononokeIdentitySet,
) -> bool {
let log = tunables().get_log_draft_acl_failures();
let enforce = tunables().get_enforce_draft_acl();
let log = tunables().log_draft_acl_failures().unwrap_or_default();
let enforce = tunables().enforce_draft_acl().unwrap_or_default();
if log || enforce {
let (draft_result, write_result) = join!(
self.check_if_draft_access_allowed(identities),

View File

@ -144,7 +144,8 @@ pub async fn create_getbundle_response(
create_hg_changeset_part(ctx, blobrepo, commits_to_send.clone(), lfs_params).await?;
parts.push(cg_part);
if !draft_commits.is_empty() && tunables().get_mutation_generate_for_draft() {
if !draft_commits.is_empty() && tunables().mutation_generate_for_draft().unwrap_or_default()
{
let mutations_fut = {
cloned!(ctx);
let hg_mutation_store = blobrepo.hg_mutation_store_arc();
@ -240,7 +241,9 @@ pub async fn find_commits_to_send(
let params = Params { heads, excludes };
let nodes_to_send = if !tunables().get_getbundle_use_low_gen_optimization()
let nodes_to_send = if !tunables()
.getbundle_use_low_gen_optimization()
.unwrap_or_default()
|| !low_gen_num_checker.is_low_gen_num(lowest_head_gen_num)
{
call_difference_of_union_of_ancestors_revset(

View File

@ -39,7 +39,9 @@ pub(crate) struct LowGenNumChecker {
impl LowGenNumChecker {
pub(crate) fn new_from_tunables(highest_gen_num: u64) -> Self {
let difference = tunables().get_getbundle_high_low_gen_num_difference_threshold();
let difference = tunables()
.getbundle_high_low_gen_num_difference_threshold()
.unwrap_or_default();
let low_gen_num_threshold = if difference > 0 {
let difference = difference as u64;
Some(highest_gen_num.saturating_sub(difference))
@ -125,7 +127,9 @@ pub(crate) async fn compute_partial_getbundle(
excludes: Vec<(ChangesetId, Generation)>,
low_gen_num_checker: &LowGenNumChecker,
) -> Result<PartialGetBundle, Error> {
let traversal_limit = tunables().get_getbundle_partial_getbundle_traversal_limit();
let traversal_limit = tunables()
.getbundle_partial_getbundle_traversal_limit()
.unwrap_or_default();
if traversal_limit == 0 {
// This optimimization is disabled, just exit quickly
return Ok(PartialGetBundle::new_no_partial_result(heads, excludes));
@ -246,7 +250,9 @@ pub(crate) async fn low_gen_num_optimization(
high_gens_params,
} = split_params;
let limit = tunables().get_getbundle_low_gen_optimization_max_traversal_limit();
let limit = tunables()
.getbundle_low_gen_optimization_max_traversal_limit()
.unwrap_or_default();
let limit = if limit <= 0 {
DEFAULT_TRAVERSAL_LIMIT
} else {

View File

@ -240,7 +240,9 @@ pub fn get_unordered_file_history_for_multiple_nodes(
allow_short_getpack_history: bool,
) -> impl Stream<Item = HgFileHistoryEntry, Error = Error> {
let limit = if allow_short_getpack_history {
let limit = tunables::tunables().get_remotefilelog_file_history_limit();
let limit = tunables::tunables()
.remotefilelog_file_history_limit()
.unwrap_or_default();
if limit <= 0 { None } else { Some(limit as u64) }
} else {
None

View File

@ -269,7 +269,9 @@ lazy_static! {
}
fn clone_timeout() -> Duration {
let timeout = tunables().get_repo_client_clone_timeout_secs();
let timeout = tunables()
.repo_client_clone_timeout_secs()
.unwrap_or_default();
if timeout > 0 {
Duration::from_secs(timeout as u64)
} else {
@ -278,7 +280,9 @@ fn clone_timeout() -> Duration {
}
fn default_timeout() -> Duration {
let timeout = tunables().get_repo_client_default_timeout_secs();
let timeout = tunables()
.repo_client_default_timeout_secs()
.unwrap_or_default();
if timeout > 0 {
Duration::from_secs(timeout as u64)
} else {
@ -286,7 +290,9 @@ fn default_timeout() -> Duration {
}
}
fn getbundle_timeout() -> Duration {
let timeout = tunables().get_repo_client_getbundle_timeout_secs();
let timeout = tunables()
.repo_client_getbundle_timeout_secs()
.unwrap_or_default();
if timeout > 0 {
Duration::from_secs(timeout as u64)
} else {
@ -295,7 +301,9 @@ fn getbundle_timeout() -> Duration {
}
fn getpack_timeout() -> Duration {
let timeout = tunables().get_repo_client_getpack_timeout_secs();
let timeout = tunables()
.repo_client_getpack_timeout_secs()
.unwrap_or_default();
if timeout > 0 {
Duration::from_secs(timeout as u64)
} else {
@ -340,7 +348,10 @@ fn bundle2caps() -> String {
("listkeys", vec![]),
];
if tunables().get_mutation_advertise_for_infinitepush() {
if tunables()
.mutation_advertise_for_infinitepush()
.unwrap_or_default()
{
caps.push(("b2x:infinitepushmutation", vec![]));
}
@ -372,20 +383,37 @@ struct UndesiredPathLogger {
impl UndesiredPathLogger {
fn new(ctx: CoreContext, repo: &BlobRepo) -> Result<Self, Error> {
let tunables = tunables();
let repo_needs_logging =
repo.repo_identity().name() == tunables.get_undesired_path_repo_name_to_log().as_str();
let repo_needs_logging = repo.repo_identity().name()
== tunables
.undesired_path_repo_name_to_log()
.unwrap_or_default()
.as_str();
let path_prefix_to_log = if repo_needs_logging {
MPath::new_opt(tunables.get_undesired_path_prefix_to_log().as_str())?
MPath::new_opt(
tunables
.undesired_path_prefix_to_log()
.unwrap_or_default()
.as_str(),
)?
} else {
None
};
let path_regex_to_log = if repo_needs_logging
&& !tunables.get_undesired_path_regex_to_log().is_empty()
&& !tunables
.undesired_path_regex_to_log()
.unwrap_or_default()
.is_empty()
{
Some(
Regex::new(tunables.get_undesired_path_regex_to_log().as_str()).map_err(|e| {
Regex::new(
tunables
.undesired_path_regex_to_log()
.unwrap_or_default()
.as_str(),
)
.map_err(|e| {
error!(
ctx.logger(),
"Error initializing undesired path regex for {}: {}",
@ -663,7 +691,8 @@ impl RepoClient {
ctx: CoreContext,
params: GettreepackArgs,
) -> BoxStream<BytesOld, Error> {
let hash_validation_percentage = tunables().get_hash_validation_percentage();
let hash_validation_percentage =
tunables().hash_validation_percentage().unwrap_or_default();
let validate_hash = ((rand::random::<usize>() % 100) as i64) < hash_validation_percentage;
let undesired_path_logger =
@ -732,7 +761,8 @@ impl RepoClient {
let lfs_params = self.lfs_params();
let hash_validation_percentage = tunables().get_hash_validation_percentage();
let hash_validation_percentage =
tunables().hash_validation_percentage().unwrap_or_default();
let validate_hash =
rand::thread_rng().gen_ratio(hash_validation_percentage as u32, 100);
let getpack_buffer_size = 500;
@ -1074,7 +1104,8 @@ impl RepoClient {
cloned!(ctx);
async move {
let max_nodes = tunables()
.get_repo_client_max_nodes_in_known_method()
.repo_client_max_nodes_in_known_method()
.unwrap_or_default()
.try_into()
.unwrap();
if max_nodes > 0 {
@ -2499,7 +2530,11 @@ fn with_command_monitor<T>(ctx: CoreContext, t: T) -> Monitor<T, Sender<()>> {
let start = Instant::now();
loop {
let interval = match tunables().get_command_monitor_interval().try_into() {
let interval = match tunables()
.command_monitor_interval()
.unwrap_or_default()
.try_into()
{
Ok(interval) if interval > 0 => interval,
_ => {
break;
@ -2508,7 +2543,11 @@ fn with_command_monitor<T>(ctx: CoreContext, t: T) -> Monitor<T, Sender<()>> {
tokio::time::sleep(Duration::from_secs(interval)).await;
if tunables().get_command_monitor_remote_logging() != 0 {
if tunables()
.command_monitor_remote_logging()
.unwrap_or_default()
!= 0
{
info!(
ctx.logger(),
"Command in progress. Elapsed: {}s, BlobPuts: {}, BlobGets: {}, SqlWrites: {}, SqlReadsMaster: {}, SqlReadsReplica: {}.",

View File

@ -70,7 +70,9 @@ impl BookmarkCacheRepo for Arc<Repo> {
}
fn bookmarks_timeout() -> Duration {
let timeout = tunables().get_repo_client_bookmarks_timeout_secs();
let timeout = tunables()
.repo_client_bookmarks_timeout_secs()
.unwrap_or_default();
if timeout > 0 {
Duration::from_secs(timeout as u64)
} else {
@ -248,7 +250,10 @@ where
fn get_warm_bookmark_cache(&self) -> Option<&Arc<dyn BookmarksCache + Send + Sync>> {
if self.repo.repo_client_use_warm_bookmarks_cache() {
if !tunables().get_disable_repo_client_warm_bookmarks_cache() {
if !tunables()
.disable_repo_client_warm_bookmarks_cache()
.unwrap_or_default()
{
return Some(self.repo.warm_bookmarks_cache());
}
}

View File

@ -167,7 +167,10 @@ async fn run_push(
hook_rejection_remapper,
} = action;
if tunables().get_mutation_accept_for_infinitepush() {
if tunables()
.mutation_accept_for_infinitepush()
.unwrap_or_default()
{
repo.hg_mutation_store()
.add_entries(ctx, uploaded_hg_changeset_ids, mutations)
.await
@ -247,7 +250,10 @@ async fn run_infinitepush(
uploaded_hg_changeset_ids,
} = action;
if tunables().get_mutation_accept_for_infinitepush() {
if tunables()
.mutation_accept_for_infinitepush()
.unwrap_or_default()
{
repo.hg_mutation_store()
.add_entries(ctx, uploaded_hg_changeset_ids, mutations)
.await
@ -501,7 +507,7 @@ async fn normal_pushrebase<'a>(
cross_repo_push_source: CrossRepoPushSource,
) -> Result<(ChangesetId, Vec<pushrebase::PushrebaseChangesetPair>), BundleResolverError> {
let bookmark_restriction = BookmarkKindRestrictions::OnlyPublishing;
let remote_mode = if tunables().get_force_local_pushrebase() {
let remote_mode = if tunables().force_local_pushrebase().unwrap_or_default() {
PushrebaseRemoteMode::Local
} else {
repo.repo_config().pushrebase.remote_mode.clone()
@ -640,7 +646,11 @@ async fn plain_push_bookmark(
.with_new_changesets(new_changesets)
.with_pushvars(maybe_pushvars)
.with_push_source(cross_repo_push_source)
.only_log_acl_checks(tunables().get_log_only_wireproto_write_acl())
.only_log_acl_checks(
tunables()
.log_only_wireproto_write_acl()
.unwrap_or_default(),
)
.run(
ctx,
&AuthorizationContext::new(ctx),
@ -684,7 +694,11 @@ async fn plain_push_bookmark(
.with_new_changesets(new_changesets)
.with_pushvars(maybe_pushvars)
.with_push_source(cross_repo_push_source)
.only_log_acl_checks(tunables().get_log_only_wireproto_write_acl())
.only_log_acl_checks(
tunables()
.log_only_wireproto_write_acl()
.unwrap_or_default(),
)
.run(
ctx,
&AuthorizationContext::new(ctx),
@ -721,7 +735,11 @@ async fn plain_push_bookmark(
bookmarks_movement::DeleteBookmarkOp::new(&bookmark_push.name, old_target, reason)
.only_if_public()
.with_pushvars(maybe_pushvars)
.only_log_acl_checks(tunables().get_log_only_wireproto_write_acl())
.only_log_acl_checks(
tunables()
.log_only_wireproto_write_acl()
.unwrap_or_default(),
)
.run(ctx, &AuthorizationContext::new(ctx), repo)
.await
.context("Failed to delete bookmark")?;
@ -748,7 +766,11 @@ async fn infinitepush_scratch_bookmark(
)
.only_if_scratch()
.with_push_source(cross_repo_push_source)
.only_log_acl_checks(tunables().get_log_only_wireproto_write_acl())
.only_log_acl_checks(
tunables()
.log_only_wireproto_write_acl()
.unwrap_or_default(),
)
.run(
ctx,
&AuthorizationContext::new(ctx),
@ -780,7 +802,11 @@ async fn infinitepush_scratch_bookmark(
)
.only_if_scratch()
.with_push_source(cross_repo_push_source)
.only_log_acl_checks(tunables().get_log_only_wireproto_write_acl())
.only_log_acl_checks(
tunables()
.log_only_wireproto_write_acl()
.unwrap_or_default(),
)
.run(
ctx,
&AuthorizationContext::new(ctx),

View File

@ -965,7 +965,9 @@ impl<'r> Bundle2Resolver<'r> {
.try_collect()
.await?;
let commit_limit = tunables().get_unbundle_limit_num_of_commits_in_push();
let commit_limit = tunables()
.unbundle_limit_num_of_commits_in_push()
.unwrap_or_default();
// Ignore commit limit if hg sync job is pushing. Hg sync job is used
// to mirror one repository into another, and we can't discard a push
// even if it's too big
@ -981,7 +983,9 @@ impl<'r> Bundle2Resolver<'r> {
}
let changesets = if is_infinitepush
&& tunables().get_filter_pre_existing_commits_on_infinitepush()
&& tunables()
.filter_pre_existing_commits_on_infinitepush()
.unwrap_or_default()
{
let hg_cs_ids = changesets.iter().map(|(id, _)| *id).collect::<Vec<_>>();
@ -1026,7 +1030,9 @@ impl<'r> Bundle2Resolver<'r> {
let mut ctx = self.ctx.clone();
if is_infinitepush
&& tunables::tunables().get_commit_cloud_use_background_session_class()
&& tunables::tunables()
.commit_cloud_use_background_session_class()
.unwrap_or_default()
{
ctx.session_mut()
.override_session_class(SessionClass::BackgroundUnlessTooSlow);

View File

@ -126,7 +126,9 @@ impl NewBlobs {
}
};
let buffer_size = tunables::tunables().get_repo_client_concurrent_blob_uploads();
let buffer_size = tunables::tunables()
.repo_client_concurrent_blob_uploads()
.unwrap_or_default();
let s = if buffer_size <= 0 {
entries
.into_iter()

View File

@ -444,7 +444,7 @@ impl RepoFactory {
) -> Result<Arc<RedactedBlobs>> {
self.redacted_blobs
.get_or_try_init(db_config, || async move {
let redacted_blobs = if tunables().get_redaction_config_from_xdb() {
let redacted_blobs = if tunables().redaction_config_from_xdb().unwrap_or_default() {
let redacted_content_store =
self.open::<SqlRedactedContentStore>(db_config).await?;
// Fetch redacted blobs in a separate task so that slow polls
@ -1494,7 +1494,8 @@ impl RepoFactory {
const KEY_PREFIX: &str = "scm.mononoke.sql";
const MC_CODEVER: u32 = 0;
let sitever: u32 = tunables()
.get_sql_memcache_sitever()
.sql_memcache_sitever()
.unwrap_or_default()
.try_into()
.unwrap_or(0);
Some(sql_query_config::CachingConfig {

View File

@ -175,9 +175,13 @@ impl SourceControlServiceImpl {
}
let sampling_rate = core::num::NonZeroU64::new(if POPULAR_METHODS.contains(name) {
tunables().get_scs_popular_methods_sampling_rate() as u64
tunables()
.scs_popular_methods_sampling_rate()
.unwrap_or_default() as u64
} else {
tunables().get_scs_other_methods_sampling_rate() as u64
tunables()
.scs_other_methods_sampling_rate()
.unwrap_or_default() as u64
});
if let Some(sampling_rate) = sampling_rate {
scuba.sampled(sampling_rate);
@ -288,9 +292,11 @@ impl SourceControlServiceImpl {
let metadata = self.create_metadata(req_ctxt).await?;
let session = SessionContainer::builder(self.fb)
.metadata(Arc::new(metadata))
.blobstore_maybe_read_qps_limiter(tunables().get_scs_request_read_qps())
.blobstore_maybe_read_qps_limiter(tunables().scs_request_read_qps().unwrap_or_default())
.await
.blobstore_maybe_write_qps_limiter(tunables().get_scs_request_write_qps())
.blobstore_maybe_write_qps_limiter(
tunables().scs_request_write_qps().unwrap_or_default(),
)
.await
.build();
Ok(session)
@ -570,7 +576,7 @@ fn log_result<T: AddScubaResponse>(
scuba.add_future_stats(stats);
scuba.add("status", status);
if let Some(error) = error {
if !tunables().get_scs_error_log_sampling() {
if !tunables().scs_error_log_sampling().unwrap_or_default() {
scuba.unsampled();
}
scuba.add("error", error.as_str());

View File

@ -112,7 +112,9 @@ impl IdMap for IdMapMemWrites {
if res.is_ok() {
let new_size = self.mem.len();
let old_size = new_size - mappings_size;
let sampling_rate = tunables().get_segmented_changelog_idmap_log_sampling_rate();
let sampling_rate = tunables()
.segmented_changelog_idmap_log_sampling_rate()
.unwrap_or_default();
let sampling_rate = if sampling_rate <= 0 {
DEFAULT_LOG_SAMPLING_RATE
} else {

View File

@ -259,8 +259,9 @@ impl OnDemandUpdateSegmentedChangelog {
) -> Result<bool> {
let changeset_fetcher = self.changeset_fetcher.clone();
let id_map = self.namedag.read().await.map().clone_idmap();
let max_commits =
tunables::tunables().get_segmented_changelog_client_max_commits_to_traverse();
let max_commits = tunables::tunables()
.segmented_changelog_client_max_commits_to_traverse()
.unwrap_or_default();
for cs_id in heads {
let ancestors =
AncestorsNodeStream::new(ctx.clone(), &changeset_fetcher, *cs_id).compat();

View File

@ -69,10 +69,11 @@ impl PeriodicReloadSegmentedChangelog {
// This is a future to trigger force reload of segmented changelog
let fut = async move {
let mut force_reload_val =
tunables().get_by_repo_segmented_changelog_force_reload(&name);
let mut force_reload_val = tunables().by_repo_segmented_changelog_force_reload(&name);
loop {
let mut jitter = tunables().get_segmented_changelog_force_reload_jitter_secs();
let mut jitter = tunables()
.segmented_changelog_force_reload_jitter_secs()
.unwrap_or_default();
if jitter <= 0 {
jitter = 30;
}
@ -82,7 +83,7 @@ impl PeriodicReloadSegmentedChangelog {
tokio::time::sleep(jitter).await;
let new_force_reload_val =
tunables().get_by_repo_segmented_changelog_force_reload(&name);
tunables().by_repo_segmented_changelog_force_reload(&name);
if force_reload_val != new_force_reload_val {
info!(ctx_clone.logger(), "force reloading segmented changelog");
force_reload_notify_clone.notify_waiters();

View File

@ -374,8 +374,9 @@ impl SegmentedChangelogTailer {
.fetch_bounded(ctx, Direction::NewestFirst, Some(repo_bounds))
.map(|res| {
counter += 1;
let sampling_rate =
tunables().get_segmented_changelog_tailer_log_sampling_rate();
let sampling_rate = tunables()
.segmented_changelog_tailer_log_sampling_rate()
.unwrap_or_default();
let sampling_rate = if sampling_rate <= 0 {
DEFAULT_LOG_SAMPLING_RATE
} else {

View File

@ -236,7 +236,8 @@ where
.map_err(HttpError::BadRequest)?;
let zstd_level: i32 = tunables::tunables()
.get_zstd_compression_level()
.zstd_compression_level()
.unwrap_or_default()
.try_into()
.unwrap_or_default();
let compression = match req.headers().get(HEADER_CLIENT_COMPRESSION) {
@ -356,7 +357,10 @@ where
pq: http::uri::PathAndQuery,
body: Body,
) -> Result<Response<Body>, HttpError> {
if tunables().get_disable_http_service_edenapi() {
if tunables()
.disable_http_service_edenapi()
.unwrap_or_default()
{
let res = Response::builder()
.status(http::StatusCode::SERVICE_UNAVAILABLE)
.body("EdenAPI service is killswitched".into())

View File

@ -8,14 +8,13 @@
use std::cell::RefCell;
use std::collections::HashMap;
use std::ops::Deref;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::AtomicI64;
use std::sync::Arc;
use std::thread_local;
use std::time::Duration;
use anyhow::Result;
use arc_swap::ArcSwap;
use arc_swap::ArcSwapOption;
use cached_config::ConfigHandle;
use futures::future::poll_fn;
use futures::Future;
@ -65,9 +64,12 @@ pub fn tunables() -> TunablesReference {
})
}
// This type exists to simplify code generation in tunables-derive
pub type TunableString = ArcSwap<String>;
pub type TunableVecOfStrings = ArcSwap<Vec<String>>;
// These types exist to simplify code generation in tunables-derive
pub type TunableBool = ArcSwapOption<bool>;
pub type TunableI64 = ArcSwapOption<i64>;
pub type TunableString = ArcSwapOption<String>;
pub type TunableVecOfStrings = ArcSwapOption<Vec<String>>;
pub type TunableBoolByRepo = ArcSwap<HashMap<String, bool>>;
pub type TunableStringByRepo = ArcSwap<HashMap<String, String>>;
@ -76,229 +78,229 @@ pub type TunableI64ByRepo = ArcSwap<HashMap<String, i64>>;
#[derive(Tunables, Default, Debug)]
pub struct MononokeTunables {
mutation_advertise_for_infinitepush: AtomicBool,
mutation_accept_for_infinitepush: AtomicBool,
mutation_generate_for_draft: AtomicBool,
warm_bookmark_cache_poll_interval_ms: AtomicI64,
mutation_advertise_for_infinitepush: TunableBool,
mutation_accept_for_infinitepush: TunableBool,
mutation_generate_for_draft: TunableBool,
warm_bookmark_cache_poll_interval_ms: TunableI64,
/// Don't read from the BookmarksSubscription when updating the WBC, and instead poll for the
/// entire list of bookmarks on every iteration.
warm_bookmark_cache_disable_subscription: AtomicBool,
warm_bookmark_cache_disable_subscription: TunableBool,
/// Maximum age of bookmarks subscriptions.
bookmark_subscription_max_age_ms: AtomicI64,
bookmark_subscription_protect_master: AtomicBool,
max_scuba_msg_length: AtomicI64,
wishlist_read_qps: AtomicI64,
wishlist_write_qps: AtomicI64,
edenapi_req_dumper_sample_ratio: AtomicI64,
command_monitor_interval: AtomicI64,
command_monitor_remote_logging: AtomicI64,
bookmark_subscription_max_age_ms: TunableI64,
bookmark_subscription_protect_master: TunableBool,
max_scuba_msg_length: TunableI64,
wishlist_read_qps: TunableI64,
wishlist_write_qps: TunableI64,
edenapi_req_dumper_sample_ratio: TunableI64,
command_monitor_interval: TunableI64,
command_monitor_remote_logging: TunableI64,
// Log all getfiles/gettreepack requests for paths that start with prefix
// in a particular repo
undesired_path_repo_name_to_log: TunableString,
undesired_path_prefix_to_log: TunableString,
undesired_path_regex_to_log: TunableString,
pushrebase_disable_rebased_commit_validation: AtomicBool,
filenodes_disabled: AtomicBool,
filenodes_master_fallback_ratio: AtomicI64,
pushrebase_disable_rebased_commit_validation: TunableBool,
filenodes_disabled: TunableBool,
filenodes_master_fallback_ratio: TunableI64,
// Skiplist config
skiplist_max_skips_without_yield: AtomicI64,
skiplist_reload_disabled: AtomicBool,
skiplist_reload_interval: AtomicI64,
deduplicated_put_sampling_rate: AtomicI64,
disable_repo_client_warm_bookmarks_cache: AtomicBool,
remotefilelog_file_history_limit: AtomicI64,
disable_hooks_on_plain_push: AtomicBool,
run_hooks_on_additional_changesets: AtomicBool,
hooks_additional_changesets_limit: AtomicI64,
skiplist_max_skips_without_yield: TunableI64,
skiplist_reload_disabled: TunableBool,
skiplist_reload_interval: TunableI64,
deduplicated_put_sampling_rate: TunableI64,
disable_repo_client_warm_bookmarks_cache: TunableBool,
remotefilelog_file_history_limit: TunableI64,
disable_hooks_on_plain_push: TunableBool,
run_hooks_on_additional_changesets: TunableBool,
hooks_additional_changesets_limit: TunableI64,
// SCS scuba sampling knobs
scs_popular_methods_sampling_rate: AtomicI64,
scs_other_methods_sampling_rate: AtomicI64,
scs_popular_methods_sampling_rate: TunableI64,
scs_other_methods_sampling_rate: TunableI64,
// When false error logs are never sampled
scs_error_log_sampling: AtomicBool,
redacted_logging_sampling_rate: AtomicI64,
redaction_config_from_xdb: AtomicBool,
getbundle_use_low_gen_optimization: AtomicBool,
getbundle_high_low_gen_num_difference_threshold: AtomicI64,
getbundle_low_gen_optimization_max_traversal_limit: AtomicI64,
getbundle_partial_getbundle_traversal_limit: AtomicI64,
repo_client_bookmarks_timeout_secs: AtomicI64,
repo_client_clone_timeout_secs: AtomicI64,
repo_client_default_timeout_secs: AtomicI64,
repo_client_getbundle_timeout_secs: AtomicI64,
repo_client_getpack_timeout_secs: AtomicI64,
repo_client_concurrent_blob_uploads: AtomicI64,
repo_client_max_nodes_in_known_method: AtomicI64,
scs_error_log_sampling: TunableBool,
redacted_logging_sampling_rate: TunableI64,
redaction_config_from_xdb: TunableBool,
getbundle_use_low_gen_optimization: TunableBool,
getbundle_high_low_gen_num_difference_threshold: TunableI64,
getbundle_low_gen_optimization_max_traversal_limit: TunableI64,
getbundle_partial_getbundle_traversal_limit: TunableI64,
repo_client_bookmarks_timeout_secs: TunableI64,
repo_client_clone_timeout_secs: TunableI64,
repo_client_default_timeout_secs: TunableI64,
repo_client_getbundle_timeout_secs: TunableI64,
repo_client_getpack_timeout_secs: TunableI64,
repo_client_concurrent_blob_uploads: TunableI64,
repo_client_max_nodes_in_known_method: TunableI64,
// How many trees is getting prepared at once
repo_client_gettreepack_buffer_size: AtomicI64,
derived_data_slow_derivation_threshold_secs: AtomicI64,
disable_running_hooks_in_pushredirected_repo: AtomicBool,
scs_request_read_qps: AtomicI64,
scs_request_write_qps: AtomicI64,
enable_logging_commit_rewrite_data: AtomicBool,
repo_client_gettreepack_buffer_size: TunableI64,
derived_data_slow_derivation_threshold_secs: TunableI64,
disable_running_hooks_in_pushredirected_repo: TunableBool,
scs_request_read_qps: TunableI64,
scs_request_write_qps: TunableI64,
enable_logging_commit_rewrite_data: TunableBool,
// All blobstore read request with size bigger than
// this threshold will be logged to scuba
blobstore_read_size_logging_threshold: AtomicI64,
hash_validation_percentage: AtomicI64,
blobstore_read_size_logging_threshold: TunableI64,
hash_validation_percentage: TunableI64,
// Filter out commits that we already have in infinitepush. Shouldn't be needed if we have a
// client exchanging commits with us, but when processing bundled uploads (i.e. commit cloud
// filling), it might help a lot.
filter_pre_existing_commits_on_infinitepush: AtomicBool,
backfill_read_qps: AtomicI64,
backfill_write_qps: AtomicI64,
disable_commit_scribe_logging_scs: AtomicBool,
xrepo_sync_disable_all_syncs: AtomicBool,
xrepo_disable_commit_sync_lease: AtomicBool,
filter_pre_existing_commits_on_infinitepush: TunableBool,
backfill_read_qps: TunableI64,
backfill_write_qps: TunableI64,
disable_commit_scribe_logging_scs: TunableBool,
xrepo_sync_disable_all_syncs: TunableBool,
xrepo_disable_commit_sync_lease: TunableBool,
// Use Background session class while deriving data. This makes derived data not write
// data to blobstore sync queue if a write was successful to the main blobstore.
derived_data_use_background_session_class: TunableBoolByRepo,
commit_cloud_use_background_session_class: AtomicBool,
multiplex_blobstore_background_session_timeout_ms: AtomicI64,
commit_cloud_use_background_session_class: TunableBool,
multiplex_blobstore_background_session_timeout_ms: TunableI64,
allow_change_xrepo_mapping_extra: AtomicBool,
allow_change_xrepo_mapping_extra: TunableBool,
// Disable EdenAPI in http_service.
disable_http_service_edenapi: AtomicBool,
disable_http_service_edenapi: TunableBool,
// Disable putting hydrating manifests in .hg
disable_hydrating_manifests_in_dot_hg: AtomicBool,
disable_hydrating_manifests_in_dot_hg: TunableBool,
// Rendez vous configuration.
rendezvous_dispatch_delay_ms: AtomicI64,
rendezvous_dispatch_max_threshold: AtomicI64,
rendezvous_dispatch_delay_ms: TunableI64,
rendezvous_dispatch_max_threshold: TunableI64,
unbundle_limit_num_of_commits_in_push: AtomicI64,
unbundle_limit_num_of_commits_in_push: TunableI64,
// Maximium negative caching age of a blob, in milliseconds
// Negative means to not use weak consistency at all
manifold_weak_consistency_max_age_ms: AtomicI64,
manifold_weak_consistency_max_age_ms: TunableI64,
// -1: No override, use manifold server side config and rollout checks
// if set to > -1, set the client side option to override (see manifoldblob code)
manifold_request_priority_override: AtomicI64,
manifold_request_priority_override: TunableI64,
// Frequency at which to collect SQL connection pool stats
sql_connection_pool_stats_collection_interval_ms: AtomicI64,
sql_connection_pool_stats_collection_interval_ms: TunableI64,
bookmarks_cache_ttl_ms: AtomicI64,
bookmarks_cache_ttl_ms: TunableI64,
// Disable running SaveMappingPushrebaseHook on every Pushrebase
disable_save_mapping_pushrebase_hook: AtomicBool,
disable_save_mapping_pushrebase_hook: TunableBool,
// Set to 0 to disable compression
zstd_compression_level: AtomicI64,
zstd_compression_level: TunableI64,
// Commits that aren't related (i.e. that are not ancestors of each other)
// can be derived in parallel, and that's what derived data does.
// derived_data_parallel_derivation_buffer limits
// how many commits will be derived at once.
derived_data_parallel_derivation_buffer: AtomicI64,
derived_data_parallel_derivation_buffer: TunableI64,
// Tunables to disable derived data derivation either for the full repo
// or for specific derived data types inside a repo
all_derived_data_disabled: TunableBoolByRepo,
derived_data_types_disabled: TunableVecOfStringsByRepo,
// How often to check if derived data is disabled or not
derived_data_disabled_watcher_delay_secs: AtomicI64,
derived_data_disabled_watcher_delay_secs: TunableI64,
// Stops deriving on derivation workers. Will not drain Derivation Queue
derived_data_disable_derivation_workers: AtomicBool,
derived_data_disable_derivation_workers: TunableBool,
// How long to wait before worker retries in case of an error
// or empty Derivation queue.
derivation_worker_sleep_duration: AtomicI64,
derivation_worker_sleep_duration: TunableI64,
// How long client should wait between polls of Derived data service
derivation_request_retry_delay: AtomicI64,
derivation_request_retry_delay: TunableI64,
// Sets the size of the batch for derivaiton.
derivation_batch_size: AtomicI64,
derivation_batch_size: TunableI64,
// Maximum time to wait for remote derivation request to finish in secs
// before falling back to local derivation
remote_derivation_fallback_timeout_secs: AtomicI64,
remote_derivation_fallback_timeout_secs: TunableI64,
// Timeout for derivation request on service.
dds_request_timeout: AtomicI64,
dds_request_timeout: TunableI64,
// Disable the parallel derivation for DM and default to serial
deleted_manifest_disable_new_parallel_derivation: AtomicBool,
deleted_manifest_disable_new_parallel_derivation: TunableBool,
// multiplexed blobstore is_present/get new semantics rollout
multiplex_blobstore_get_do_queue_lookup: AtomicBool,
multiplex_blobstore_is_present_do_queue_lookup: AtomicBool,
multiplex_blobstore_get_do_queue_lookup: TunableBool,
multiplex_blobstore_is_present_do_queue_lookup: TunableBool,
// Not in use.
// TODO(mitrandir): clean it up
fastlog_use_mutable_renames: TunableBoolByRepo,
// Disable mutable renames for fastlog in case they cause problems.
fastlog_disable_mutable_renames: TunableBoolByRepo,
megarepo_api_dont_set_file_mutable_renames: AtomicBool,
megarepo_api_dont_set_directory_mutable_renames: AtomicBool,
megarepo_api_dont_set_file_mutable_renames: TunableBool,
megarepo_api_dont_set_directory_mutable_renames: TunableBool,
force_unode_v2: AtomicBool,
fastlog_use_gen_num_traversal: AtomicBool,
force_unode_v2: TunableBool,
fastlog_use_gen_num_traversal: TunableBool,
// Changing the value of this tunable forces all mononoke instances
// to reload segmented changelog. One can also specify jitter (or use default)
segmented_changelog_force_reload: TunableI64ByRepo,
segmented_changelog_force_reload_jitter_secs: AtomicI64,
segmented_changelog_force_reload_jitter_secs: TunableI64,
// Override default progress logging sampling rate for segmented changelog parts
segmented_changelog_idmap_log_sampling_rate: AtomicI64,
segmented_changelog_tailer_log_sampling_rate: AtomicI64,
segmented_changelog_idmap_log_sampling_rate: TunableI64,
segmented_changelog_tailer_log_sampling_rate: TunableI64,
// How many commits to walk back from the client heads before failing to rebuild SC
segmented_changelog_client_max_commits_to_traverse: AtomicI64,
segmented_changelog_client_max_commits_to_traverse: TunableI64,
// Timeout for is_present call for multiplexed blobstore
is_present_timeout_ms: AtomicI64,
is_present_timeout_ms: TunableI64,
// What timeout to use when doing filenode lookup.
// Usually filenode lookup is used while generating hg changesets
filenode_lookup_timeout_ms: AtomicI64,
filenode_lookup_timeout_ms: TunableI64,
// Sampling ratio percentage for warm boomark cache.
warm_bookmark_cache_logging_sampling_pct: AtomicI64,
warm_bookmark_cache_logging_sampling_pct: TunableI64,
// Setting this tunable to a new non-zero value and restarting
// mononoke hosts will invalidate the cache
blobstore_memcache_sitever: AtomicI64,
blobstore_memcache_sitever: TunableI64,
// Setting this tunable to a new non-zero value and restarting
// mononoke hosts will invalidate the cache
sql_memcache_sitever: AtomicI64,
sql_memcache_sitever: TunableI64,
// Setting this tunable to a new non-zero value and restarting
// mononoke hosts will invalidate bonsai_hg_mapping cache
bonsai_hg_mapping_sitever: AtomicI64,
bonsai_hg_mapping_sitever: TunableI64,
// Setting this tunable to a new non-zero value will update the
// TTL for the mutation store cache
hg_mutation_store_caching_ttl_secs: AtomicI64,
hg_mutation_store_caching_ttl_secs: TunableI64,
// Setting this tunable to a new non-zero value and restarting
// mononoke hosts will invalidate hg mutation store cache
hg_mutation_store_sitever: AtomicI64,
hg_mutation_store_sitever: TunableI64,
// EdenAPI requests that take long than this get logged unsampled
edenapi_unsampled_duration_threshold_ms: AtomicI64,
edenapi_unsampled_duration_threshold_ms: TunableI64,
// Setting this tunable to a new non-zero value and restarting
// mononoke hosts will invalidate mutable renames cache
mutable_renames_sitever: AtomicI64,
mutable_renames_sitever: TunableI64,
// Setting this will enable hooks on pushrebase bookmark moves that were
// initiated by a service (for user-initiated moves we always run hooks).
// Most of them will run in no-op mode but some of them (namely,
// verify_integrity) will need to do some work like logging and this is
// why it may be useful to run them.
enable_hooks_on_service_pushrebase: AtomicBool,
enable_hooks_on_service_pushrebase: TunableBool,
// Control whether the BYPASS_READONLY pushvar is restricted by an ACL
enforce_bypass_readonly_acl: AtomicBool,
enforce_bypass_readonly_acl: TunableBool,
// Boolean to batch requests sent to Land Service
batching_to_land_service: AtomicBool,
batching_to_land_service: TunableBool,
// Which region writes should be done to, in order to minimise latency.
// This should align with underlying storage (SQL/Manifold) write regions.
@ -312,34 +314,34 @@ pub struct MononokeTunables {
sql_lag_monitoring_blocklist: TunableVecOfStrings,
// If set, the hook won't be created at all
disable_check_write_permissions_hook: AtomicBool,
disable_check_write_permissions_hook: TunableBool,
// If set, the check result will be discarded for user identities
log_only_for_users_in_cwp_hook: AtomicBool,
log_only_for_users_in_cwp_hook: TunableBool,
// If set, the check result will be discarded for service identities
log_only_for_services_in_cwp_hook: AtomicBool,
log_only_for_services_in_cwp_hook: TunableBool,
// If set, the wireproto implementation will only log the repo write ACL
// check result.
log_only_wireproto_write_acl: AtomicBool,
log_only_wireproto_write_acl: TunableBool,
// If set the `draft` ACL action will be checked and logged on draft access
// Unless `enforce_draft_acl` is set `read` action will still be used for
// granting access.
log_draft_acl_failures: AtomicBool,
log_draft_acl_failures: TunableBool,
// If set the `draft` ACL action will be used for `draft` access.
enforce_draft_acl: AtomicBool,
enforce_draft_acl: TunableBool,
// Force local pushrebase instead of talking to SCS or Land Service
force_local_pushrebase: AtomicBool,
force_local_pushrebase: TunableBool,
// Disable SCS pushredirecting commits landed on a small repo to a big one
disable_scs_pushredirect: AtomicBool,
disable_scs_pushredirect: TunableBool,
// Enable usage of basename_suffix_skeleton_manifest in commit_find_files
disable_basename_suffix_skeleton_manifest: AtomicBool,
disable_basename_suffix_skeleton_manifest: TunableBool,
// Enable using BSSM for suffix queries. Might be inneficient for broad suffixes (like .php)
enable_bssm_suffix_query: AtomicBool,
enable_bssm_suffix_query: TunableBool,
// List of targets in AOSP megarepo to apply squashing config overrides
megarepo_squashing_config_override_targets: TunableVecOfStringsByRepo,
@ -349,12 +351,12 @@ pub struct MononokeTunables {
megarepo_override_author_check: TunableBoolByRepo,
// Disable SQL queries being retried after admission control errors
disable_sql_auto_retries: AtomicBool,
disable_sql_auto_retries: TunableBool,
// Disable SQL queries being cached using `cacheable` keyword
disable_sql_auto_cache: AtomicBool,
disable_sql_auto_cache: TunableBool,
// Disable using rendezvous for batching WAL deletes.
// TODO: delete once it using WAL here shows to be stable
wal_disable_rendezvous_on_deletes: AtomicBool,
wal_disable_rendezvous_on_deletes: TunableBool,
// Enable derivation on service per repo
enable_remote_derivation: TunableBoolByRepo,
@ -365,13 +367,13 @@ pub struct MononokeTunables {
// commit_graph_edges and commit_graph_merge_parents tables)
enable_writing_to_new_commit_graph: TunableBoolByRepo,
// Timeout for writing to the new commit graph
commit_graph_writes_timeout_ms: AtomicI64,
commit_graph_writes_timeout_ms: TunableI64,
// Usage of new commit graph for speeding up server-side operations
new_commit_graph_is_ancestor_percentage: TunableI64ByRepo,
// Disable the fix to use isolation level read committed
disable_wal_read_committed: AtomicBool,
disable_wal_read_committed: TunableBool,
}
fn log_tunables(tunables: &TunablesStruct) -> String {
@ -523,23 +525,19 @@ pub fn override_tunables(new_tunables: Option<Arc<MononokeTunables>>) {
TUNABLES_OVERRIDE.with(|t| *t.borrow_mut() = new_tunables);
}
// Get a duration from tunable
// Or if tunable is 0 use a provided default value
/// Get a duration from a tunable or a provided default
/// value if the tunable is not set.
pub fn get_duration_from_tunable_or(
get_tunable: impl Fn(&MononokeTunables) -> i64,
get_tunable: impl Fn(&MononokeTunables) -> Option<i64>,
into_duration: impl Fn(u64) -> Duration,
default: u64,
) -> Duration {
let value = get_tunable(tunables().deref()) as u64;
// 0 is used as sentinel because we don't have a way to know if tunable wasn't set
// or was unset. It's hacky but acceptable for Duration.
into_duration(if value != 0 { value } else { default })
into_duration(get_tunable(tunables().deref()).map_or(default, |i| i as u64))
}
#[cfg(test)]
mod test {
use std::collections::HashMap;
use std::sync::atomic::AtomicBool;
use maplit::hashmap;
@ -547,8 +545,8 @@ mod test {
#[derive(Tunables, Default)]
struct TestTunables {
boolean: AtomicBool,
num: AtomicI64,
boolean: TunableBool,
num: TunableI64,
string: TunableString,
vecofstrings: TunableVecOfStrings,
@ -573,18 +571,18 @@ mod test {
#[test]
fn test_override_tunables() {
assert_eq!(tunables().get_wishlist_write_qps(), 0);
assert!(tunables().wishlist_write_qps().is_none());
let res = with_tunables(
MononokeTunables {
wishlist_write_qps: AtomicI64::new(2),
wishlist_write_qps: ArcSwapOption::from(Some(Arc::new(2))),
..MononokeTunables::default()
},
|| tunables().get_wishlist_write_qps(),
|| tunables().wishlist_write_qps().unwrap_or_default(),
);
assert_eq!(res, 2);
assert_eq!(tunables().get_wishlist_write_qps(), 0);
assert!(tunables().wishlist_write_qps().is_none());
}
#[test]
@ -605,9 +603,9 @@ mod test {
d.insert(s("boolean"), true);
let test = TestTunables::default();
assert!(!test.get_boolean());
assert!(test.boolean().is_none());
test.update_bools(&d);
assert!(test.get_boolean());
assert_eq!(test.boolean(), Some(true));
}
#[test]
@ -617,32 +615,32 @@ mod test {
d.insert(s("boolean"), true);
let test = TestTunables::default();
assert!(!test.get_boolean());
assert!(test.boolean().is_none());
test.update_bools(&d);
assert!(test.get_boolean());
assert_eq!(test.boolean(), Some(true));
test.update_bools(&hashmap! {});
assert!(!test.get_boolean());
assert!(test.boolean().is_none());
// ints
let test = TestTunables::default();
test.update_ints(&hashmap! { s("num") => 1});
assert_eq!(test.get_num(), 1);
assert_eq!(test.num(), Some(1));
test.update_ints(&hashmap! {});
assert_eq!(test.get_num(), 0);
assert_eq!(test.num(), None);
// strings
let test = TestTunables::default();
test.update_strings(&hashmap! { s("string") => s("string")});
assert_eq!(test.get_string(), Arc::new(s("string")));
assert_eq!(test.string(), Some(Arc::new(s("string"))));
test.update_strings(&hashmap! {});
assert_eq!(test.get_string(), Arc::new(s("")));
assert!(test.string().is_none());
// by repo bools
assert_eq!(test.get_by_repo_repobool("repo"), None);
assert_eq!(test.get_by_repo_repobool("repo2"), None);
assert_eq!(test.by_repo_repobool("repo"), None);
assert_eq!(test.by_repo_repobool("repo2"), None);
test.update_by_repo_bools(&hashmap! {
s("repo") => hashmap! {
@ -652,12 +650,12 @@ mod test {
s("repobool") => false,
}
});
assert_eq!(test.get_by_repo_repobool("repo"), Some(true));
assert_eq!(test.get_by_repo_repobool("repo2"), Some(false));
assert_eq!(test.by_repo_repobool("repo"), Some(true));
assert_eq!(test.by_repo_repobool("repo2"), Some(false));
test.update_by_repo_bools(&hashmap! {});
assert_eq!(test.get_by_repo_repobool("repo"), None);
assert_eq!(test.get_by_repo_repobool("repo2"), None);
assert_eq!(test.by_repo_repobool("repo"), None);
assert_eq!(test.by_repo_repobool("repo2"), None);
}
#[test]
@ -666,9 +664,9 @@ mod test {
d.insert(s("num"), 10);
let test = TestTunables::default();
assert_eq!(test.get_num(), 0);
assert!(test.num().is_none());
test.update_ints(&d);
assert_eq!(test.get_num(), 10);
assert_eq!(test.num(), Some(10));
}
#[test]
@ -677,9 +675,9 @@ mod test {
d.insert(s("missing"), 10);
let test = TestTunables::default();
assert_eq!(test.get_num(), 0);
assert!(test.num().is_none());
test.update_ints(&d);
assert_eq!(test.get_num(), 0);
assert!(test.num().is_none());
}
#[test]
@ -688,9 +686,9 @@ mod test {
d.insert(s("string"), s("value"));
let test = TestTunables::default();
assert_eq!(test.get_string().as_str(), "");
assert!(test.string().is_none());
test.update_strings(&d);
assert_eq!(test.get_string().as_str(), "value");
assert_eq!(test.string().unwrap().as_str(), "value");
}
#[test]
@ -699,10 +697,10 @@ mod test {
d.insert(s("vecofstrings"), vec![s("value"), s("value2")]);
let test = TestTunables::default();
assert!(&test.get_vecofstrings().is_empty());
assert!(&test.vecofstrings().is_none());
test.update_vec_of_strings(&d);
assert_eq!(
&test.get_vecofstrings().as_slice(),
&test.vecofstrings().unwrap().as_slice(),
&[s("value"), s("value2")]
);
}
@ -711,8 +709,8 @@ mod test {
fn update_by_repo_bool() {
let test = TestTunables::default();
assert_eq!(test.get_by_repo_repobool("repo"), None);
assert_eq!(test.get_by_repo_repobool("repo2"), None);
assert_eq!(test.by_repo_repobool("repo"), None);
assert_eq!(test.by_repo_repobool("repo2"), None);
test.update_by_repo_bools(&hashmap! {
s("repo") => hashmap! {
@ -722,29 +720,29 @@ mod test {
s("repobool") => true,
}
});
assert_eq!(test.get_by_repo_repobool("repo"), Some(true));
assert_eq!(test.get_by_repo_repobool("repo2"), Some(true));
assert_eq!(test.by_repo_repobool("repo"), Some(true));
assert_eq!(test.by_repo_repobool("repo2"), Some(true));
test.update_by_repo_bools(&hashmap! {
s("repo") => hashmap! {
s("repobool") => true,
}
});
assert_eq!(test.get_by_repo_repobool("repo2"), None);
assert_eq!(test.by_repo_repobool("repo2"), None);
test.update_by_repo_bools(&hashmap! {
s("repo") => hashmap! {
s("repobool") => false,
}
});
assert_eq!(test.get_by_repo_repobool("repo"), Some(false));
assert_eq!(test.by_repo_repobool("repo"), Some(false));
}
#[test]
fn update_by_repo_two_bools() {
let test = TestTunables::default();
assert_eq!(test.get_by_repo_repobool("repo"), None);
assert_eq!(test.get_by_repo_repobool2("repo"), None);
assert_eq!(test.by_repo_repobool("repo"), None);
assert_eq!(test.by_repo_repobool2("repo"), None);
test.update_by_repo_bools(&hashmap! {
s("repo") => hashmap! {
@ -753,8 +751,8 @@ mod test {
}
});
assert_eq!(test.get_by_repo_repobool("repo"), Some(true));
assert_eq!(test.get_by_repo_repobool2("repo"), Some(true));
assert_eq!(test.by_repo_repobool("repo"), Some(true));
assert_eq!(test.by_repo_repobool2("repo"), Some(true));
test.update_by_repo_bools(&hashmap! {
s("repo") => hashmap! {
@ -763,16 +761,16 @@ mod test {
}
});
assert_eq!(test.get_by_repo_repobool("repo"), Some(true));
assert_eq!(test.get_by_repo_repobool2("repo"), Some(false));
assert_eq!(test.by_repo_repobool("repo"), Some(true));
assert_eq!(test.by_repo_repobool2("repo"), Some(false));
}
#[test]
fn update_by_repo_str() {
let test = TestTunables::default();
assert_eq!(test.get_by_repo_repostr("repo"), None);
assert_eq!(test.get_by_repo_repostr("repo2"), None);
assert_eq!(test.by_repo_repostr("repo"), None);
assert_eq!(test.by_repo_repostr("repo2"), None);
test.update_by_repo_strings(&hashmap! {
s("repo") => hashmap! {
@ -782,23 +780,23 @@ mod test {
s("repostr") => s("world"),
},
});
assert_eq!(test.get_by_repo_repostr("repo"), Some(s("hello")));
assert_eq!(test.get_by_repo_repostr("repo2"), Some(s("world")));
assert_eq!(test.by_repo_repostr("repo"), Some(s("hello")));
assert_eq!(test.by_repo_repostr("repo2"), Some(s("world")));
test.update_by_repo_strings(&hashmap! {
s("repo") => hashmap! {
s("repostr") => s("hello2"),
},
});
assert_eq!(test.get_by_repo_repostr("repo"), Some(s("hello2")));
assert_eq!(test.get_by_repo_repostr("repo2"), None);
assert_eq!(test.by_repo_repostr("repo"), Some(s("hello2")));
assert_eq!(test.by_repo_repostr("repo2"), None);
}
#[test]
fn update_by_repo_two_strs() {
let test = TestTunables::default();
assert_eq!(test.get_by_repo_repostr("repo"), None);
assert_eq!(test.get_by_repo_repostr2("repo"), None);
assert_eq!(test.by_repo_repostr("repo"), None);
assert_eq!(test.by_repo_repostr2("repo"), None);
test.update_by_repo_strings(&hashmap! {
s("repo") => hashmap! {
@ -807,8 +805,8 @@ mod test {
}
});
assert_eq!(test.get_by_repo_repostr("repo"), Some(s("hello")));
assert_eq!(test.get_by_repo_repostr2("repo"), Some(s("world")));
assert_eq!(test.by_repo_repostr("repo"), Some(s("hello")));
assert_eq!(test.by_repo_repostr2("repo"), Some(s("world")));
test.update_by_repo_strings(&hashmap! {
s("repo") => hashmap! {
@ -816,16 +814,16 @@ mod test {
}
});
assert_eq!(test.get_by_repo_repostr("repo"), Some(s("hello2")));
assert_eq!(test.get_by_repo_repostr2("repo"), None);
assert_eq!(test.by_repo_repostr("repo"), Some(s("hello2")));
assert_eq!(test.by_repo_repostr2("repo"), None);
}
#[test]
fn update_by_repo_int() {
let test = TestTunables::default();
assert_eq!(test.get_by_repo_repoint("repo"), None);
assert_eq!(test.get_by_repo_repoint("repo2"), None);
assert_eq!(test.by_repo_repoint("repo"), None);
assert_eq!(test.by_repo_repoint("repo2"), None);
test.update_by_repo_ints(&hashmap! {
s("repo") => hashmap! {
@ -835,23 +833,23 @@ mod test {
s("repoint") => 2,
},
});
assert_eq!(test.get_by_repo_repoint("repo"), Some(1));
assert_eq!(test.get_by_repo_repoint("repo2"), Some(2));
assert_eq!(test.by_repo_repoint("repo"), Some(1));
assert_eq!(test.by_repo_repoint("repo2"), Some(2));
test.update_by_repo_ints(&hashmap! {
s("repo") => hashmap! {
s("repoint") => 3,
},
});
assert_eq!(test.get_by_repo_repoint("repo"), Some(3));
assert_eq!(test.get_by_repo_repoint("repo2"), None);
assert_eq!(test.by_repo_repoint("repo"), Some(3));
assert_eq!(test.by_repo_repoint("repo2"), None);
}
#[test]
fn update_by_repo_two_ints() {
let test = TestTunables::default();
assert_eq!(test.get_by_repo_repoint("repo"), None);
assert_eq!(test.get_by_repo_repoint2("repo"), None);
assert_eq!(test.by_repo_repoint("repo"), None);
assert_eq!(test.by_repo_repoint2("repo"), None);
test.update_by_repo_ints(&hashmap! {
s("repo") => hashmap! {
@ -860,8 +858,8 @@ mod test {
}
});
assert_eq!(test.get_by_repo_repoint("repo"), Some(1));
assert_eq!(test.get_by_repo_repoint2("repo"), Some(2));
assert_eq!(test.by_repo_repoint("repo"), Some(1));
assert_eq!(test.by_repo_repoint2("repo"), Some(2));
test.update_by_repo_ints(&hashmap! {
s("repo") => hashmap! {
@ -869,21 +867,21 @@ mod test {
}
});
assert_eq!(test.get_by_repo_repoint("repo"), Some(3));
assert_eq!(test.get_by_repo_repoint2("repo"), None);
assert_eq!(test.by_repo_repoint("repo"), Some(3));
assert_eq!(test.by_repo_repoint2("repo"), None);
}
#[test]
fn update_by_repo_vec_of_strings() {
let test = TestTunables::default();
assert_eq!(test.get_by_repo_repovecofstrings("repo"), None);
assert_eq!(test.by_repo_repovecofstrings("repo"), None);
test.update_by_repo_vec_of_strings(&hashmap! {
s("repo") => hashmap! {
s("unrelated") => vec![s("val1"), s("val2")],
}
});
assert_eq!(test.get_by_repo_repovecofstrings("repo"), None);
assert_eq!(test.by_repo_repovecofstrings("repo"), None);
test.update_by_repo_vec_of_strings(&hashmap! {
s("repo") => hashmap! {
@ -892,7 +890,7 @@ mod test {
});
assert_eq!(
test.get_by_repo_repovecofstrings("repo"),
test.by_repo_repovecofstrings("repo"),
Some(vec![s("val1"), s("val2")])
);
}
@ -901,10 +899,10 @@ mod test {
async fn test_with_tunables_async(_fb: fbinit::FacebookInit) {
let res = with_tunables_async(
MononokeTunables {
wishlist_write_qps: AtomicI64::new(2),
wishlist_write_qps: ArcSwapOption::from(Some(Arc::new(2))),
..MononokeTunables::default()
},
async { tunables().get_wishlist_write_qps() }.boxed(),
async { tunables().wishlist_write_qps().unwrap_or_default() }.boxed(),
)
.await;

View File

@ -62,10 +62,10 @@ impl TunableType {
Self::I64 => quote! { i64 },
Self::String => quote! { Arc<String> },
Self::VecOfStrings => quote! { Arc<Vec<String>> },
Self::ByRepoBool => quote! { Option<bool> },
Self::ByRepoString => quote! { Option<String> },
Self::ByRepoI64 => quote! { Option<i64> },
Self::ByRepoVecOfStrings => quote! { Option<Vec<String>> },
Self::ByRepoBool => quote! { bool },
Self::ByRepoString => quote! { String },
Self::ByRepoI64 => quote! { i64 },
Self::ByRepoVecOfStrings => quote! { Vec<String> },
}
}
@ -95,29 +95,27 @@ impl TunableType {
}
fn generate_getter_method(&self, name: Ident) -> TokenStream {
let method = quote::format_ident!("get_{}", name);
let by_repo_method = quote::format_ident!("get_by_repo_{}", name);
let external_type = self.external_type();
match &self {
Self::Bool | Self::I64 => {
quote! {
pub fn #method(&self) -> #external_type {
return self.#name.load(std::sync::atomic::Ordering::Relaxed)
pub fn #name(&self) -> Option<#external_type> {
self.#name.load_full().map(|arc_v| *arc_v)
}
}
}
Self::String | Self::VecOfStrings => {
quote! {
pub fn #method(&self) -> #external_type {
pub fn #name(&self) -> Option<#external_type> {
self.#name.load_full()
}
}
}
Self::ByRepoBool | Self::ByRepoI64 | Self::ByRepoString | Self::ByRepoVecOfStrings => {
let by_repo_method = quote::format_ident!("by_repo_{}", name);
quote! {
pub fn #by_repo_method(&self, repo: &str) -> #external_type {
pub fn #by_repo_method(&self, repo: &str) -> Option<#external_type> {
self.#name.load_full().get(repo).map(|val| (*val).clone())
}
}
@ -213,16 +211,15 @@ where
match ty {
TunableType::I64 | TunableType::Bool => {
body.extend(quote! {
#(self.#names.store(
tunables.get(stringify!(#names)).cloned().unwrap_or_default(),
std::sync::atomic::Ordering::Relaxed
);)*
#(
self.#names.swap(tunables.get(stringify!(#names)).map(|v| Arc::new(*v)));
)*
});
}
TunableType::String | TunableType::VecOfStrings => {
body.extend(quote! {
#(self.#names.swap(
Arc::new(tunables.get(stringify!(#names)).cloned().unwrap_or_default())
#(
self.#names.swap(tunables.get(stringify!(#names)).map(|v| Arc::new(v.clone()))
);)*
});
}
@ -279,8 +276,8 @@ fn resolve_type(ty: Type) -> TunableType {
if let Type::Path(p) = ty {
if let Some(ident) = p.path.get_ident() {
match &ident.to_string()[..] {
"AtomicBool" => return TunableType::Bool,
"AtomicI64" => return TunableType::I64,
"TunableBool" => return TunableType::Bool,
"TunableI64" => return TunableType::I64,
"TunableVecOfStrings" => return TunableType::VecOfStrings,
// TunableString is a type alias of ArcSwap<String>.
// p.path.get_ident() returns None for ArcSwap<String>