@@ -46,60 +46,84 @@ void main() {
4646 receivePort.close ();
4747 });
4848
49- /// Work with a single store across multiple isolates.
50- test ('single store in multiple isolates' , () async {
51- final receivePort = ReceivePort ();
52- final isolate =
53- await Isolate .spawn (createDataIsolate, receivePort.sendPort);
54-
55- final sendPortCompleter = Completer <SendPort >();
56- late Completer <dynamic > responseCompleter;
57- receivePort.listen ((dynamic data) {
58- if (data is SendPort ) {
59- sendPortCompleter.complete (data);
60- } else {
61- print ('Main received: $data ' );
62- responseCompleter.complete (data);
63- }
64- });
49+ /// Work with a single store across multiple isolates using
50+ /// the legacy way of passing a pointer reference to the isolate.
51+ test ('single store using reference' , () async {
52+ final storeCreator = (dynamic msg) =>
53+ Store .fromReference (getObjectBoxModel (), msg as ByteData );
54+ await testUsingStoreFromIsolate (storeCreator, (env) => env.store.reference);
55+ });
6556
66- // Receive the SendPort from the Isolate
67- SendPort sendPort = await sendPortCompleter.future;
57+ /// Work with a single store across multiple isolates using
58+ /// the directory path to attach to an existing store.
59+ test ('single store using attach' , () async {
60+ final storeCreator =
61+ (dynamic msg) => Store .attach (getObjectBoxModel (), msg as String );
62+ await testUsingStoreFromIsolate (storeCreator, (env) => env.dir.path);
63+ });
64+ }
6865
69- final call = (dynamic message) {
70- responseCompleter = Completer <dynamic >();
71- sendPort.send (message);
72- return responseCompleter.future;
73- };
66+ class IsolateInitMessage {
67+ SendPort sendPort;
68+ Store Function (dynamic ) storeCreator;
7469
75- // Pass the store to the isolate
76- final env = TestEnv ('isolates' );
77- expect (await call (env.store.reference), equals ('store set' ));
70+ IsolateInitMessage (this .sendPort, this .storeCreator);
71+ }
7872
79- {
80- // check simple box operations
81- expect (env.box.isEmpty (), isTrue);
82- expect (await call (['put' , 'Foo' ]), equals (1 )); // returns inserted id = 1
83- expect (env.box.get (1 )! .tString, equals ('Foo' ));
73+ Future <void > testUsingStoreFromIsolate (Store Function (dynamic ) storeCreator,
74+ dynamic Function (TestEnv ) storeRefGetter) async {
75+ final receivePort = ReceivePort ();
76+ final initMessage = IsolateInitMessage (receivePort.sendPort, storeCreator);
77+ final isolate = await Isolate .spawn (createDataIsolate, initMessage);
78+
79+ final sendPortCompleter = Completer <SendPort >();
80+ late Completer <dynamic > responseCompleter;
81+ receivePort.listen ((dynamic data) {
82+ if (data is SendPort ) {
83+ sendPortCompleter.complete (data);
84+ } else {
85+ print ('Main received: $data ' );
86+ responseCompleter.complete (data);
8487 }
88+ });
8589
86- {
87- // verify that query streams (using observers) work fine across isolates
88- final queryStream = env.box.query ().watch ();
89- // starts a subscription
90- final futureFirst = queryStream.map ((q) => q.find ()).first;
91- expect (await call (['put' , 'Bar' ]), equals (2 ));
92- List <TestEntity > found = await futureFirst.timeout (defaultTimeout);
93- expect (found.length, equals (2 ));
94- expect (found.last.tString, equals ('Bar' ));
95- }
90+ // Receive the SendPort from the Isolate
91+ SendPort sendPort = await sendPortCompleter.future;
92+
93+ final call = (dynamic message) {
94+ responseCompleter = Completer <dynamic >();
95+ sendPort.send (message);
96+ return responseCompleter.future;
97+ };
98+
99+ // FIXME Send path instead of reference when using attach.
100+ // Pass the store to the isolate
101+ final env = TestEnv ('isolates' );
102+ expect (await call (storeRefGetter (env)), equals ('store set' ));
103+
104+ {
105+ // check simple box operations
106+ expect (env.box.isEmpty (), isTrue);
107+ expect (await call (['put' , 'Foo' ]), equals (1 )); // returns inserted id = 1
108+ expect (env.box.get (1 )! .tString, equals ('Foo' ));
109+ }
110+
111+ {
112+ // verify that query streams (using observers) work fine across isolates
113+ final queryStream = env.box.query ().watch ();
114+ // starts a subscription
115+ final futureFirst = queryStream.map ((q) => q.find ()).first;
116+ expect (await call (['put' , 'Bar' ]), equals (2 ));
117+ List <TestEntity > found = await futureFirst.timeout (defaultTimeout);
118+ expect (found.length, equals (2 ));
119+ expect (found.last.tString, equals ('Bar' ));
120+ }
96121
97- expect (await call (['close' ]), equals ('done' ));
122+ expect (await call (['close' ]), equals ('done' ));
98123
99- isolate.kill ();
100- receivePort.close ();
101- env.close ();
102- });
124+ isolate.kill ();
125+ receivePort.close ();
126+ env.close ();
103127}
104128
105129// Echoes back any received message.
@@ -119,19 +143,20 @@ void echoIsolate(SendPort sendPort) async {
119143}
120144
121145// Creates data in the background, in the [Store] received as the first message.
122- void createDataIsolate (SendPort sendPort ) async {
146+ void createDataIsolate (IsolateInitMessage initMessage ) async {
123147 // Open the ReceivePort to listen for incoming messages
124148 final port = ReceivePort ();
125149
126150 // Send the port where the main isolate can contact us
151+ final sendPort = initMessage.sendPort;
127152 sendPort.send (port.sendPort);
128153
129154 Store ? store;
130155 // Listen for messages
131156 await for (final msg in port) {
132157 if (store == null ) {
133158 // first message data is Store's C pointer address
134- store = Store . fromReference ( getObjectBoxModel (), msg as ByteData );
159+ store = initMessage. storeCreator ( msg);
135160 sendPort.send ('store set' );
136161 } else {
137162 print ('Isolate received: $msg ' );
0 commit comments