diff --git a/.changeset/metal-vans-grin.md b/.changeset/metal-vans-grin.md new file mode 100644 index 00000000..ece7c3a6 --- /dev/null +++ b/.changeset/metal-vans-grin.md @@ -0,0 +1,5 @@ +--- +'@journeyapps/powersync-sdk-common': patch +--- + +Fixed regression where watched queries would update for table changes in external (not in query) tables. diff --git a/.changeset/shaggy-apples-lick.md b/.changeset/shaggy-apples-lick.md new file mode 100644 index 00000000..fe75a78e --- /dev/null +++ b/.changeset/shaggy-apples-lick.md @@ -0,0 +1,5 @@ +--- +'@journeyapps/powersync-sdk-web': patch +--- + +Minor code cleanup for shared sync worker. diff --git a/packages/powersync-sdk-common/src/client/AbstractPowerSyncDatabase.ts b/packages/powersync-sdk-common/src/client/AbstractPowerSyncDatabase.ts index 7dec6d10..502adfa6 100644 --- a/packages/powersync-sdk-common/src/client/AbstractPowerSyncDatabase.ts +++ b/packages/powersync-sdk-common/src/client/AbstractPowerSyncDatabase.ts @@ -592,9 +592,12 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver { if (changedTables.size > 0) { - eventOptions.push({ - changedTables: [...changedTables] - }); + const intersection = Array.from(changedTables.values()).filter((change) => watchedTables.has(change)); + if (intersection.length) { + eventOptions.push({ + changedTables: intersection + }); + } } changedTables.clear(); }, diff --git a/packages/powersync-sdk-web/src/db/sync/SharedWebStreamingSyncImplementation.ts b/packages/powersync-sdk-web/src/db/sync/SharedWebStreamingSyncImplementation.ts index 706806cb..443eb9bc 100644 --- a/packages/powersync-sdk-web/src/db/sync/SharedWebStreamingSyncImplementation.ts +++ b/packages/powersync-sdk-web/src/db/sync/SharedWebStreamingSyncImplementation.ts @@ -42,8 +42,12 @@ class SharedSyncClientProvider extends AbstractSharedSyncClientProvider { }; } - uploadCrud(): Promise { - return this.options.uploadCrud(); + async uploadCrud(): Promise { + /** + * Don't return anything here, just incase something which is not + * serializable is returned from the `uploadCrud` function. + */ + await this.options.uploadCrud(); } get logger() { diff --git a/packages/powersync-sdk-web/src/worker/sync/SharedSyncImplementation.ts b/packages/powersync-sdk-web/src/worker/sync/SharedSyncImplementation.ts index d77503bf..823256c1 100644 --- a/packages/powersync-sdk-web/src/worker/sync/SharedSyncImplementation.ts +++ b/packages/powersync-sdk-web/src/worker/sync/SharedSyncImplementation.ts @@ -205,7 +205,7 @@ export class SharedSyncImplementation async disconnect() { this.abortController?.abort('Disconnected'); - this.iterateListeners((l) => l.statusChanged?.(new SyncStatus({ connected: false }))); + this.updateAllStatuses({ connected: false }); } /** diff --git a/packages/powersync-sdk-web/tests/watch.test.ts b/packages/powersync-sdk-web/tests/watch.test.ts index 15eabd82..67c399d5 100644 --- a/packages/powersync-sdk-web/tests/watch.test.ts +++ b/packages/powersync-sdk-web/tests/watch.test.ts @@ -101,4 +101,46 @@ describe('Watch Tests', () => { // There should be one initial result plus one throttled result expect(receivedUpdatesCount).equals(2); }); + + it('should only watch tables inside query', async () => { + const assetsAbortController = new AbortController(); + + const watchAssets = powersync.watch('SELECT count() AS count FROM assets', [], { + signal: assetsAbortController.signal + }); + + const customersAbortController = new AbortController(); + + const watchCustomers = powersync.watch('SELECT count() AS count FROM customers', [], { + signal: customersAbortController.signal + }); + + let receivedAssetsUpdatesCount = 0; + // Listen to assets updates + (async () => { + for await (const update of watchAssets) { + receivedAssetsUpdatesCount++; + } + })(); + + let receivedCustomersUpdatesCount = 0; + (async () => { + for await (const update of watchCustomers) { + receivedCustomersUpdatesCount++; + } + })(); + + // Create the inserts as fast as possible + await powersync.execute('INSERT INTO assets(id, make, customer_id) VALUES (uuid(), ?, ?)', ['test', uuid()]); + + await new Promise((resolve) => setTimeout(resolve, throttleDuration * 2)); + assetsAbortController.abort(); + customersAbortController.abort(); + + // There should be one initial result plus one throttled result + expect(receivedAssetsUpdatesCount).equals(2); + + // Only the initial result should have yielded. + expect(receivedCustomersUpdatesCount).equals(1); + }); });