Isolate Transport¶
rpc_dart_isolate provides a transport that runs the responder side in a separate Dart isolate. Use it to offload CPU-intensive work without blocking the main isolate. On native platforms it uses dart:isolate; on web it uses isolate_manager with web workers.
Installation¶
dependencies:
rpc_dart_isolate: <latest>
How It Works¶
RpcIsolateTransport.spawn() starts an isolate, sets up a bidirectional message channel between host and worker, and returns a named record:
final (:transport, :kill) = await RpcIsolateTransport.spawn(
entrypoint: myWorkerEntrypoint,
);
transport— the host-sideIRpcTransport. Wire it to aRpcCallerEndpointas usual.kill()— terminates the isolate immediately.
Defining the Worker Entrypoint¶
The worker function receives the transport and custom parameters. It must set up a RpcResponderEndpoint and register contracts:
void calculatorWorker(IRpcTransport transport, Map<String, dynamic> params) {
final endpoint = RpcResponderEndpoint(transport: transport);
endpoint.registerServiceContract(CalculatorResponder());
endpoint.start();
// The isolate stays alive as long as the endpoint is open.
}
The entrypoint signature must match RpcIsolateEntrypoint:
typedef RpcIsolateEntrypoint =
void Function(IRpcTransport transport, Map<String, dynamic> customParams);
Warning
The entrypoint function must be a top-level function or a static method — Dart isolates cannot send closures across isolate boundaries.
Usage¶
import 'package:rpc_dart_isolate/rpc_dart_isolate.dart';
// Spawn the worker isolate
final (:transport, :kill) = await RpcIsolateTransport.spawn(
entrypoint: calculatorWorker,
customParams: {'precision': 10},
debugName: 'calculator-worker',
);
// Use the transport on the host side
final caller = CalculatorContractCaller(
RpcCallerEndpoint(transport: transport),
);
final result = await caller.sum(SumRequest(values: [1, 2, 3]));
print('sum = ${result.result}');
// Shut down
await caller.endpoint.close();
kill();
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
entrypoint |
RpcIsolateEntrypoint |
required | Worker function |
customParams |
Map<String, dynamic>? |
{} |
Arbitrary data passed to the worker |
isolateId |
String |
'default' |
Logical ID (used in default debug name) |
debugName |
String? |
'rpc-isolate-{id}' |
Name shown in the Dart VM debugger |
policy |
RpcSecurityPolicy |
default policy | Security limits |
workerUri |
Uri? |
null |
Web worker script URI (web only, ignored on IO) |
Web / Wasm¶
On web, workerUri points to the compiled worker script. The API is identical — only the workerUri parameter differs:
final (:transport, :kill) = await RpcIsolateTransport.spawn(
entrypoint: calculatorWorker,
workerUri: Uri.parse('worker.dart.js'),
);
Notes¶
- The isolate transport supports zero-copy (
supportsZeroCopy == true) — objects are passed directly viaSendPortasdirectObjectmessages without serialization. - All four RPC patterns (unary, server-stream, client-stream, bidirectional) are supported.
kill()is immediate; for a graceful shutdown close the endpoint first, then callkill().