Skip to content
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

Replay time ordering #405

Merged
merged 28 commits into from
Dec 9, 2024
Merged

Replay time ordering #405

merged 28 commits into from
Dec 9, 2024

Conversation

lmeier
Copy link
Contributor

@lmeier lmeier commented Oct 21, 2024

We do 2 things here:

  • for all tracks we include the updatedAtMsDiff, which will be used to determine the location.updatedAt
  • we modify updatedAtMsDiff in RadarAPIHelper to update updatedAtMsDiff at request time, as updatedAtMsDiff is meant to represent the difference between the client request time and the timestamp of the location processed by the SDK. This is an important fix to locations being replayed as previously their updatedAtMsDiff was determined by their original (failed) request time — not actually the time at successful request.

@lmeier lmeier requested a review from KennyHuRadar October 21, 2024 19:20
@ShiCheng-Lu
Copy link
Contributor

I think on here we want to save the location's time (timeInMs) instead of the request time for the replay

@ShiCheng-Lu
Copy link
Contributor

ShiCheng-Lu commented Oct 25, 2024

I think on here we want to save the location's time (timeInMs) instead of the request time for the replay

nvm, this is not going to be used. Maybe we should get rid of the timestamps that will no longer be used to avoid future confusion. Because this doesn't need to be back-compatible with server, only server need to be back compatible with sdks.

long timeInMs = (long)(location.timestamp.timeIntervalSince1970 * 1000);
long timeInMs = (long)(location.timestamp.timeIntervalSince1970 * 1000);
RadarTrackingOptions *options = [Radar getTrackingOptions];
if (!foreground || options.replay != RadarTrackingOptionsReplayNone) {
params[@"updatedAtMsDiff"] = @(nowMs - timeInMs);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all track requests should have this updatedAtMsDiff, likely = 0 for normal tracks, but it'll keep our server code path consistent. We also don't need to set locationMs in the request as its not used, a bit of wasted bandwidth, we can send it at line:417 if the request fails.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can basically think that all tracks are replays, but some are replayed immediately.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We toss in the locationMs for updating the updatedAtMsDiff in RadarAPIHelper.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had initial hesitancy towards making all /tracks have updatedAtMsDiff, but yea, your model that they'd all have it matches mine. Might as well change that.

@lmeier lmeier marked this pull request as ready for review October 28, 2024 19:19
params[@"updatedAtMsDiff"] = @(nowMs - timeInMs);
long locationMs = (long)(location.timestamp.timeIntervalSince1970 * 1000);
RadarTrackingOptions *options = [Radar getTrackingOptions];
if (!verified || !foreground) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so verified background reqs will use updatedAtMsDiff, is that intended?
Are we intending to change how we treat foreground timestamps or holding off on that bc it's a bigger change not needed for the fix?

Would recommend updating the PR description with a high level description of the changes to make it easier to understand.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that's correct. Per slack conversation with Nick, the intention is to not change any timestamp logic for verified requests.

All non verified /tracks will now use updatedAtMsDiff, both foreground and background. There's no reason to hold off on making (non-verified) foreground requests use this logic -- in fact it's required for making sure that foreground requests slot in correctly in between background requests.

Ooo yea, good call out re: pr description -- just updated it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should the code be:

if (!verified) {

as is it doesn't match your comment. Unless I'm missing something

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do want background verified tracks to use the existing logic, i.e. if (!foreground) ...

So either if (!verified || !foreground) {

Does that make sense?

@tjulien
Copy link
Contributor

tjulien commented Nov 8, 2024

@lmeier what's the linear for this?

@lmeier
Copy link
Contributor Author

lmeier commented Nov 8, 2024

@@ -67,9 +67,38 @@ - (void)requestWithMethod:(NSString *)method
}

if (params) {
[req setHTTPBody:[NSJSONSerialization dataWithJSONObject:params options:0 error:NULL]];
if (!params[@"updatedAtMsDiff"] && !params[@"replays"]) {
Copy link
Contributor

@tjulien tjulien Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: it would be nice if iOS and Android had the same logic for this if case

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good callout, fixed: 1cd42d9

long timeInMs = (long)(location.timestamp.timeIntervalSince1970 * 1000);
params[@"updatedAtMsDiff"] = @(nowMs - timeInMs);
}
long locationMs = (long)(location.timestamp.timeIntervalSince1970 * 1000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok so I guess the approach now is:
• change foreground = true to also use updatedAtMsDiff (for consistency? I might have been the one to bring this up?)
• Don't special case verified = true on the client side, handle it differently on the server side

If we decided not to change foreground = true to updatedAtMsDiff, would the other changes to updatedAtMsDiff in these PRs be enough to fix the bug? Or is the inconsistent behavior between foreground = true and foreground = false causing a problem?

Copy link
Contributor Author

@lmeier lmeier Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

 change foreground = true to also use updatedAtMsDiff (for consistency? I might have been the one to bring this up?)

If we decided not to change foreground = true to updatedAtMsDiff, would the other changes to updatedAtMsDiff in these PRs be enough to fix the bug? Or is the inconsistent behavior between foreground = true and foreground = false causing a problem?

Yes, for three reasons:

  • not using updatedAtMsDiff causes a problem when a foreground location gets forced to server time while background locations are adjusted per updatedAtMsDiff, leading to inconsistent ordering (a subsequent background location can be brought erroneously before the foreground location by the updatedAtMsDiff adjustment). So no, the other updatedAtMsDiff changes would be not sufficient to fully fix the bug.
  • for consistency
  • because there's no empirical reason to specially trust foreground locations from the OS as time-correct. It's true that foreground locations aren't subject to delays related to backgrounding, but the OS can and does deliver locations when foregrounded that have a non now timestamp

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

• Don't special case verified = true on the client side, handle it differently on the server side

Correct, per slack conversation. I'll link in #mobile

@@ -67,9 +67,39 @@ - (void)requestWithMethod:(NSString *)method
}

if (params) {
[req setHTTPBody:[NSJSONSerialization dataWithJSONObject:params options:0 error:NULL]];
NSNumber *prevUpdatedAtMsDiff = params[@"updatedAtMsDiff"];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we're collecting locationMS we could also pass up updatedAt (we probably already are) we could do this bookkeeping server side but I think let's do that in a v2 in the interest of getting this out.

@KennyHuRadar KennyHuRadar merged commit 65844f2 into master Dec 9, 2024
2 checks passed
@KennyHuRadar KennyHuRadar deleted the replayTimestamps branch December 9, 2024 22:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants