Skip to content

Commit

Permalink
Avoid emitting duplicate sync status events
Browse files Browse the repository at this point in the history
  • Loading branch information
Simon Binder committed Jan 15, 2025
1 parent bd22580 commit 836dec5
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 6 deletions.
4 changes: 4 additions & 0 deletions packages/powersync_core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.1.1-dev

- Fix `statusStream` emitting the same sync status multiple times.

## 1.1.0

- Increase limit on number of columns per table to 1999.
Expand Down
17 changes: 12 additions & 5 deletions packages/powersync_core/lib/src/database/powersync_db_mixin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -148,17 +148,23 @@ mixin PowerSyncDatabaseMixin implements SqliteConnection {
}

@protected
@visibleForTesting
void setStatus(SyncStatus status) {
if (status != currentStatus) {
currentStatus = status.copyWith(
// Note that currently the streaming sync implementation will never set hasSynced.
// lastSyncedAt implies that syncing has completed at some point (hasSynced = true).
// The previous values of hasSynced should be preserved here.
// Note that currently the streaming sync implementation will never set hasSynced.
// lastSyncedAt implies that syncing has completed at some point (hasSynced = true).
// The previous values of hasSynced should be preserved here.
final newStatus = status.copyWith(
hasSynced: status.lastSyncedAt != null
? true
: status.hasSynced ?? currentStatus.hasSynced,
lastSyncedAt: status.lastSyncedAt ?? currentStatus.lastSyncedAt);
statusStreamController.add(currentStatus);
// If the absence of hasSync was the only difference, the new states would be equal
// and don't require an event. So, check again.
if (newStatus != currentStatus) {
currentStatus = newStatus;
statusStreamController.add(currentStatus);
}
}
}

Expand All @@ -181,6 +187,7 @@ mixin PowerSyncDatabaseMixin implements SqliteConnection {
await disconnect();
// Now we can close the database
await database.close();
await statusStreamController.close();
}

/// Connect to the PowerSync service, and keep the databases in sync.
Expand Down
2 changes: 1 addition & 1 deletion packages/powersync_core/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: powersync_core
version: 1.1.0
version: 1.1.1-dev
homepage: https://powersync.com
repository: https://github.com/powersync-ja/powersync.dart
description: PowerSync Dart SDK - sync engine for building local-first apps.
Expand Down
23 changes: 23 additions & 0 deletions packages/powersync_core/test/powersync_shared_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:powersync_core/powersync_core.dart';
import 'package:sqlite_async/mutex.dart';
import 'package:test/test.dart';
import 'package:uuid/parsing.dart';
Expand Down Expand Up @@ -89,5 +90,27 @@ void main() {
// Check that it is a valid uuid
UuidParsing.parseAsByteList(id);
});

test('does not emit duplicate sync status events', () async {
final db = await testUtils.setupPowerSync(path: path);
expectLater(
db.statusStream,
emitsInOrder(
[
// Manual setStatus call. hasSynced set to true because lastSyncedAt is set
isA<SyncStatus>().having((e) => e.hasSynced, 'hasSynced', true),
// Closing the database emits a disconnected status
isA<SyncStatus>().having((e) => e.connected, 'connected', false),
emitsDone
],
),
);

final status = SyncStatus(connected: true, lastSyncedAt: DateTime.now());
db.setStatus(status);
db.setStatus(status); // Should not re-emit!

await db.close();
});
});
}

0 comments on commit 836dec5

Please sign in to comment.