@@ -19,6 +19,8 @@ import 'package:powersync_core/src/streaming_sync.dart';
19
19
import 'package:powersync_core/src/sync_status.dart' ;
20
20
import 'package:sqlite_async/sqlite3_common.dart' ;
21
21
import 'package:sqlite_async/sqlite_async.dart' ;
22
+ // ignore: implementation_imports
23
+ import 'package:sqlite_async/src/native/native_isolate_mutex.dart' ;
22
24
23
25
/// A PowerSync managed database.
24
26
///
@@ -44,6 +46,8 @@ class PowerSyncDatabaseImpl
44
46
@protected
45
47
late Future <void > isInitialized;
46
48
49
+ final SimpleMutex _syncMutex = SimpleMutex (), _crudMutex = SimpleMutex ();
50
+
47
51
@override
48
52
49
53
/// The Logger used by this [PowerSyncDatabase] .
@@ -224,7 +228,13 @@ class PowerSyncDatabaseImpl
224
228
await Isolate .spawn (
225
229
_syncIsolate,
226
230
_PowerSyncDatabaseIsolateArgs (
227
- receiveMessages.sendPort, dbRef, retryDelay, clientParams),
231
+ receiveMessages.sendPort,
232
+ dbRef,
233
+ retryDelay,
234
+ clientParams,
235
+ _crudMutex.shared,
236
+ _syncMutex.shared,
237
+ ),
228
238
debugName: 'Sync ${database .openFactory .path }' ,
229
239
onError: receiveUnhandledErrors.sendPort,
230
240
errorsAreFatal: true ,
@@ -259,16 +269,32 @@ class PowerSyncDatabaseImpl
259
269
return database.writeLock (callback,
260
270
debugContext: debugContext, lockTimeout: lockTimeout);
261
271
}
272
+
273
+ @override
274
+ Future <void > close () async {
275
+ await super .close ();
276
+
277
+ await _crudMutex.close ();
278
+ await _crudMutex.close ();
279
+ }
262
280
}
263
281
264
282
class _PowerSyncDatabaseIsolateArgs {
265
283
final SendPort sPort;
266
284
final IsolateConnectionFactory dbRef;
267
285
final Duration retryDelay;
268
286
final Map <String , dynamic >? parameters;
287
+ final SerializedMutex crudMutex;
288
+ final SerializedMutex syncMutex;
269
289
270
290
_PowerSyncDatabaseIsolateArgs (
271
- this .sPort, this .dbRef, this .retryDelay, this .parameters);
291
+ this .sPort,
292
+ this .dbRef,
293
+ this .retryDelay,
294
+ this .parameters,
295
+ this .crudMutex,
296
+ this .syncMutex,
297
+ );
272
298
}
273
299
274
300
Future <void > _syncIsolate (_PowerSyncDatabaseIsolateArgs args) async {
@@ -277,6 +303,9 @@ Future<void> _syncIsolate(_PowerSyncDatabaseIsolateArgs args) async {
277
303
StreamController <String > crudUpdateController = StreamController .broadcast ();
278
304
final upstreamDbClient = args.dbRef.upstreamPort.open ();
279
305
306
+ final crudMutex = args.crudMutex.open ();
307
+ final syncMutex = args.syncMutex.open ();
308
+
280
309
CommonDatabase ? db;
281
310
final Mutex mutex = args.dbRef.mutex.open ();
282
311
StreamingSyncImplementation ? openedStreamingSync;
@@ -294,6 +323,8 @@ Future<void> _syncIsolate(_PowerSyncDatabaseIsolateArgs args) async {
294
323
// It needs to be closed before killing the isolate
295
324
// in order to free the mutex for other operations.
296
325
await mutex.close ();
326
+ await crudMutex.close ();
327
+ await syncMutex.close ();
297
328
rPort.close ();
298
329
299
330
// TODO: If we closed our resources properly, this wouldn't be necessary...
@@ -348,14 +379,17 @@ Future<void> _syncIsolate(_PowerSyncDatabaseIsolateArgs args) async {
348
379
349
380
final storage = BucketStorage (connection);
350
381
final sync = StreamingSyncImplementation (
351
- adapter: storage,
352
- credentialsCallback: loadCredentials,
353
- invalidCredentialsCallback: invalidateCredentials,
354
- uploadCrud: uploadCrud,
355
- crudUpdateTriggerStream: crudUpdateController.stream,
356
- retryDelay: args.retryDelay,
357
- client: http.Client (),
358
- syncParameters: args.parameters);
382
+ adapter: storage,
383
+ credentialsCallback: loadCredentials,
384
+ invalidCredentialsCallback: invalidateCredentials,
385
+ uploadCrud: uploadCrud,
386
+ crudUpdateTriggerStream: crudUpdateController.stream,
387
+ retryDelay: args.retryDelay,
388
+ client: http.Client (),
389
+ syncParameters: args.parameters,
390
+ crudMutex: crudMutex,
391
+ syncMutex: syncMutex,
392
+ );
359
393
openedStreamingSync = sync ;
360
394
sync .streamingSync ();
361
395
sync .statusStream.listen ((event) {
0 commit comments