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

Send tracks events in batches of no more than 1000 #293

Merged
merged 4 commits into from
Jul 22, 2024

Conversation

bjhomer
Copy link
Contributor

@bjhomer bjhomer commented Jul 16, 2024

When sending tracks events, adds a limit of 1000 events to send per batch.

There are two reasons for this:

  • Tracks events are currently being fetched on the main queue, because that's where -[TracksService sendQueuedEvents] is being called when the timer goes off. If we fetch an unbounded number of events, it can result in the main thread hanging if there are many tracks events to send.
  • The tracks reporting endpoint will reject batches that are too large. Experimentally, I've seen this happen when I tried to send 100k events in a single batch. This would lead to increasingly large event counts on device, as we continued to gather then without ever being able to send them.

With these changes, the UI is much less likely to hang. On my device, fetching a batch of 1000 events took only 0.03s, which is probably acceptable on the main thread. By contrast, fetching 93,000 events took 2.25s, a clearly noticeable hang. (And yes, we have a user who appears to have over 100,000 unsent events. Not sure how.)


  • I have considered if this change warrants release notes and have added them to the appropriate section in the CHANGELOG.md if necessary.

@bjhomer bjhomer force-pushed the bj/performance-improvements branch from 5261e8f to 337ee56 Compare July 16, 2024 21:21
@bjhomer bjhomer force-pushed the bj/performance-improvements branch from 337ee56 to 7f93b52 Compare July 16, 2024 21:23
@bjhomer bjhomer marked this pull request as ready for review July 16, 2024 21:23
@bjhomer bjhomer requested a review from a team July 16, 2024 21:24
@AliSoftware AliSoftware requested a review from mokagio July 16, 2024 23:44
@bjhomer bjhomer changed the title Send tracks events in batches of no more than 3000 Send tracks events in batches of no more than 1000 Jul 17, 2024
Copy link
Contributor

@mokagio mokagio left a comment

Choose a reason for hiding this comment

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

Thanks @bjhomer . I appreciate how you never shy from diving into Tracks to implement fixes. 🙇‍♂️

Happy for this to land as is because it sounds like it would unlock your work.

One question, though:

Tracks events are currently being fetched on the main queue, because that's where -[TracksService sendQueuedEvents] is being called when the timer goes off.

Have you considered moving the call to a dedicated queue?

Just curious if you found issues with changing queue or if it's something that wasn't considered in the interest of getting the fix out.

CHANGELOG.md Outdated Show resolved Hide resolved
Sources/Event Logging/TracksEventPersistenceService.m Outdated Show resolved Hide resolved
Sources/Event Logging/TracksEventPersistenceService.m Outdated Show resolved Hide resolved
@@ -161,7 +161,7 @@ - (void)sendQueuedEvents
[self.timer invalidate];
[[NSNotificationCenter defaultCenter] postNotificationName:TrackServiceWillSendQueuedEventsNotification object:nil];

NSArray *events = [self.tracksEventService allTracksEvents];
NSArray *events = [self.tracksEventService tracksEventsWithLimit:1000];
Copy link
Contributor

Choose a reason for hiding this comment

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

My first reaction seeing this change was "if we are batching, what happens to any other batch at this time? Is this safe or will it lose events? do we need to manage the next batch(es)?"

Correct me if I'm wrong given you're surely fresher on the internal details than I am.

I think this is 100% safe without any logic to get the next batch(es). That's because any remaining even will be picked up on the next sendQueuedEvents call, and that will continue until the even queue will be empty.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, they should just wait around until the next time we send events, and then we'll send the next batch.

There's potentially an issue if there's a problem with one particular Tracks event that causes the batch to be rejected; that batch would remain as the first batch, and keep retrying indefinitely, preventing later events from being sent. But I don't know if that's even a possibility, and if it is, it's no worse than the situation we're already in — a single invalid event would already cause all the other events to fail, even without that change. So I'm not concerned about fixing that in this PR.

@bjhomer
Copy link
Contributor Author

bjhomer commented Jul 22, 2024

Have you considered moving the call to a dedicated queue?
Just curious if you found issues with changing queue or if it's something that wasn't considered in the interest of getting the fix out.

Yeah, I think I would like to move it to another queue, but I was going for a smaller change in the interest of getting a fix out sooner.

@bjhomer
Copy link
Contributor Author

bjhomer commented Jul 22, 2024

And really, our events are already running on a background context… the problem is that because the main thread still needs to access that context (via -performAndWait or -perform), the main thread can be blocked if the context is busy doing something else on another thread.

A better solution would probably want to have two separate contexts; one for writing, and one for reading. But that seems quite a bit more complex than what I have time to allocate to this at the moment. :)

@bjhomer bjhomer merged commit c58c9c6 into trunk Jul 22, 2024
7 checks passed
@bjhomer bjhomer deleted the bj/performance-improvements branch July 22, 2024 16:12
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.

2 participants