-
Notifications
You must be signed in to change notification settings - Fork 134
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
RUMM-1609 Use NTP server offset #607
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.
⚠️ Clock.sync
only notifies the first and last samples, so we are losing the intermediate offsets!
Is it true that previously (with using Clock.now
) we were receiving some initial approximation even before Clock.sync's
first {}
callback?
I'm wondering if we can cover this gap by using Clock.now
right after Clock.sync
:
func synchronize(with pool: ...) {
Clock.sync(
// ...
first: { publisher.publishAsync(...) } // first approximation
completion: { publisher.publishAsync(...) } // stable result
)
publisher.publishAsync(Clock.now - currentDeviceTime()) // ← this
}
Kronos seems to integrate with UserDefaults and stores the last-known NTP time in there. With this change we should read it back as soon as possible. This will be thread safe and will be as precise as before, no?
if let offset = offset { | ||
self.publisher.publishAsync(offset) | ||
} else if let now = now { | ||
self.publisher.publishAsync(now.timeIntervalSinceNow) |
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.
Is it possible to get now
but not offset
, or this is just a sanity fallback? In any case, it would be good to have inline comment on this, otherwise it seems unclear.
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.
Yes, my comment above is misplaced. This is indeed a fallback in case the last sample returns a nil
offset.
Th now
parameter is Clock.now
, so it is possible to have now
but not offset
.
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.
I've updated my comment, LMKWYT!
Yes, Kronos first loads the previous offset from the UserDefaults. Their interface is not public, but we can indeed do this workaround 👍 It is thread-safe since they load from the user defaults on the current thread, but they could change that behavior any time. |
d3d737a
to
5eae9a8
Compare
It's IMO fine 👍. Kronos now requires using |
Actually, their requirement should be to 'invoke |
What and why?
The Kronos
Clock.now
property is not thread safe and should always be invoked from the main thread, this change would have a large impact on our codebase. As an alternative, we can rely on the server time offset we get fromClock.sync
: TheClock.now
is in fact used byDateCorrector
to actually compute the server offset.Below a quick benchmark of the computed offset previously used and the server offset applied by this PR:
Fix #588
How?
The
ServerDateProvider
will now provide anoffset
time interval and its concrete implementationNTPServerDateProvider
will retrieve that value fromKronos.Clock.sync
.Clock.sync
callback is invoked on the main thread, so we are now using aValuePublisher
to safely access the server time offset.Clock.sync
only notifies the first and last samples, so we are losing the intermediate offsets!Review checklist