Proper api to terminate a MoorIsolate

This commit is contained in:
Simon Binder 2019-11-05 21:36:51 +01:00
parent 44cb7c0503
commit e3d3bcd99e
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
5 changed files with 43 additions and 10 deletions

View File

@ -1,6 +1,8 @@
import 'dart:async';
import 'dart:isolate';
import 'package:pedantic/pedantic.dart';
/// An isolate communication setup where there's a single "server" isolate that
/// communicates with a varying amount of "client" isolates.
///
@ -46,7 +48,12 @@ class IsolateCommunication {
final response = (await stream.first) as _ServerConnectionResponse;
return IsolateCommunication._(response.sendPort, stream, debugLog);
final communication =
IsolateCommunication._(response.sendPort, stream, debugLog);
unawaited(communication.closed.then((_) => clientReceive.close()));
return communication;
}
/// Closes the connection to the server.
@ -183,6 +190,10 @@ class Server {
void close() {
_openConnectionPort.close();
_opened.close();
for (var connected in currentChannels) {
connected.close();
}
}
void _handleMessageOnConnectionPort(dynamic message) {
@ -199,6 +210,7 @@ class Server {
communication.closed.whenComplete(() {
currentChannels.remove(communication);
receiveFromClient.close();
});
}
}

View File

@ -3,6 +3,7 @@ import 'dart:isolate';
import 'package:moor/moor.dart';
import 'package:moor/src/runtime/executor/stream_queries.dart';
import 'package:pedantic/pedantic.dart';
import 'communication.dart';
part 'client.dart';
@ -33,9 +34,7 @@ class MoorIsolate {
/// Identifier for the server isolate that we can connect to.
final ServerKey _server;
final Isolate _isolate;
MoorIsolate._(this._server, this._isolate);
MoorIsolate._(this._server);
/// Connects to this [MoorIsolate] from another isolate. All operations on the
/// returned [DatabaseConnection] will be executed on a background isolate.
@ -45,6 +44,21 @@ class MoorIsolate {
return client._connection;
}
/// Stops the background isolate and disconnects all [DatabaseConnection]s
/// created.
/// If you only want to disconnect a database connection created via
/// [connect], use [GeneratedDatabase.close] instead.
Future<void> shutdownAll() async {
final connection = await IsolateCommunication.connectAsClient(_server);
unawaited(connection.request(_NoArgsRequest.terminateAll).then((_) {},
onError: (_) {
// the background isolate is closed before it gets a chance to reply
// to the terminateAll request. Ignore the error
}));
await connection.closed;
}
/// Creates a new [MoorIsolate] on a background thread.
///
/// The [opener] function will be used to open the [DatabaseConnection] used
@ -58,10 +72,9 @@ class MoorIsolate {
final receiveServer = ReceivePort();
final keyFuture = receiveServer.first;
final isolate = await Isolate.spawn(
_startMoorIsolate, [receiveServer.sendPort, opener]);
await Isolate.spawn(_startMoorIsolate, [receiveServer.sendPort, opener]);
final key = await keyFuture as ServerKey;
return MoorIsolate._(key, isolate);
return MoorIsolate._(key);
}
/// Creates a [MoorIsolate] in the [Isolate.current] isolate. The returned
@ -70,7 +83,7 @@ class MoorIsolate {
/// connection which operations are all executed on this isolate.
static MoorIsolate inCurrent(DatabaseOpener opener) {
final server = _MoorServer(opener);
return MoorIsolate._(server.key, Isolate.current);
return MoorIsolate._(server.key);
}
}

View File

@ -18,6 +18,10 @@ enum _NoArgsRequest {
/// integer, which serves as an identifier for the transaction in
/// [_ExecuteQuery.transactionId].
startTransaction,
/// Close the background isolate, disconnect all clients, release all
/// associated resources
terminateAll,
}
enum _StatementMethod {

View File

@ -37,6 +37,10 @@ class _MoorServer {
return connection.executor.ensureOpen();
case _NoArgsRequest.startTransaction:
return _spawnTransaction();
case _NoArgsRequest.terminateAll:
server.close();
Isolate.current.kill();
break;
// the following are requests which are handled on the client side
case _NoArgsRequest.runOnCreate:
throw UnsupportedError(

View File

@ -11,12 +11,12 @@ void main() {
setUp(() async {
isolate = await MoorIsolate.spawn(_backgroundConnection);
isolateConnection = await isolate.connect(isolateDebugLog: true);
isolateConnection = await isolate.connect(isolateDebugLog: false);
});
tearDown(() {
isolateConnection.executor.close();
isolate.kill();
return isolate.shutdownAll();
});
test('can open database and send requests', () async {