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
Add an option for flutter daemon to listen on a TCP port #95418
Conversation
317d3f5
to
07d852d
Compare
Added a new class DaemonConnection to reuse the connection handling between daemon server and client, and handle connection with different medium (stdio, socket). Added a new option `listen-on-tcp-port` to the flutter daemon command, when passed, the daemon will accept commands on a port instead of stdio.
07d852d
to
759e9cf
Compare
final String port = stringArg('listen-on-tcp-port'); | ||
await _DaemonServer( | ||
port: int.parse(port), |
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 should probably be checked that it's a valid int.
final String port = stringArg('listen-on-tcp-port'); | |
await _DaemonServer( | |
port: int.parse(port), | |
int port; | |
try { | |
port = int.parse(stringArg('listen-on-tcp-port')); | |
} on FormatException catch (error) { | |
throwToolExit('Invalid port for `--listen-on-tcp-port`: $error'); | |
} | |
await _DaemonServer( | |
port: port, |
this.notifyingLogger, | ||
}); | ||
|
||
int port; |
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.
int port; | |
final int port; |
int port; | ||
|
||
/// Stdout logger used to print general server-related errors. | ||
Logger logger; |
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.
Logger logger; | |
final Logger logger; |
Logger logger; | ||
|
||
// Logger that sends the message to the other end of daemon connection. | ||
NotifyingLogger notifyingLogger; |
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.
NotifyingLogger notifyingLogger; | |
final NotifyingLogger notifyingLogger; |
if (!_onExitCompleter.isCompleted) { | ||
_onExitCompleter.complete(0); | ||
} | ||
}, | ||
); | ||
} | ||
|
||
DaemonConnection connection; |
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.
DaemonConnection connection; | |
final DaemonConnection connection; |
void send(Map<String, Object?> message) { | ||
globals.stdio.stdoutWrite( | ||
'[${json.encode(message)}]\n', | ||
fallback: (String message, dynamic error, StackTrace stack) { |
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.
fallback: (String message, dynamic error, StackTrace stack) { | |
fallback: (String message, Object? error, StackTrace stack) { |
map['params'] = _toJsonable(args); | ||
} | ||
_send(map); | ||
daemon.connection.sendEvent(name, args != null ? _toJsonable(args) : null); |
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.
_toJsonable
returns null
when args
is null.
daemon.connection.sendEvent(name, args != null ? _toJsonable(args) : null); | |
daemon.connection.sendEvent(name, _toJsonable(args)); |
} | ||
|
||
/// A [DaemonStream] that uses [Socket] as the underlying stream. | ||
class TcpDaemonStreams extends DaemonStreams { |
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 this tested anywhere?
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.
Added a new test for this class
/// microtask queue. This avoids a deadlock when tests `await` a Future | ||
/// which queues a microtask that will not be processed unless the queue | ||
/// is flushed. | ||
// Future<T> _runFakeAsync<T>(Future<T> Function(FakeAsync time) f) 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.
Delete?
Thanks for the thorough review! I've just pushed the fix for the review feedbacks. PTAL, 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.
Minor nits
stdinCommandStream, | ||
stdoutCommandResponse, | ||
DaemonConnection( | ||
daemonStreams: StdioDaemonStreams(), |
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.
daemonStreams: StdioDaemonStreams(), | |
daemonStreams: StdioDaemonStreams(globals.stdio), |
globals.printStatus('Starting device daemon...'); | ||
final Daemon daemon = Daemon( | ||
stdinCommandStream, stdoutCommandResponse, | ||
DaemonConnection( | ||
daemonStreams: StdioDaemonStreams(), |
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.
daemonStreams: StdioDaemonStreams(), | |
daemonStreams: StdioDaemonStreams(globals.stdio), |
stdinCommandStream, | ||
stdoutCommandResponse, | ||
DaemonConnection( | ||
daemonStreams: StdioDaemonStreams(), |
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.
daemonStreams: StdioDaemonStreams(), | |
daemonStreams: StdioDaemonStreams(globals.stdio), |
StdioDaemonStreams([Stdio? stdio]) : | ||
_stdio = stdio ?? globals.stdio, | ||
inputStream = _convertInputStream((stdio ?? globals.stdio).stdin); |
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.
Make the injected globals required, ideally we should be able to remove import 'globals.dart' as globals;
from almost everywhere but context_runner.dart
. Unfortunately the commands don't have their dependencies injected yet, so the global context objects will need to be passed from there.
StdioDaemonStreams([Stdio? stdio]) : | |
_stdio = stdio ?? globals.stdio, | |
inputStream = _convertInputStream((stdio ?? globals.stdio).stdin); | |
StdioDaemonStreams(Stdio stdio) : | |
_stdio = stdio, | |
inputStream = _convertInputStream(stdio.stdin); |
Logger? logger, | ||
}): _logger = logger ?? globals.logger { |
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.
Logger? logger, | |
}): _logger = logger ?? globals.logger { | |
required Logger logger, | |
}): _logger = logger { |
Logger? logger, | ||
}) : _logger = logger ?? globals.logger { |
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.
Logger? logger, | |
}) : _logger = logger ?? globals.logger { | |
required Logger logger, | |
}) : _logger = logger { |
}); | ||
final Daemon daemon = Daemon( | ||
DaemonConnection( | ||
daemonStreams: TcpDaemonStreams(socket), |
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.
daemonStreams: TcpDaemonStreams(socket), | |
daemonStreams: TcpDaemonStreams(socket, logger: logger), |
} | ||
|
||
/// Connects to a remote host and creates a [DaemonStreams] from the socket. | ||
TcpDaemonStreams.connect( |
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 this used?
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 will be used in my next PR, would you want me to remove it from here, and add the change in my next PR instead?
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.
No, you can leave it in this PR, wanted to make sure it wasn't leftover from something else you tried.
|
||
// @dart = 2.8 |
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.
// @dart = 2.8 |
Make this file null safe.
BufferLogger bufferLogger; | ||
FakeDaemonStreams daemonStreams; | ||
DaemonConnection daemonConnection; |
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.
BufferLogger bufferLogger; | |
FakeDaemonStreams daemonStreams; | |
DaemonConnection daemonConnection; | |
late BufferLogger bufferLogger; | |
late FakeDaemonStreams daemonStreams; | |
late DaemonConnection daemonConnection; |
Just pushed the changes for the review feedback, PTAL, 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.
LGTM
Thanks for the review Jenn! |
)" This reverts commit 2b46ea4.
…tter#95418)" Fixes the test brekage and reverts commit caed03d.
Added a new class DaemonConnection to reuse the connection handling
between daemon server and client, and handle connection with different
medium (stdio, socket).
Added a new option
listen-on-tcp-port
to the flutter daemon command,when passed, the daemon will accept commands on a port instead of stdio.
This will be used to create a device proxy.
Context: b/210724354
Pre-launch Checklist
///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.