T-127: replace InProcessClient with socket loopback
test / unit + widget + golden + a11y (push) Failing after 2m16s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
test / dart doc (lib API) (push) Failing after 29s
test / unit + widget + golden + a11y (push) Failing after 2m16s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
test / dart doc (lib API) (push) Failing after 29s
Fourth slice of T-99. The UI's DaemonClient now talks to its own IpcServer through the same per-workspace Unix socket the C `clide` client uses — one transport, one wire contract, no second path through the dispatch tree. Changes: * lib/kernel/src/ipc/in_process.dart deleted. Nothing imports it. * DaemonClient.socketPath becomes mutable + new `reconnectAt(path)` method swaps an active client onto a different socket without restart. Project switch in main.dart uses it — the dispatcher + IpcServer are rebuilt for the new workspace, and the client reconnects to the new path. * main.dart's daemonClientFactory now builds a real DaemonClient pointed at workspaceSocketPath(workRoot); swapIpcServer kicks off server.start() then client.start() in sequence. * lib/test_app.dart's pane.spawn smoke test uses dispatcher.dispatch directly instead of InProcessClient — same coverage, no dead-end import. * DaemonClient client_test gets a reconnectAt round-trip test. T-128 (delete IsolateClient + Backend + backend_entry.dart) unblocked. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -276,5 +276,45 @@ void main() {
|
||||
await Future<void>.delayed(const Duration(milliseconds: 100));
|
||||
expect(flips, contains(true));
|
||||
});
|
||||
|
||||
test('reconnectAt swaps socket paths and re-binds (T-127)', () async {
|
||||
final pathA = await _tmpSocket();
|
||||
final daemonA = _TestDaemon(pathA);
|
||||
await daemonA.start();
|
||||
addTearDown(daemonA.close);
|
||||
|
||||
final bus = DaemonBus();
|
||||
addTearDown(bus.dispose);
|
||||
final client = _build(pathA, bus);
|
||||
addTearDown(client.dispose);
|
||||
await client.start();
|
||||
await daemonA.waitForClient();
|
||||
await Future<void>.delayed(const Duration(milliseconds: 50));
|
||||
expect(client.isConnected, isTrue);
|
||||
expect(client.socketPath, pathA);
|
||||
|
||||
// Spin up a SECOND daemon on a different socket and move the
|
||||
// client over to it.
|
||||
final pathB = await _tmpSocket();
|
||||
final daemonB = _TestDaemon(pathB);
|
||||
await daemonB.start();
|
||||
addTearDown(daemonB.close);
|
||||
|
||||
await client.reconnectAt(pathB);
|
||||
await daemonB.waitForClient();
|
||||
await Future<void>.delayed(const Duration(milliseconds: 50));
|
||||
expect(client.socketPath, pathB);
|
||||
expect(client.isConnected, isTrue);
|
||||
|
||||
// A request goes to the NEW daemon — verify by reading the
|
||||
// line off daemonB.lines.
|
||||
final lineFuture = daemonB.lines.first;
|
||||
final responseFuture = client.request('ping');
|
||||
final reqLine = await lineFuture;
|
||||
final reqJson = jsonDecode(reqLine) as Map<String, Object?>;
|
||||
daemonB.send(IpcResponse.ok(id: reqJson['id'] as String, data: const {'pong': true}).encode());
|
||||
final resp = await responseFuture;
|
||||
expect(resp.ok, isTrue);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user