Skip to content

Commit 664cba3

Browse files
committed
Add sync tests
1 parent a7a17ac commit 664cba3

12 files changed

+441
-241
lines changed

packages/common/src/client/sync/bucket/SqliteBucketStorage.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,9 @@ export class SqliteBucketStorage extends BaseObserver<BucketStorageListener> imp
208208
if (result == 1) {
209209
if (priority == null) {
210210
const bucketToCount = Object.fromEntries(checkpoint.buckets.map((b) => [b.bucket, b.count]));
211-
await tx.execute('UPDATE ps_buckets SET count_since_last = 0, count_at_last = ?1->name WHERE ?1->name IS NOT NULL', [JSON.stringify(bucketToCount)]);
211+
// The two parameters could be replaced with one, but: https://github.com/powersync-ja/better-sqlite3/pull/6
212+
const jsonBucketCount = JSON.stringify(bucketToCount);
213+
await tx.execute('UPDATE ps_buckets SET count_since_last = 0, count_at_last = ?->name WHERE ?->name IS NOT NULL', [jsonBucketCount, jsonBucketCount]);
212214
}
213215

214216
return true;

packages/common/src/client/sync/stream/AbstractStreamingSyncImplementation.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,7 @@ The next upload iteration will be delayed.`);
754754
// will use by default.
755755
priority: bucket.priority ?? 3,
756756
atLast: savedProgress?.atLast ?? 0,
757-
sinceLast: savedProgress.sinceLast ?? 0,
757+
sinceLast: savedProgress?.sinceLast ?? 0,
758758
targetCount: bucket.count ?? 0,
759759
};
760760
}
@@ -780,7 +780,7 @@ The next upload iteration will be delayed.`);
780780
});
781781

782782
if (!this.syncStatus.isEqual(updatedStatus)) {
783-
this.syncStatusOptions = options;
783+
Object.assign(this.syncStatusOptions, options);
784784
this.syncStatus = updatedStatus;
785785
// Only trigger this is there was a change
786786
this.iterateListeners((cb) => cb.statusChanged?.(updatedStatus));

packages/common/src/client/sync/stream/streaming-sync-types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ export interface StreamingSyncCheckpointDiff {
102102
last_op_id: OpId;
103103
updated_buckets: BucketChecksum[];
104104
removed_buckets: string[];
105-
write_checkpoint: string;
105+
write_checkpoint?: string;
106106
};
107107
}
108108

packages/node/package.json

-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757
"@powersync/drizzle-driver": "workspace:*",
5858
"@types/async-lock": "^1.4.0",
5959
"drizzle-orm": "^0.35.2",
60-
"fetch-mock": "^12.5.2",
6160
"rollup": "4.14.3",
6261
"typescript": "^5.5.3",
6362
"vitest": "^3.0.5"

packages/node/src/db/BetterSQLite3DBAdapter.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ export class BetterSQLite3DBAdapter extends BaseObserver<DBAdapterListener> impl
6464
}
6565

6666
if (!directoryExists) {
67-
throw new Error(`The dbLocation directory at "${this.options.dbLocation}" does not exist. Please create it before opening the PowerSync database!`);
67+
throw new Error(
68+
`The dbLocation directory at "${this.options.dbLocation}" does not exist. Please create it before opening the PowerSync database!`
69+
);
6870
}
6971

7072
dbFilePath = path.join(this.options.dbLocation, dbFilePath);

packages/node/src/db/PowerSyncDatabase.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ export type NodePowerSyncDatabaseOptions = PowerSyncDatabaseOptions & {
2222
database: DBAdapter | SQLOpenFactory | NodeSQLOpenOptions;
2323
/**
2424
* Options to override how the SDK will connect to the sync service.
25-
*
25+
*
2626
* This option is intended to be used for internal tests.
2727
*/
28-
remoteOptions?: Partial<AbstractRemoteOptions>,
28+
remoteOptions?: Partial<AbstractRemoteOptions>;
2929
};
3030

3131
/**
@@ -68,7 +68,7 @@ export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
6868
const remote = new NodeRemote(
6969
connector,
7070
DEFAULT_REMOTE_LOGGER,
71-
(this.options as NodePowerSyncDatabaseOptions).remoteOptions,
71+
(this.options as NodePowerSyncDatabaseOptions).remoteOptions
7272
);
7373

7474
return new NodeStreamingSyncImplementation({

packages/node/src/db/RemoteConnection.ts

+33-8
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,43 @@ export class RemoteConnection implements LockContext {
1919
this.database = database;
2020
}
2121

22-
async executeBatch(query: string, params: any[][] = []): Promise<QueryResult> {
23-
const result = await this.database.executeBatch(query, params ?? []);
24-
return RemoteConnection.wrapQueryResult(result);
22+
/**
23+
* Runs the inner function, but appends the stack trace where this function was called. This is useful for workers
24+
* because stack traces from worker errors are otherwise unrelated to the application issue that has caused them.
25+
*/
26+
private async recoverTrace<T>(inner: () => Promise<T>): Promise<T> {
27+
const trace = {};
28+
Error.captureStackTrace(trace);
29+
30+
try {
31+
return await inner();
32+
} catch (e) {
33+
if (e instanceof Error && e.stack) {
34+
e.stack += (trace as any).stack;
35+
}
36+
37+
throw e;
38+
}
39+
}
40+
41+
executeBatch(query: string, params: any[][] = []): Promise<QueryResult> {
42+
return this.recoverTrace(async () => {
43+
const result = await this.database.executeBatch(query, params ?? []);
44+
return RemoteConnection.wrapQueryResult(result);
45+
});
2546
}
2647

27-
async execute(query: string, params?: any[] | undefined): Promise<QueryResult> {
28-
const result = await this.database.execute(query, params ?? []);
29-
return RemoteConnection.wrapQueryResult(result);
48+
execute(query: string, params?: any[] | undefined): Promise<QueryResult> {
49+
return this.recoverTrace(async () => {
50+
const result = await this.database.execute(query, params ?? []);
51+
return RemoteConnection.wrapQueryResult(result);
52+
});
3053
}
3154

32-
async executeRaw(query: string, params?: any[] | undefined): Promise<any[][]> {
33-
return await this.database.executeRaw(query, params ?? []);
55+
executeRaw(query: string, params?: any[] | undefined): Promise<any[][]> {
56+
return this.recoverTrace(async () => {
57+
return await this.database.executeRaw(query, params ?? []);
58+
});
3459
}
3560

3661
async getAll<T>(sql: string, parameters?: any[]): Promise<T[]> {

packages/node/src/sync/stream/NodeRemote.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export class NodeRemote extends AbstractRemote {
2929
) {
3030
super(connector, logger, {
3131
fetchImplementation: options?.fetchImplementation ?? new NodeFetchProvider(),
32-
...(options ?? {}),
32+
...(options ?? {})
3333
});
3434
}
3535

packages/node/tests/PowerSyncDatabase.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ databaseTest('can watch tables', async ({ database }) => {
9595
tempDirectoryTest('throws error if target directory does not exist', async ({ tmpdir }) => {
9696
const directory = path.join(tmpdir, 'some', 'nested', 'location', 'that', 'does', 'not', 'exist');
9797

98-
expect(async () => {
98+
await expect(async () => {
9999
const database = new PowerSyncDatabase({
100100
schema: AppSchema,
101101
database: {

0 commit comments

Comments
 (0)