Skip to content

Commit 46d413b

Browse files
committed
Add test
1 parent b519608 commit 46d413b

File tree

3 files changed

+87
-5
lines changed

3 files changed

+87
-5
lines changed

packages/node/src/db/PowerSyncDatabase.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
7878
connector: PowerSyncBackendConnector,
7979
options: NodeAdditionalConnectionOptions
8080
): AbstractStreamingSyncImplementation {
81-
const remote = new NodeRemote(connector, this.options.logger, {
81+
const logger = this.options.logger;
82+
const remote = new NodeRemote(connector, logger, {
8283
dispatcher: options.dispatcher,
8384
...(this.options as NodePowerSyncDatabaseOptions).remoteOptions
8485
});
@@ -92,7 +93,8 @@ export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
9293
},
9394
retryDelayMs: this.options.retryDelayMs,
9495
crudUploadThrottleMs: this.options.crudUploadThrottleMs,
95-
identifier: this.database.name
96+
identifier: this.database.name,
97+
logger: logger
9698
});
9799
}
98100
}

packages/node/tests/sync.test.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { describe, vi, expect, beforeEach } from 'vitest';
2+
import util from 'node:util';
23

34
import { MockSyncService, mockSyncServiceTest, TestConnector, waitForSyncStatus } from './utils';
45
import {
56
AbstractPowerSyncDatabase,
67
BucketChecksum,
8+
createLogger,
79
OplogEntryJSON,
810
PowerSyncConnectionOptions,
911
ProgressWithOperations,
@@ -536,6 +538,84 @@ function defineSyncTests(impl: SyncClientImplementation) {
536538
expect(rows).toStrictEqual([{ name: 'from server' }]);
537539
});
538540

541+
mockSyncServiceTest('handles uploads across checkpoints', async ({ syncService }) => {
542+
const logger = createLogger('test', { logLevel: Logger.TRACE });
543+
const logMessages: string[] = [];
544+
(logger as any).invoke = (level, args) => {
545+
console.log(...args);
546+
logMessages.push(util.format(...args));
547+
};
548+
549+
// Regression test for https://github.com/powersync-ja/powersync-js/pull/665
550+
let database = await syncService.createDatabase({ logger });
551+
const connector = new TestConnector();
552+
let finishUpload: () => void;
553+
const finishUploadPromise = new Promise<void>((resolve, reject) => {
554+
finishUpload = resolve;
555+
});
556+
connector.uploadData = async (db) => {
557+
const batch = await db.getCrudBatch();
558+
if (batch != null) {
559+
await finishUploadPromise;
560+
await batch.complete();
561+
}
562+
};
563+
564+
await database.execute('INSERT INTO lists (id, name) VALUES (uuid(), ?);', ['local']);
565+
database.connect(connector, options);
566+
await vi.waitFor(() => expect(syncService.connectedListeners).toHaveLength(1));
567+
568+
syncService.pushLine({ checkpoint: { last_op_id: '1', write_checkpoint: '1', buckets: [bucket('a', 1)] } });
569+
syncService.pushLine({
570+
data: {
571+
bucket: 'a',
572+
data: [
573+
{
574+
checksum: 0,
575+
op_id: '1',
576+
op: 'PUT',
577+
object_id: '1',
578+
object_type: 'lists',
579+
data: '{"name": "s1"}'
580+
}
581+
]
582+
}
583+
});
584+
// 1. Could not apply checkpoint due to local data. We will retry [...] after that upload is completed.
585+
syncService.pushLine({ checkpoint_complete: { last_op_id: '1' } });
586+
await vi.waitFor(() => {
587+
expect(logMessages).toEqual(expect.arrayContaining([expect.stringContaining('due to local data')]));
588+
});
589+
590+
// 2. Send additional checkpoint while we're still busy uploading
591+
syncService.pushLine({ checkpoint: { last_op_id: '2', write_checkpoint: '2', buckets: [bucket('a', 2)] } });
592+
syncService.pushLine({
593+
data: {
594+
bucket: 'a',
595+
data: [
596+
{
597+
checksum: 0,
598+
op_id: '2',
599+
op: 'PUT',
600+
object_id: '2',
601+
object_type: 'lists',
602+
data: '{"name": "s2"}'
603+
}
604+
]
605+
}
606+
});
607+
syncService.pushLine({ checkpoint_complete: { last_op_id: '2' } });
608+
609+
// 3. Crud upload complete
610+
finishUpload!();
611+
612+
// 4. Ensure the database is applying the second checkpoint
613+
await vi.waitFor(async () => {
614+
const rows = await database.getAll('SELECT * FROM lists WHERE name = ?', ['s2']);
615+
expect(rows).toHaveLength(1);
616+
});
617+
});
618+
539619
mockSyncServiceTest('should update sync state incrementally', async ({ syncService }) => {
540620
const powersync = await syncService.createDatabase();
541621
powersync.connect(new TestConnector(), options);

packages/node/tests/utils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
column,
1010
NodePowerSyncDatabaseOptions,
1111
PowerSyncBackendConnector,
12-
PowerSyncConnectionOptions,
1312
PowerSyncCredentials,
1413
PowerSyncDatabase,
1514
Schema,
@@ -128,8 +127,9 @@ export const mockSyncServiceTest = tempDirectoryTest.extend<{
128127
}
129128
};
130129

131-
const newConnection = async () => {
130+
const newConnection = async (options: Partial<NodePowerSyncDatabaseOptions> = {}) => {
132131
const db = await createDatabase(tmpdir, {
132+
...options,
133133
remoteOptions: {
134134
fetchImplementation: inMemoryFetch
135135
}
@@ -156,7 +156,7 @@ export const mockSyncServiceTest = tempDirectoryTest.extend<{
156156
export interface MockSyncService {
157157
pushLine: (line: StreamingSyncLine) => void;
158158
connectedListeners: any[];
159-
createDatabase: () => Promise<PowerSyncDatabase>;
159+
createDatabase: (options?: Partial<NodePowerSyncDatabaseOptions>) => Promise<PowerSyncDatabase>;
160160
}
161161

162162
export class TestConnector implements PowerSyncBackendConnector {

0 commit comments

Comments
 (0)