-
Notifications
You must be signed in to change notification settings - Fork 12
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
Ensure network monitor path update handler is called on start #199
Ensure network monitor path update handler is called on start #199
Conversation
All other usages across the class are via `self.`.
Source code locality helps local reasoning.
Without one, the update block would not run on start, resulting in 100% launches being marked as offline. Hat tip https://msolarana.netlify.app/2018/08/04/monitoring-network-changes/
dispatch_queue_attr_t attrs = dispatch_queue_attr_make_with_qos_class( | ||
DISPATCH_QUEUE_SERIAL, | ||
QOS_CLASS_UTILITY, | ||
DISPATCH_QUEUE_PRIORITY_DEFAULT |
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.
The docs indicate that the third parameter to dispatch_queue_attr_make_with_qos_class
is a relative priority within the QOS class, and can range from 0 to -15. Usually, we'd want to pass 0
, unless we specifically know we want to set it to a lower priority than some other value.
As it happens, DISPATCH_QUEUE_PRIORITY_DEFAULT
happens to be equal to 0, but it's semantically the wrong thing to be passing here, because this parameter doesn't take a dispatch_queue_priority_t
at all; it just wants an int
.
I'd recommend replacing this with 0
explicitly. That's what I've seen in most of the Apple sample code that uses this API. (One such example here).
Though… see below; we may be able to drop this call altogether.
QOS_CLASS_UTILITY, | ||
DISPATCH_QUEUE_PRIORITY_DEFAULT | ||
); | ||
self.networkMonitorQueue = dispatch_queue_create("com.automattic.tracks.network.monitor", attrs); |
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.
Apple's docs (and various Apple engineers) recommend using dispatch_queue_create_with_target
instead to create a serial queue that will target one of the existing concurrent views, rather than creating a new root queue. Creating a root queue will usually result in a permanent thread dedicated to this queue, which is definitely overkill for this particular use case.
Bonus: if we use the target
API, then I don't think we need to create the attrs
above at all.
I really wish this were documented better, but it's not. It's all in WWDC videos and Twitter lore from Apple engineers.
self.networkMonitorQueue = dispatch_queue_create("com.automattic.tracks.network.monitor", attrs); | |
dispatch_queue_t utilityQueue = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0); | |
self.networkMonitorQueue = dispatch_queue_create_with_target("com.automattic.tracks.network.monitor", DISPATCH_QUEUE_SERIAL, utilityQueue); |
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.
@bjhomer, I tried this approach but it behaved as before: When the demo app launches, the update handler block is not called.
I pushed that version to a dedicated branch if you want to play with it 2ca8b3b .
In the meantime, I applied your other suggestion and verified it works following the manual script from the PR description.
What do you think of merging this version in, so we can ship the fix in WordPress 19.5, which is scheduled for the coming Monday, and then figure out why the code that Apple recommends doesn't work?
Thanks!
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.
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.
@bjhomer 🤦♂️... I had a feeling I missed something, but couldn't put my finger on it.
I incorporated your suggestion and verified it worked, as you said 🎉 Thanks!
Given my track record in this PR, I dismissed your review and asked for a new one. Much appreciated 🙇♂️
Thanks for catching this. Sorry I missed it earlier! |
I'm committing this for reference purposes only as it does not work. When the app starts, the update handler block is not called. See discussion in #199.
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 commented about how to make my proposed version work, but I'm okay with this version if you'd prefer it.
Co-authored-by: BJ Homer <[email protected]>
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.
This looks good to me!
Earlier today, @yaelirub reported an unusual spike in events logged with the device offline in WordPress iOS starting from 19.2.
Together with @twstokes, the tracked it to the Tracks update to version 0.11.0 and the new network reachability logic from #186. Tanner noticed that, at launch, the network path was
nil
, resulting in this branch of the network properties logging conditional running.I experienced the same behavior when running the TracksDemo app from this repo (microapps FTW!).
The behavior I experienced was that the block meant to receive network path updates was not called when the monitor started, even though that's the expectation set by the documentation.
I did some googling but nobody reported the issue. I stumbled onto this post by @madsolar8582 that also explicitly sets a queue on which to dispatch the update block execution. I tried it out and it did the trick 🎉
To test
On
trunk
, put a breakpoint in the update block:Automattic-Tracks-iOS/Sources/Event Logging/TracksService.m
Line 323 in 7fc4afe
Notice that it's not hit on start, but it is if you change you network interface, for example by turning the Wi-Fi on.
Repeat on this branch and notice that the block is called when the demo app starts (fix) and also when the network changes (no regressions).
Alternatively, use
updateDeviceInformationFromReachability
as the inspection point for the breakpoint. Ontrunk
here: updateDeviceInformationFromReachability. If you do that, be mindful that it gets called as part ofTracksService
init, and will haveself.networkPath
nil
there because the monitoring hasn't been setup yet.