Skip to content

Commit ff27d56

Browse files
committed
Fix connect() resolving early with Rust client
1 parent 8a9a5dc commit ff27d56

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

.changeset/new-readers-dance.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@powersync/common': patch
3+
---
4+
5+
Rust sync client: Fix `connect()` resolving before a connection is made.

packages/common/src/client/sync/stream/AbstractStreamingSyncImplementation.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -928,11 +928,16 @@ The next upload iteration will be delayed.`);
928928
}
929929

930930
const info = instruction.UpdateSyncStatus.status;
931+
const lastStatus = syncImplementation.syncStatus;
931932
const coreCompleteSync = info.priority_status.find((s) => s.priority == FULL_SYNC_PRIORITY);
932933
const completeSync = coreCompleteSync != null ? coreStatusToJs(coreCompleteSync) : null;
933934

934935
syncImplementation.updateSyncStatus({
935-
connected: info.connected,
936+
// The first update to the connected field should only happen when it has really changed - there's a
937+
// statusUpdated listener in connect() that will only make the promise complete once connected has changed.
938+
// We only want to apply that workaround while we're connecting because it's only relevant in the initial
939+
// connect call. Afterwards, we want to forward the sync status unchanged.
940+
connected: lastStatus.connected == info.connected && info.connecting ? undefined : info.connected,
936941
connecting: info.connecting,
937942
dataFlow: {
938943
downloading: info.downloading != null,

packages/node/tests/sync.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,27 @@ function defineSyncTests(impl: SyncClientImplementation) {
112112
connectionMethod: SyncStreamConnectionMethod.HTTP
113113
};
114114

115+
mockSyncServiceTest('connect() waits for connection', async ({ syncService }) => {
116+
const database = await syncService.createDatabase();
117+
let connectCompleted = false;
118+
database.connect(new TestConnector(), options).then(() => {
119+
connectCompleted = true;
120+
});
121+
expect(connectCompleted).toBeFalsy();
122+
123+
await vi.waitFor(() => expect(syncService.connectedListeners).toHaveLength(1));
124+
// Opening the socket is not enough, we set connected: true when the first line is received.
125+
expect(connectCompleted).toBeFalsy();
126+
127+
syncService.pushLine({
128+
checkpoint: {
129+
last_op_id: '10',
130+
buckets: [bucket('a', 10)]
131+
}
132+
});
133+
await vi.waitFor(() => connectCompleted);
134+
});
135+
115136
describe('reports progress', () => {
116137
let lastOpId = 0;
117138

0 commit comments

Comments
 (0)