-
Notifications
You must be signed in to change notification settings - Fork 28.9k
Change iOS device discovery from polling to long-running observation #58137
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
Conversation
// Run in interactive mode (via script) to convince | ||
// xcdevice it has a terminal attached and pipe stdout. |
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.
Learned this trick from https://github.com/flutter/flutter/pull/12079/files#diff-5a9a07600dceb28cbe887a5a64a24b0aR502-R504.
Timer _timer; | ||
|
||
Future<List<Device>> pollingGetDevices({ Duration timeout }); | ||
|
||
void startPolling() { | ||
Future<void> startPolling() async { |
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.
g3 PollingDeviceDiscovery subclasses don't override startPolling
or stopPolling
.
6740b4a
to
941b59c
Compare
|
||
@protected | ||
@visibleForTesting | ||
ItemListNotifier<Device> deviceNotifier; |
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.
Renamed _items
-> deviceNotifier
}, onDone: () { | ||
// If the xcdevice process is killed, restart it. | ||
_logger.printTrace('xcdevice observe stopped, restarting'); | ||
startPolling(); |
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.
So I'm understanding this correctly: since we're relying on a single long running process now, it needs to restart in case it goes down unexpectedly, otherwise IDEs wouldn't be able to discover new iOS devices without restarting - right?
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.
That's it.
_logger.printTrace('xcdevice observe stopped, restarting'); | ||
|
||
// If the xcdevice process is killed, give it a few seconds and restart it. | ||
Timer(const Duration(seconds: 1), () { |
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.
What if the device discovery exits immediately on start up (something is broken). Will this keep scheduling work in a loop? Likewise if this is killed as part of tear down.
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.
PollingDeviceDiscovery
polling currently schedules a timer every 4 seconds to call device-specific discovery code, so that's the existing behavior. It depends what we want the behavior to be. If I killall
xcdevice (exits 137), I would expect it to get rescheduled and the IDE not to need to be restarted. However if it just fails in some other way, rerunning it probably won't help? @zanderso What do you think?
Restarting after stopPolling
is bad though...
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.
Its a bit of a tricky situation. How common is it for this process to go down during an IDE session? It might be less risky to log a message and move on
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 never saw it organically go down in my testing, but I also never saw my hard drive fill up with xcdevice
caches described in #56826.
Good opportunity for metrics?
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.
yeah, if we're not sure lets measure
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.
It looks like close()
on the StreamController
for this Stream
isn't called, so how does the 'onDone' callback get invoked?
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.
It is now. See comment at #58137 (comment).
_logger.printTrace('xcdevice observe stopped, restarting'); | ||
|
||
// If the xcdevice process is killed, give it a few seconds and restart it. | ||
Timer(const Duration(seconds: 1), () { |
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.
It looks like close()
on the StreamController
for this Stream
isn't called, so how does the 'onDone' callback get invoked?
void _setupDeviceIdentifierByEventStream() { | ||
// _deviceIdentifierByEvent Should always be available for listeners | ||
// in case polling needs to be stopped and restarted. | ||
_deviceIdentifierByEvent = StreamController<Map<XCDeviceEvent, String>>.broadcast( | ||
onListen: _startObservingTetheredIOSDevices, | ||
onCancel: _stopObservingTetheredIOSDevices, | ||
); | ||
} |
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 was the piece I was missing when I wasn't closing _deviceIdentifierByEvent
on the last commit. I want polling to be able to be started, stopped, and re-started. Before, I was avoiding closing it so it could be re-listened to, but I guess it should be closed when no one is listening.
Really I want to be able to pause the subscription and resume it, but the pause()
documentation says:
* To avoid buffering events on a broadcast stream, it is better to
* cancel this subscription, and start to listen again when events
* are needed, if the intermediate events are not important.
'xcrun', | ||
'xcdevice', | ||
'observe', | ||
'--both', |
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 also changed this to --both
to reflect what I just did in https://github.com/flutter/flutter/pull/58257/files#diff-8d108d6a887a4f5b74f7c7d77003e795R97. Wireless devices aren't being sufaced yet, so if one attaches it will kick off an unnecessary fetch. Should be rare.
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.
lgtm after addressing @jonahwilliams comments.
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.
LGTM
_items ??= ItemListNotifier<Device>(); | ||
return _items.onRemoved; | ||
deviceNotifier ??= ItemListNotifier<Device>(); | ||
return deviceNotifier.onRemoved; | ||
} | ||
|
||
void dispose() => stopPolling(); |
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.
Shouldn't this be async now?
super('iOS devices'); | ||
|
||
@override | ||
void dispose() { | ||
_observedDeviceEventsSubscription?.cancel(); |
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.
Should this not call super.dispose()
?
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.
Also, if the super signature was async, this would just be await stopPolling()
Description
For daemon iOS device polling, change periodic
xcdevice list
calls to a long-runningxcdevice observe
call.Related Issues
Fixes #56826
Tests
Checklist
///
).flutter analyze --flutter-repo
) does not report any problems on my PR.Breaking Change