-
Notifications
You must be signed in to change notification settings - Fork 653
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace chrono with near-create inside near-network #5175
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, given that what we want to do here is a "proper" mocked clock, I think it makes sense to try to avoid thread-locals, and use proper dependency injection. That is, to have two types: a clock (which returns time) and a time (which doesn't have a global now
associated function):
#[derive(Clone)]
pub struct Clock {
repr: ClockRepr,
}
#[derive(Clone)]
enum ClockRepr {
Real,
Mocked { now: Arc<AtomicU64> },
}
#[derive(Clone, Copy)]
pub struct Time {
inner: SystemTime,
}
impl Clock {
pub fn real_clock() -> Clock {
Clock { repr: ClockRepr::Real }
}
pub fn mocked_clock() -> (Clock, Arc<AtomicU64>) {
let now = Arc::new(AtomicU64::new(0));
let clock = Clock { repr: ClockRepr::Mocked { now: Arc::clone(&now) } };
(clock, now)
}
pub fn now(&self) -> Time {
let inner = match &self.repr {
ClockRepr::Real => SystemTime::now(),
ClockRepr::Mocked { now } => {
std::time::UNIX_EPOCH + Duration::from_nanos(now.load(Ordering::Relaxed))
}
};
Time { inner }
}
}
impl Time {
#[deprecated(
reason = "deliberately not implementing, use `now` method on the appropriate `Clock` instance."
)]
pub fn now() -> Time {
unimplemented!(
"deliberately not implementing, use `now` method on the appropriate `Clock` instance."
)
}
pub fn duration_since(&self, start: Time) -> Duration {
self.inner.duration_since(self.inner).unwrap_or_default()
}
}
I think this might be a way to slice the work between this PR and #5123. #5123 is the simplest, stupidest thing we can do to unblock fuzzing of whatever specific feature we want to fuzz, and this PR is the proper, long-term solution which would serve us until at least April 2262.
It depends on how we want to use time function. I see 2 options:
|
@matklad I see. I talked with @yordanmadzhunkov I'll close this PR for now. We need to first finish how we mock time, we will have to do this some other way later. |
refactor Co-authored-by: Aleksey Kladov <[email protected]>
As discussed with @matklad, we discussed implementing our of crate for time.
Currently we use 4 methods to represent time
chrono
(Utc::now()
) (Datetime<Utc>
) ,SystemTime
,Instant::now
,u64
, they all have their issues.chrono
library, it contains timezone information, we only care aboutUtc
timeInstant
is written in such a way, that it's not possible to convert it to unix timestamp. However, it's monotonic, which is good.SystemTime
works, but it's not monitonic. It's possible that if we measure time at timea
then at timeb
; the durationb-a
will be negative, causing our code to fail.XXX::now()
, which we can mock. Ideally, we would be able to ensure that ::now() is correct, by grepping code and checking that we seeNearClock::now()
in all places that time is used. This will make it easy to check that we use correct time anywhere.Duration
, so any duration such thata < b
, created bya - b
, will default to0
, if the difference were to become nagative. This will reduce chances of any crashed happening, when negative time is not expected.We are going to create our own wrapper around
SystemTime
andDuration
. This will allow us to do the mocking properly.Note:
If we decide to ship it, I'll split this PR into two parts:
near-clock
crate for mocking time - pt 1 #5177)See #5174