Skip to content

Commit 573dfad

Browse files
Add Crud unit tests
1 parent 129c287 commit 573dfad

File tree

7 files changed

+307
-17
lines changed

7 files changed

+307
-17
lines changed

packages/lite-sdk/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@
4444
"test:exports": "attw --pack ."
4545
},
4646
"dependencies": {
47-
"ts-codec": "^1.3.0"
48-
},
49-
"devDependencies": {
50-
"@types/node": "^20.5.9",
47+
"ts-codec": "^1.3.0",
5148
"@powersync/service-jsonbig": "^0.17.11",
5249
"@powersync/service-sync-rules": "^0.29.5",
5350
"@powersync/service-core": "^1.15.8"
51+
},
52+
"devDependencies": {
53+
"@types/node": "^20.5.9"
5454
}
5555
}

packages/lite-sdk/src/client/storage/BucketStorage.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@ export type SavedProgress = {
1010
};
1111

1212
export interface LocalState {
13+
/**
14+
* The last write checkpoint that was applied to the local database.
15+
*/
1316
lastOpId: bigint;
17+
/**
18+
* The target write checkpoint that the local database is syncing to.
19+
*/
1420
targetOpId: bigint;
1521
}
1622

packages/lite-sdk/src/client/storage/MemoryBucketStorageImpl.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ export class MemoryBucketStorageImpl implements BucketStorage {
151151
return false;
152152
}
153153

154+
if (await this.crudManager?.hasCrud()) {
155+
// Still has crud data, can't update checkpoint
156+
return false;
157+
}
158+
154159
// Call the callback to get the new opId
155160
const opId = await cb();
156161

packages/lite-sdk/src/client/sync/SyncClientImpl.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export class SyncClientImpl extends BaseObserver<SyncClientListener> implements
5858
this.openStreamFn = options.streamOpener ?? openHttpStream;
5959
}
6060

61-
protected get bucketStorage(): BucketStorage {
61+
get bucketStorage(): BucketStorage {
6262
return this.options.storage;
6363
}
6464

@@ -123,9 +123,9 @@ export class SyncClientImpl extends BaseObserver<SyncClientListener> implements
123123
async checkpoint(customCheckpoint?: string): Promise<CreateCheckpointResponse> {
124124
let targetCheckpoint: string | undefined = customCheckpoint;
125125
// FIXME, could this be optimized?
126-
// If there are no crud items, we set the target to the custom checkpoint or the max op id
127-
// We then set the local target to the new checkpoint
128-
await this.bucketStorage.handleCrudUploaded(customCheckpoint);
126+
// We essentially set the target op to the max_id then if there is no crud we set it to the target later
127+
// Don't pass in `customCheckpoint` here, that makes it difficult to test if we applied it later
128+
await this.bucketStorage.handleCrudUploaded();
129129
const targetUpdated = await this.bucketStorage.updateLocalTarget(async () => {
130130
if (targetCheckpoint) {
131131
return targetCheckpoint;
@@ -317,7 +317,7 @@ export class SyncClientImpl extends BaseObserver<SyncClientListener> implements
317317

318318
// Handle various sync line types
319319
if (`checkpoint` in line) {
320-
this.options.debugMode && console.debug(`Received checkpoint`, line.checkpoint);
320+
this.options.debugMode && console.debug(`Received checkpoint`, JSON.stringify(line, null, '\t'));
321321
const bucketsToDelete = new Set<string>(syncState.bucketMap.keys());
322322
const newBuckets = new Map<string, BucketDescription>();
323323
for (const checksum of line.checkpoint.buckets) {
@@ -337,7 +337,8 @@ export class SyncClientImpl extends BaseObserver<SyncClientListener> implements
337337
downloading: true
338338
});
339339
} else if (`checkpoint_complete` in line) {
340-
this.options.debugMode && console.debug(`Received checkpoint complete`, syncState.targetCheckpoint);
340+
this.options.debugMode &&
341+
console.debug(`Received checkpoint complete`, JSON.stringify(line, null, '\t'), syncState.targetCheckpoint);
341342
const result = await this.applyCheckpoint(syncState.targetCheckpoint!);
342343
if (result.endIteration) {
343344
return;
@@ -348,7 +349,12 @@ export class SyncClientImpl extends BaseObserver<SyncClientListener> implements
348349
// Status updated in applyCheckpoint when applied successfully
349350
}
350351
} else if (`partial_checkpoint_complete` in line) {
351-
this.options.debugMode && console.debug(`Received partial checkpoint complete`, syncState.targetCheckpoint);
352+
this.options.debugMode &&
353+
console.debug(
354+
`Received partial checkpoint complete`,
355+
JSON.stringify(line, null, '\t'),
356+
syncState.targetCheckpoint
357+
);
352358
const priority = line.partial_checkpoint_complete.priority;
353359
const result = await this.bucketStorage.syncLocalDatabase(syncState.targetCheckpoint!, priority);
354360
if (!result.checkpointValid) {
@@ -363,7 +369,8 @@ export class SyncClientImpl extends BaseObserver<SyncClientListener> implements
363369
// We'll keep on downloading, but can report that this priority is synced now.
364370
}
365371
} else if (`checkpoint_diff` in line) {
366-
this.options.debugMode && console.debug(`Received checkpoint diff`, syncState.targetCheckpoint);
372+
this.options.debugMode &&
373+
console.debug(`Received checkpoint diff`, JSON.stringify(line, null, '\t'), syncState.targetCheckpoint);
367374
// TODO: It may be faster to just keep track of the diff, instead of the entire checkpoint
368375
if (syncState.targetCheckpoint == null) {
369376
throw new Error(`Checkpoint diff without previous checkpoint`);
@@ -406,7 +413,7 @@ export class SyncClientImpl extends BaseObserver<SyncClientListener> implements
406413
}
407414
await this.bucketStorage.removeBuckets(bucketsToDelete);
408415
} else if (`data` in line) {
409-
this.options.debugMode && console.debug(`Received data`, line.data);
416+
this.options.debugMode && console.debug(`Received data`, JSON.stringify(line, null, '\t'));
410417
const { data } = line;
411418
// Update status to indicate we're downloading data
412419
this.updateSyncStatus({

packages/lite-sdk/tests/powersync-lite.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ describe(`PowerSync Lite`, { timeout: Infinity }, () => {
4242
const systemDependencies = DEFAULT_SYSTEM_DEPENDENCIES();
4343
const syncClient = new SyncClientImpl({
4444
connectionRetryDelayMs: 1000,
45-
debugMode: false,
45+
debugMode: true,
4646
uploadThrottleMs: 1000,
4747
storage: new MemoryBucketStorageImpl({
4848
operationsHandlers: [syncOperationsHandler],
@@ -53,10 +53,12 @@ describe(`PowerSync Lite`, { timeout: Infinity }, () => {
5353

5454
await syncClient.connect(new TestConnector());
5555

56+
await new Promise((resolve) => setTimeout(resolve, 1000000));
57+
5658
// Long running test for demonstrating the sync client
5759
});
5860

59-
it(`should handle uploads`, async () => {
61+
it.skip(`should handle uploads`, async () => {
6062
let lastPut: SyncOperation | null = null;
6163

6264
const syncOperationsHandler: SyncOperationsHandler = {

0 commit comments

Comments
 (0)