Skip to content

Commit f2ebd02

Browse files
authored
Merge pull request #266 from powersync-ja/fix-web-performance
[web] debounce update notifications
2 parents a2fa493 + 2db0e8f commit f2ebd02

File tree

4 files changed

+26
-7
lines changed

4 files changed

+26
-7
lines changed

.changeset/strange-feet-explain.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@powersync/web': patch
3+
---
4+
5+
Debounce update notifications to fix performance issue with large amounts of data synced

packages/web/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,16 @@ export class WASQLiteDBAdapter extends BaseObserver<DBAdapterListener> implement
9090

9191
this.methods = await dbOpener(this.options.dbFilename);
9292
this.methods.registerOnTableChange(
93-
Comlink.proxy((opType: number, tableName: string, rowId: number) => {
94-
this.iterateListeners((cb) => cb.tablesUpdated?.({ opType, table: tableName, rowId }));
93+
Comlink.proxy((event) => {
94+
this.iterateListeners((cb) => cb.tablesUpdated?.(event));
9595
})
9696
);
9797

9898
return;
9999
}
100100
this.methods = await _openDB(this.options.dbFilename, { useWebWorker: false });
101-
this.methods.registerOnTableChange((opType: number, tableName: string, rowId: number) => {
102-
this.iterateListeners((cb) => cb.tablesUpdated?.({ opType, table: tableName, rowId }));
101+
this.methods.registerOnTableChange((event) => {
102+
this.iterateListeners((cb) => cb.tablesUpdated?.(event));
103103
});
104104
}
105105

packages/web/src/shared/open-db.ts

+15-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import '@journeyapps/wa-sqlite';
33
import * as Comlink from 'comlink';
44
import type { DBFunctionsInterface, OnTableChangeCallback, WASQLExecuteResult } from './types';
55
import { Mutex } from 'async-mutex';
6+
import { BatchedUpdateNotification } from '@powersync/common';
67

78
let nextId = 1;
89

@@ -26,8 +27,21 @@ export async function _openDB(
2627
*/
2728
const listeners = new Map<number, OnTableChangeCallback>();
2829

30+
let updatedTables = new Set<string>();
31+
let updateTimer: any = null;
32+
33+
function fireUpdates() {
34+
updateTimer = null;
35+
const event: BatchedUpdateNotification = { tables: [...updatedTables], groupedUpdates: {}, rawUpdates: [] };
36+
updatedTables.clear();
37+
Array.from(listeners.values()).forEach((l) => l(event));
38+
}
39+
2940
sqlite3.register_table_onchange_hook(db, (opType: number, tableName: string, rowId: number) => {
30-
Array.from(listeners.values()).forEach((l) => l(opType, tableName, rowId));
41+
updatedTables.add(tableName);
42+
if (updateTimer == null) {
43+
updateTimer = setTimeout(fireUpdates, 0);
44+
}
3145
});
3246

3347
/**

packages/web/src/shared/types.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { QueryResult } from '@powersync/common';
1+
import type { BatchedUpdateNotification, QueryResult } from '@powersync/common';
22

33
export type WASQLExecuteResult = Omit<QueryResult, 'rows'> & {
44
rows: {
@@ -22,7 +22,7 @@ export type DBWorkerInterface = DBFunctionsInterface;
2222

2323
export type WASQLiteExecuteMethod = (sql: string, params?: any[]) => Promise<WASQLExecuteResult>;
2424
export type WASQLiteExecuteBatchMethod = (sql: string, params?: any[]) => Promise<WASQLExecuteResult>;
25-
export type OnTableChangeCallback = (opType: number, tableName: string, rowId: number) => void;
25+
export type OnTableChangeCallback = (event: BatchedUpdateNotification) => void;
2626
export type OpenDB = (dbFileName: string) => DBWorkerInterface;
2727

2828
export type SQLBatchTuple = [string] | [string, Array<any> | Array<Array<any>>];

0 commit comments

Comments
 (0)