diff --git a/.changeset/perfect-zebras-marry.md b/.changeset/perfect-zebras-marry.md new file mode 100644 index 000000000..c21bd66ad --- /dev/null +++ b/.changeset/perfect-zebras-marry.md @@ -0,0 +1,7 @@ +--- +'@powersync/common': patch +'@powersync/web': patch +'@powersync/react-native': patch +--- + +Improved `getCrudBatch` to use a default limit of 100 CRUD entries. diff --git a/packages/common/src/client/AbstractPowerSyncDatabase.ts b/packages/common/src/client/AbstractPowerSyncDatabase.ts index d587d9760..fc2be124f 100644 --- a/packages/common/src/client/AbstractPowerSyncDatabase.ts +++ b/packages/common/src/client/AbstractPowerSyncDatabase.ts @@ -132,6 +132,8 @@ export const DEFAULT_POWERSYNC_DB_OPTIONS = { crudUploadThrottleMs: DEFAULT_CRUD_UPLOAD_THROTTLE_MS }; +export const DEFAULT_CRUD_BATCH_LIMIT = 100; + /** * Requesting nested or recursive locks can block the application in some circumstances. * This default lock timeout will act as a failsafe to throw an error if a lock cannot @@ -492,7 +494,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver { + async getCrudBatch(limit: number = DEFAULT_CRUD_BATCH_LIMIT): Promise { const result = await this.getAll( `SELECT id, tx_id, data FROM ${PSInternalTable.CRUD} ORDER BY id ASC LIMIT ?`, [limit + 1] diff --git a/packages/web/tests/crud.test.ts b/packages/web/tests/crud.test.ts index 714080b37..182548bcf 100644 --- a/packages/web/tests/crud.test.ts +++ b/packages/web/tests/crud.test.ts @@ -1,9 +1,9 @@ -import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { AbstractPowerSyncDatabase, Column, ColumnType, CrudEntry, Schema, Table, UpdateType } from '@powersync/common'; import { PowerSyncDatabase } from '@powersync/web'; +import pDefer from 'p-defer'; import { v4 as uuid } from 'uuid'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { generateTestDb } from './utils/testDb'; -import pDefer from 'p-defer'; const testId = '2290de4f-0488-4e50-abed-f8e8eb1d0b42'; @@ -311,4 +311,35 @@ describe('CRUD Tests', () => { await txPromise; expect(await r).toEqual(null); }); + + it('CRUD Batch Limits', async () => { + const initialBatch = await powersync.getCrudBatch(); + expect(initialBatch, 'Initial CRUD batch should be null').null; + + /** + * Create some items. Use Multiple transactions to demonstrate getCrudBatch does not + * group by transaction. + */ + for (let i = 0; i < 2; i++) { + await powersync.writeTransaction(async (tx) => { + for (let j = 0; j < 51; j++) { + await tx.execute(`INSERT INTO assets(id, description) VALUES(uuid(), ?)`, [`test-${i}-${j}`]); + } + }); + } + + // This should contain CRUD entries for the first and second transaction + const smallBatch = await powersync.getCrudBatch(55); + expect(smallBatch, 'CRUD items should be present').exist; + expect(smallBatch?.crud.length, 'Should only be 55 CRUD items').eq(55); + expect(smallBatch?.haveMore, 'There should be more CRUD items pending').true; + + const defaultBatch = await powersync.getCrudBatch(); + expect(defaultBatch?.crud.length, 'Should use default limit').eq(100); + expect(defaultBatch?.haveMore, 'There should be more CRUD items pending').true; + + const maxBatch = await powersync.getCrudBatch(1000); + expect(maxBatch?.crud.length, 'Should contain all created CRUD items').eq(102); + expect(maxBatch?.haveMore, 'There should not be any more pending CRUD items').false; + }); });