mirror of https://github.com/AMT-Cheif/drift.git
Merge pull request #1598 from kuhnroyal/feature/isolate-serialization
Move serialization decision from server to client
This commit is contained in:
commit
344453750f
|
@ -39,13 +39,33 @@ class DriftIsolate {
|
||||||
/// can reconstruct a [DriftIsolate] by using [DriftIsolate.fromConnectPort].
|
/// can reconstruct a [DriftIsolate] by using [DriftIsolate.fromConnectPort].
|
||||||
final SendPort connectPort;
|
final SendPort connectPort;
|
||||||
|
|
||||||
|
/// The flag indicating whether messages between this [DriftIsolate]
|
||||||
|
/// and the [DriftServer] should be serialized.
|
||||||
|
final bool serialize;
|
||||||
|
|
||||||
/// Creates a [DriftIsolate] talking to another isolate by using the
|
/// Creates a [DriftIsolate] talking to another isolate by using the
|
||||||
/// [connectPort].
|
/// [connectPort].
|
||||||
DriftIsolate.fromConnectPort(this.connectPort);
|
///
|
||||||
|
/// {@template drift_isolate_serialize}
|
||||||
|
/// Internally, drift uses ports from `dart:isolate` to send commands to an
|
||||||
|
/// internal server dispatching database actions.
|
||||||
|
/// In most setups, those ports can send and receive almost any Dart object.
|
||||||
|
/// In special cases though, the platform only supports sending simple types
|
||||||
|
/// across send types. In particular, isolates across different Flutter
|
||||||
|
/// engines (such as the ones spawned by the `workmanager` package) are
|
||||||
|
/// unable to handle most objects.
|
||||||
|
/// To support those setups, drift can serialize its internal communication
|
||||||
|
/// channel to only send simple types across isolates. The [serialize]
|
||||||
|
/// parameter, which is enabled by default, controls this behavior.
|
||||||
|
///
|
||||||
|
/// In most scenarios, [serialize] can be disabled for a considerable
|
||||||
|
/// performance improvement.
|
||||||
|
/// {@endtemplate}
|
||||||
|
DriftIsolate.fromConnectPort(this.connectPort, {this.serialize = true});
|
||||||
|
|
||||||
StreamChannel _open() {
|
StreamChannel _open() {
|
||||||
final receive = ReceivePort('drift client receive');
|
final receive = ReceivePort('drift client receive');
|
||||||
connectPort.send(receive.sendPort);
|
connectPort.send([receive.sendPort, serialize]);
|
||||||
|
|
||||||
final controller =
|
final controller =
|
||||||
StreamChannelController(allowForeignErrors: false, sync: true);
|
StreamChannelController(allowForeignErrors: false, sync: true);
|
||||||
|
@ -65,27 +85,8 @@ class DriftIsolate {
|
||||||
/// All operations on the returned [DatabaseConnection] will be executed on a
|
/// All operations on the returned [DatabaseConnection] will be executed on a
|
||||||
/// background isolate. Setting the [isolateDebugLog] is only helpful when
|
/// background isolate. Setting the [isolateDebugLog] is only helpful when
|
||||||
/// debugging drift itself.
|
/// debugging drift itself.
|
||||||
///
|
|
||||||
/// {@template drift_isolate_serialize}
|
|
||||||
/// Internally, drift uses ports from `dart:isolate` to send commands to an
|
|
||||||
/// internal server dispatching database actions.
|
|
||||||
/// In most setups, those ports can send and receive almost any Dart object.
|
|
||||||
/// In special cases though, the platform only supports sending simple types
|
|
||||||
/// across send types. In particular, isolates across different Flutter
|
|
||||||
/// engines (such as the ones spawned by the `workmanager` package) are
|
|
||||||
/// unable to handle most objects.
|
|
||||||
/// To support those setups, drift can serialize its internal communication
|
|
||||||
/// channel to only send simple types across isolates. The [serialize]
|
|
||||||
/// parameter, which is enabled by default, controls this behavior.
|
|
||||||
///
|
|
||||||
/// In most scenarios, [serialize] can be disabled for a considerable
|
|
||||||
/// performance improvement.
|
|
||||||
/// Please note that the value of [serialize] __must__ be the same across the
|
|
||||||
/// methods [spawn], [inCurrent], [connect] and [shutdownAll].
|
|
||||||
/// {@endtemplate}
|
|
||||||
// todo: breaking: Make synchronous in drift 2
|
// todo: breaking: Make synchronous in drift 2
|
||||||
Future<DatabaseConnection> connect(
|
Future<DatabaseConnection> connect({bool isolateDebugLog = false}) async {
|
||||||
{bool isolateDebugLog = false, bool serialize = true}) async {
|
|
||||||
return remote(_open(), debugLog: isolateDebugLog, serialize: serialize);
|
return remote(_open(), debugLog: isolateDebugLog, serialize: serialize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,9 +94,7 @@ class DriftIsolate {
|
||||||
/// created.
|
/// created.
|
||||||
/// If you only want to disconnect a database connection created via
|
/// If you only want to disconnect a database connection created via
|
||||||
/// [connect], use [GeneratedDatabase.close] instead.
|
/// [connect], use [GeneratedDatabase.close] instead.
|
||||||
///
|
Future<void> shutdownAll() {
|
||||||
/// {@macro drift_isolate_serialize}
|
|
||||||
Future<void> shutdownAll({bool serialize = true}) {
|
|
||||||
return shutdown(_open(), serialize: serialize);
|
return shutdown(_open(), serialize: serialize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,14 +112,13 @@ class DriftIsolate {
|
||||||
///
|
///
|
||||||
/// {@macro drift_isolate_serialize}
|
/// {@macro drift_isolate_serialize}
|
||||||
static Future<DriftIsolate> spawn(DatabaseOpener opener,
|
static Future<DriftIsolate> spawn(DatabaseOpener opener,
|
||||||
{bool serialize = true}) async {
|
{bool serialize = false}) async {
|
||||||
final receiveServer = ReceivePort();
|
final receiveServer = ReceivePort();
|
||||||
final keyFuture = receiveServer.first;
|
final keyFuture = receiveServer.first;
|
||||||
|
|
||||||
await Isolate.spawn(
|
await Isolate.spawn(_startDriftIsolate, [receiveServer.sendPort, opener]);
|
||||||
_startDriftIsolate, [receiveServer.sendPort, opener, serialize]);
|
|
||||||
final key = await keyFuture as SendPort;
|
final key = await keyFuture as SendPort;
|
||||||
return DriftIsolate.fromConnectPort(key);
|
return DriftIsolate.fromConnectPort(key, serialize: serialize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a [DriftIsolate] in the [Isolate.current] isolate. The returned
|
/// Creates a [DriftIsolate] in the [Isolate.current] isolate. The returned
|
||||||
|
@ -134,10 +132,13 @@ class DriftIsolate {
|
||||||
///
|
///
|
||||||
/// {@macro drift_isolate_serialize}
|
/// {@macro drift_isolate_serialize}
|
||||||
factory DriftIsolate.inCurrent(DatabaseOpener opener,
|
factory DriftIsolate.inCurrent(DatabaseOpener opener,
|
||||||
{bool killIsolateWhenDone = false, bool serialize = true}) {
|
{bool killIsolateWhenDone = false, bool serialize = false}) {
|
||||||
final server = RunningDriftServer(Isolate.current, opener(),
|
final server = RunningDriftServer(Isolate.current, opener(),
|
||||||
killIsolateWhenDone: killIsolateWhenDone, serialize: serialize);
|
killIsolateWhenDone: killIsolateWhenDone);
|
||||||
return DriftIsolate.fromConnectPort(server.portToOpenConnection);
|
return DriftIsolate.fromConnectPort(
|
||||||
|
server.portToOpenConnection,
|
||||||
|
serialize: serialize,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,9 +152,7 @@ class DriftIsolate {
|
||||||
void _startDriftIsolate(List args) {
|
void _startDriftIsolate(List args) {
|
||||||
final sendPort = args[0] as SendPort;
|
final sendPort = args[0] as SendPort;
|
||||||
final opener = args[1] as DatabaseOpener;
|
final opener = args[1] as DatabaseOpener;
|
||||||
final serialize = args[2] as bool;
|
|
||||||
|
|
||||||
final server =
|
final server = RunningDriftServer(Isolate.current, opener());
|
||||||
RunningDriftServer(Isolate.current, opener(), serialize: serialize);
|
|
||||||
sendPort.send(server.portToOpenConnection);
|
sendPort.send(server.portToOpenConnection);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ import '../remote.dart';
|
||||||
class RunningDriftServer {
|
class RunningDriftServer {
|
||||||
final Isolate self;
|
final Isolate self;
|
||||||
final bool killIsolateWhenDone;
|
final bool killIsolateWhenDone;
|
||||||
final bool serialize;
|
|
||||||
|
|
||||||
final DriftServer server;
|
final DriftServer server;
|
||||||
final ReceivePort connectPort = ReceivePort('drift connect');
|
final ReceivePort connectPort = ReceivePort('drift connect');
|
||||||
|
@ -22,14 +21,16 @@ class RunningDriftServer {
|
||||||
SendPort get portToOpenConnection => connectPort.sendPort;
|
SendPort get portToOpenConnection => connectPort.sendPort;
|
||||||
|
|
||||||
RunningDriftServer(this.self, DatabaseConnection connection,
|
RunningDriftServer(this.self, DatabaseConnection connection,
|
||||||
{this.killIsolateWhenDone = true, required this.serialize})
|
{this.killIsolateWhenDone = true})
|
||||||
: server = DriftServer(connection, allowRemoteShutdown: true) {
|
: server = DriftServer(connection, allowRemoteShutdown: true) {
|
||||||
final subscription = connectPort.listen((message) {
|
final subscription = connectPort.listen((message) {
|
||||||
if (message is SendPort) {
|
if (message is List && message.length == 2) {
|
||||||
|
final sendPort = message[0]! as SendPort;
|
||||||
|
final serialize = message[1]! as bool;
|
||||||
final receiveForConnection =
|
final receiveForConnection =
|
||||||
ReceivePort('drift channel #${_counter++}');
|
ReceivePort('drift channel #${_counter++}');
|
||||||
message.send(receiveForConnection.sendPort);
|
sendPort.send(receiveForConnection.sendPort);
|
||||||
final channel = IsolateChannel(receiveForConnection, message);
|
final channel = IsolateChannel(receiveForConnection, sendPort);
|
||||||
|
|
||||||
server.serve(channel, serialize: serialize);
|
server.serve(channel, serialize: serialize);
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,8 +116,7 @@ void _runTests(FutureOr<DriftIsolate> Function() spawner, bool terminateIsolate,
|
||||||
isolate = await spawner();
|
isolate = await spawner();
|
||||||
|
|
||||||
database = TodoDb.connect(
|
database = TodoDb.connect(
|
||||||
DatabaseConnection.delayed(
|
DatabaseConnection.delayed(isolate.connect()),
|
||||||
isolate.connect(isolateDebugLog: false, serialize: serialize)),
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -125,7 +124,7 @@ void _runTests(FutureOr<DriftIsolate> Function() spawner, bool terminateIsolate,
|
||||||
await database.close();
|
await database.close();
|
||||||
|
|
||||||
if (terminateIsolate) {
|
if (terminateIsolate) {
|
||||||
await isolate.shutdownAll(serialize: serialize);
|
await isolate.shutdownAll();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue