Skip to content

Commit ecc9c22

Browse files
[Feature] Implement web sync locks (#119)
* implement sync locks
1 parent cdb6b48 commit ecc9c22

File tree

15 files changed

+97
-45
lines changed

15 files changed

+97
-45
lines changed

CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,34 @@
33
All notable changes to this project will be documented in this file.
44
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
55

6+
## 2024-07-10
7+
8+
### Changes
9+
10+
---
11+
12+
Packages with breaking changes:
13+
14+
- There are no breaking changes in this release.
15+
16+
Packages with other changes:
17+
18+
- [`powersync` - `v1.3.0-alpha.9`](#powersync---v130-alpha9)
19+
- [`powersync_attachments_helper` - `v0.3.0-alpha.4`](#powersync_attachments_helper---v030-alpha4)
20+
21+
Packages with dependency updates only:
22+
23+
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
24+
25+
- `powersync_attachments_helper` - `v0.3.0-alpha.4`
26+
27+
---
28+
29+
#### `powersync` - `v1.3.0-alpha.9`
30+
31+
- Updated sqlite_async to use Navigator locks for limiting sync stream implementions in multiple tabs
32+
33+
634
## 2024-07-04
735

836
### Changes

demos/supabase-anonymous-auth/pubspec.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ packages:
350350
path: "../../packages/powersync"
351351
relative: true
352352
source: path
353-
version: "1.3.0-alpha.7"
353+
version: "1.3.0-alpha.8"
354354
realtime_client:
355355
dependency: transitive
356356
description:
@@ -480,10 +480,10 @@ packages:
480480
dependency: "direct main"
481481
description:
482482
name: sqlite_async
483-
sha256: "7c5a9bec86b6f5b7511b9ba30974fa7ea470aee2dc0d5b7021f6321a439a8d63"
483+
sha256: "79e636c857ed43f6cd5e5be72b36967a29f785daa63ff5b078bd34f74f44cb54"
484484
url: "https://pub.dev"
485485
source: hosted
486-
version: "0.8.0"
486+
version: "0.8.1"
487487
stack_trace:
488488
dependency: transitive
489489
description:

demos/supabase-anonymous-auth/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ dependencies:
1111
flutter:
1212
sdk: flutter
1313

14-
powersync: 1.3.0-alpha.8
14+
powersync: 1.3.0-alpha.9
1515
path_provider: ^2.1.1
1616
supabase_flutter: ^2.0.2
1717
path: ^1.8.3
1818
logging: ^1.2.0
19-
sqlite_async: ^0.8.0
19+
sqlite_async: ^0.8.1
2020
universal_io: ^2.2.2
2121

2222
dev_dependencies:

demos/supabase-edge-function-auth/pubspec.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ packages:
350350
path: "../../packages/powersync"
351351
relative: true
352352
source: path
353-
version: "1.3.0-alpha.7"
353+
version: "1.3.0-alpha.8"
354354
realtime_client:
355355
dependency: transitive
356356
description:
@@ -480,10 +480,10 @@ packages:
480480
dependency: "direct main"
481481
description:
482482
name: sqlite_async
483-
sha256: "7c5a9bec86b6f5b7511b9ba30974fa7ea470aee2dc0d5b7021f6321a439a8d63"
483+
sha256: "79e636c857ed43f6cd5e5be72b36967a29f785daa63ff5b078bd34f74f44cb54"
484484
url: "https://pub.dev"
485485
source: hosted
486-
version: "0.8.0"
486+
version: "0.8.1"
487487
stack_trace:
488488
dependency: transitive
489489
description:

demos/supabase-edge-function-auth/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ dependencies:
1111
flutter:
1212
sdk: flutter
1313

14-
powersync: 1.3.0-alpha.8
14+
powersync: 1.3.0-alpha.9
1515
path_provider: ^2.1.1
1616
supabase_flutter: ^2.0.2
1717
path: ^1.8.3
1818
logging: ^1.2.0
19-
sqlite_async: ^0.8.0
19+
sqlite_async: ^0.8.1
2020
universal_io: ^2.2.2
2121

2222
dev_dependencies:

demos/supabase-simple-chat/pubspec.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ packages:
382382
path: "../../packages/powersync"
383383
relative: true
384384
source: path
385-
version: "1.3.0-alpha.7"
385+
version: "1.3.0-alpha.8"
386386
realtime_client:
387387
dependency: transitive
388388
description:
@@ -536,10 +536,10 @@ packages:
536536
dependency: transitive
537537
description:
538538
name: sqlite_async
539-
sha256: "7c5a9bec86b6f5b7511b9ba30974fa7ea470aee2dc0d5b7021f6321a439a8d63"
539+
sha256: "79e636c857ed43f6cd5e5be72b36967a29f785daa63ff5b078bd34f74f44cb54"
540540
url: "https://pub.dev"
541541
source: hosted
542-
version: "0.8.0"
542+
version: "0.8.1"
543543
stack_trace:
544544
dependency: transitive
545545
description:

demos/supabase-simple-chat/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ dependencies:
3737

3838
supabase_flutter: ^1.10.25
3939
timeago: ^3.6.0
40-
powersync: 1.3.0-alpha.8
40+
powersync: 1.3.0-alpha.9
4141
path_provider: ^2.1.1
4242
path: ^1.8.3
4343
logging: ^1.2.0

demos/supabase-todolist/pubspec.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -454,14 +454,14 @@ packages:
454454
path: "../../packages/powersync"
455455
relative: true
456456
source: path
457-
version: "1.3.0-alpha.7"
457+
version: "1.3.0-alpha.8"
458458
powersync_attachments_helper:
459459
dependency: "direct main"
460460
description:
461461
path: "../../packages/powersync_attachments_helper"
462462
relative: true
463463
source: path
464-
version: "0.3.0-alpha.2"
464+
version: "0.3.0-alpha.3"
465465
realtime_client:
466466
dependency: transitive
467467
description:
@@ -591,10 +591,10 @@ packages:
591591
dependency: "direct main"
592592
description:
593593
name: sqlite_async
594-
sha256: "7c5a9bec86b6f5b7511b9ba30974fa7ea470aee2dc0d5b7021f6321a439a8d63"
594+
sha256: "79e636c857ed43f6cd5e5be72b36967a29f785daa63ff5b078bd34f74f44cb54"
595595
url: "https://pub.dev"
596596
source: hosted
597-
version: "0.8.0"
597+
version: "0.8.1"
598598
stack_trace:
599599
dependency: transitive
600600
description:

demos/supabase-todolist/pubspec.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@ environment:
1010
dependencies:
1111
flutter:
1212
sdk: flutter
13-
powersync_attachments_helper: ^0.3.0-alpha.3
13+
powersync_attachments_helper: ^0.3.0-alpha.4
1414

15-
powersync: 1.3.0-alpha.8
15+
powersync: 1.3.0-alpha.9
1616
path_provider: ^2.1.1
1717
supabase_flutter: ^2.0.1
1818
path: ^1.8.3
1919
logging: ^1.2.0
2020
camera: ^0.10.5+7
2121
image: ^4.1.3
2222
universal_io: ^2.2.2
23-
sqlite_async: ^0.8.0
23+
sqlite_async: ^0.8.1
2424

2525
dev_dependencies:
2626
flutter_test:

packages/powersync/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 1.3.0-alpha.9
2+
3+
- Updated sqlite_async to use Navigator locks for limiting sync stream implementations in multiple tabs
4+
15
## 1.3.0-alpha.8
26

37
- **FIX**(powersync-attachements-helper): pubspec file (#29).

packages/powersync/lib/src/database/web/web_powersync_database.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,17 +134,19 @@ class PowerSyncDatabaseImpl
134134

135135
await isInitialized;
136136

137-
// TODO multitab support
137+
// TODO better multitab support
138138
final storage = BucketStorage(database);
139-
140139
final sync = StreamingSyncImplementation(
141140
adapter: storage,
142141
credentialsCallback: connector.getCredentialsCached,
143142
invalidCredentialsCallback: connector.fetchCredentials,
144143
uploadCrud: () => connector.uploadData(this),
145144
updateStream: updates,
146145
retryDelay: Duration(seconds: 3),
147-
client: FetchClient(mode: RequestMode.cors));
146+
client: FetchClient(mode: RequestMode.cors),
147+
// Only allows 1 sync implementation to run at a time per database
148+
// This should be global (across tabs) when using Navigator locks.
149+
identifier: database.openFactory.path);
148150
sync.statusStream.listen((event) {
149151
setStatus(event);
150152
});

packages/powersync/lib/src/streaming_sync.dart

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:http/http.dart' as http;
44
import 'package:powersync/src/abort_controller.dart';
55
import 'package:powersync/src/exceptions.dart';
66
import 'package:powersync/src/log_internal.dart';
7+
import 'package:sqlite_async/mutex.dart';
78

89
import 'bucket_storage.dart';
910
import 'connector.dart';
@@ -37,14 +38,22 @@ class StreamingSyncImplementation {
3738

3839
SyncStatus lastStatus = const SyncStatus();
3940

41+
final Mutex syncMutex, crudMutex;
42+
4043
StreamingSyncImplementation(
4144
{required this.adapter,
4245
required this.credentialsCallback,
4346
this.invalidCredentialsCallback,
4447
required this.uploadCrud,
4548
required this.updateStream,
4649
required this.retryDelay,
47-
required http.Client client}) {
50+
required http.Client client,
51+
52+
/// A unique identifier for this streaming sync implementation
53+
/// A good value is typically the DB file path which it will mutate when syncing.
54+
String? identifier = "unknown"})
55+
: syncMutex = Mutex(identifier: "sync-$identifier"),
56+
crudMutex = Mutex(identifier: "crud-$identifier") {
4857
_client = client;
4958
statusStream = _statusStreamController.stream;
5059
}
@@ -65,8 +74,10 @@ class StreamingSyncImplementation {
6574
await invalidCredentialsCallback!();
6675
invalidCredentials = false;
6776
}
68-
await streamingSyncIteration(abortController: abortController);
69-
// Continue immediately
77+
// Protect sync iterations with exclusivity (if a valid Mutex is provided)
78+
await syncMutex.lock(
79+
() => streamingSyncIteration(abortController: abortController),
80+
timeout: retryDelay);
7081
} catch (e, stacktrace) {
7182
final message = _syncErrorMessage(e);
7283
isolateLogger.warning('Sync error: $message', e, stacktrace);
@@ -110,21 +121,23 @@ class StreamingSyncImplementation {
110121
}
111122

112123
Future<bool> uploadCrudBatch() async {
113-
if ((await adapter.hasCrud())) {
114-
_updateStatus(uploading: true);
115-
await uploadCrud();
116-
return false;
117-
} else {
118-
// This isolate is the only one triggering
119-
final updated = await adapter.updateLocalTarget(() async {
120-
return getWriteCheckpoint();
121-
});
122-
if (updated) {
123-
_localPingController.add(null);
124-
}
124+
return crudMutex.lock(() async {
125+
if ((await adapter.hasCrud())) {
126+
_updateStatus(uploading: true);
127+
await uploadCrud();
128+
return false;
129+
} else {
130+
// This isolate is the only one triggering
131+
final updated = await adapter.updateLocalTarget(() async {
132+
return getWriteCheckpoint();
133+
});
134+
if (updated) {
135+
_localPingController.add(null);
136+
}
125137

126-
return true;
127-
}
138+
return true;
139+
}
140+
}, timeout: retryDelay);
128141
}
129142

130143
Future<String> getWriteCheckpoint() async {

packages/powersync/pubspec.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: powersync
2-
version: 1.3.0-alpha.8
2+
version: 1.3.0-alpha.9
33
homepage: https://powersync.com
44
repository: https://github.com/powersync-ja/powersync.dart
55
description: PowerSync Flutter SDK - keep PostgreSQL databases in sync with on-device SQLite databases.
@@ -10,7 +10,8 @@ dependencies:
1010
flutter:
1111
sdk: flutter
1212

13-
sqlite_async: ^0.8.0
13+
sqlite_async: ^0.8.1
14+
1415
universal_io: ^2.0.0
1516
sqlite3_flutter_libs: ^0.5.15
1617
meta: ^1.0.0

packages/powersync_attachments_helper/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.3.0-alpha.4
2+
3+
- Update a dependency to the latest release.
4+
15
## 0.3.0-alpha.3
26

37
- Update a dependency to the latest release.

packages/powersync_attachments_helper/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: powersync_attachments_helper
22
description: A helper library for handling attachments when using PowerSync.
3-
version: 0.3.0-alpha.3
3+
version: 0.3.0-alpha.4
44
repository: https://github.com/powersync-ja/powersync.dart
55
homepage: https://www.powersync.com/
66
environment:
@@ -10,7 +10,7 @@ dependencies:
1010
flutter:
1111
sdk: flutter
1212

13-
powersync: 1.3.0-alpha.8
13+
powersync: 1.3.0-alpha.9
1414
logging: ^1.2.0
1515
sqlite3: "^2.4.4"
1616
path_provider: ^2.0.13

0 commit comments

Comments
 (0)