mirror of
https://github.com/facebook/sapling.git
synced 2024-10-05 14:28:17 +03:00
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:
parent
61d640517e
commit
0c5939f6a7
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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())
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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(());
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)?;
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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(" (...)");
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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?;
|
||||
|
@ -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,
|
||||
);
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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!(
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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>>();
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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(
|
||||
|
@ -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?
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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")?,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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(());
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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),
|
||||
|
@ -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(
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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: {}.",
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
@ -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 {
|
||||
|
@ -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());
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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())
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user