use crate::child_class::{ChildClass, class_of};
use crate::child_watch::StepBound;
use crate::transaction_git_request_and_reply_types::GitRequest;
use crate::transaction_git_step_rerun_and_end_rules::{is_side_ref_write, may_be_ended};
use crate::wait_ceilings::{OBJECT_STEP_CEILING, PLUMBING_STEP_CEILING};
use std::time::Duration;
pub(crate) fn step_bound(request: &GitRequest) -> StepBound {
#[cfg(test)]
let shortened: Option<Duration> = STEP_CEILING_FOR_THIS_THREAD.with(std::cell::Cell::get);
#[cfg(not(test))]
let shortened: Option<Duration> = None;
let class_ceiling: Duration = shortened.unwrap_or(match class_of(request.arguments.as_slice()) {
ChildClass::Plumbing => PLUMBING_STEP_CEILING,
ChildClass::Object => OBJECT_STEP_CEILING,
});
if may_be_ended(request) {
return StepBound::EndAt(class_ceiling);
}
if is_side_ref_write(request) {
return leave_running_bound(class_ceiling);
}
return not_ended_bound(class_ceiling);
}
fn leave_running_bound(class_ceiling: Duration) -> StepBound {
#[cfg(test)]
let extra: Duration = EXTRA_WAIT_FOR_THIS_THREAD.with(std::cell::Cell::get).unwrap_or(crate::wait_ceilings::SHORT_EXTRA_WAIT);
#[cfg(not(test))]
let extra: Duration = crate::wait_ceilings::SHORT_EXTRA_WAIT;
return StepBound::LeaveRunning { after: class_ceiling, extra };
}
fn not_ended_bound(class_ceiling: Duration) -> StepBound {
if crate::service_busy_step_record_on_this_thread::on_landing_thread() {
return StepBound::Unbounded;
}
return leave_running_bound(class_ceiling);
}
#[cfg(test)]
thread_local! {
pub(crate) static STEP_CEILING_FOR_THIS_THREAD: std::cell::Cell<Option<Duration>> = const { std::cell::Cell::new(None) };
pub(crate) static EXTRA_WAIT_FOR_THIS_THREAD: std::cell::Cell<Option<Duration>> = const { std::cell::Cell::new(None) };
}