LCOV - code coverage report

Current view
top level - /src - _worker_runner.dart
Test
lcov.info
Date
2022-04-02
Legend
Lines
hit
not hit
Branches
taken
not taken
# not executed
HitTotalCoverage
Lines495884.5%
Functions00-
Branches00-
Each row represents a line of source code
LineBranchHitsSource code
1import 'dart:isolate';
2
3import '_worker_monitor.dart';
4import 'squadron.dart';
5import 'squadron_error.dart';
6import 'squadron_exception.dart';
7import 'worker.dart';
8import 'worker_exception.dart';
9import 'worker_request.dart';
10import 'worker_service.dart';
11
12class WorkerRunner {
132 WorkerRunner(this._monitor);
14
151 factory WorkerRunner.use(WorkerService service) {
161 final worker = WorkerRunner(null);
174 worker._operations.addAll(service.operations);
18 return worker;
19 }
20
211 final _operations = <int, CommandHandler>{};
22 final WorkerMonitor? _monitor;
23
24 /// Called by the platform worker upon startup, in response to a start [WorkerRequest]. [channelInfo] is an opaque
25 /// object sent back from the platform worker to the Squadron [Worker] and used to communicate with the platform
26 /// worker. Typically, [channelInfo] would be a [SendPort] (native) or a [MessagePort] (browser). [initializer]
27 /// is called to build the [WorkerService] associated to the worker. The runner's [_operations] map will be
28 /// populated with operations from the service.
291 Future connect(
30 Map? message, Object channelInfo, WorkerInitializer initializer) async {
311 final startRequest = WorkerRequest.deserialize(message);
321 final client = startRequest?.client;
33
34 if (startRequest == null) {
351 throw newSquadronError('connection request expected');
36 } else if (client == null) {
370 throw newSquadronError('missing client for connection request');
38 }
39
40 try {
411 if (!startRequest.connect) {
420 throw newSquadronError('connection request expected');
432 } else if (_operations.isNotEmpty) {
440 throw newSquadronError('already connected');
45 }
46
472 Squadron.setId(startRequest.id!);
482 Squadron.logLevel = startRequest.logLevel!;
49
501 final init = initializer(startRequest);
512 final operations = ((init is Future) ? await init : init).operations;
525 if (operations.keys.where((k) => k <= 0).isNotEmpty) {
531 throw newSquadronError(
54 'invalid command identifier in service operations map; command ids must be > 0');
55 }
562 _operations.addAll(operations);
571 client.connect(channelInfo);
58 } catch (e, st) {
592 client.error(SquadronException.from(error: e, stackTrace: st));
60 }
61 }
62
63 /// [WorkerRequest] handler dispatching commands aoocrding to the [_operations] map.
642 void processMessage(Map message) async {
652 Squadron.finest(() => 'processing request $message');
661 final request = WorkerRequest.deserialize(message);
671 final client = request?.client;
68
69 if (request == null) {
700 throw newSquadronError('invalid message');
711 } else if (request.terminate) {
722 return _monitor?.terminate();
731 } else if (request.cancel) {
743 return _monitor?.cancel(request.cancelToken!);
75 } else if (client == null) {
760 throw newSquadronError('missing client for request: $request');
77 }
78
794 final tokenRef = _monitor?.begin(request) ?? WorkerMonitor.noTokenRef;
801 var streaming = false;
811 try {
821 if (request.connect) {
83 // connection request must be handled beforehand
840 throw newSquadronError('unexpected connection request: $message');
853 } else if (_operations.isEmpty) {
86 // commands are not available yet (maybe connect() wasn't called or awaited)
870 throw WorkerException('worker service is not ready');
881 } else if (tokenRef.cancelled) {
890 throw tokenRef.exception!;
90 }
91 // retrieve operation matching the request command
924 final op = _operations[request.command];
93 if (op == null) {
943 throw WorkerException('unknown command: ${request.command}');
95 }
96 // process
972 dynamic result = op(request);
983 result = (result is Future) ? await result : result;
993 if (result is Stream && result is! ReceivePort) {
100 // stream values to the client
1011 streaming = true;
102 CancelledException? ex;
1033 await for (var res in result) {
104 if (ex != null) {
1050 throw ex;
106 }
1071 client.reply(res);
1081 ex = tokenRef.exception;
109 }
110 } else {
111 // send result to client
1121 client.reply(result);
113 }
1141 } catch (e, st) {
1153 client.error(SquadronException.from(error: e, stackTrace: st));
116 } finally {
117 if (streaming) {
118 // ensure a closeStream response is sent to terminate streaming operations
1191 client.closeStream();
120 }
1212 _monitor?.done(tokenRef);
122 }
1231 }
124}
Choose Features