Skip to content

Commit ac82680

Browse files
fix: diagnostics app dynamic schema (#737)
1 parent e549509 commit ac82680

File tree

5 files changed

+38
-24
lines changed

5 files changed

+38
-24
lines changed

.changeset/loud-melons-try.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@powersync/diagnostics-app': patch
3+
---
4+
5+
- Fixed bug where Rust client implementation would not update the dynamic schema after sync.
6+
- Improved dynamic schema refresh logic for all implementations. Updating the schema should now always update all dependent watched queries e.g. in the SQL Console.

tools/diagnostics-app/src/library/powersync/ConnectionManager.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ import {
1313
WebStreamingSyncImplementation,
1414
WebStreamingSyncImplementationOptions
1515
} from '@powersync/web';
16+
import React from 'react';
1617
import { safeParse } from '../safeParse/safeParse';
1718
import { DynamicSchemaManager } from './DynamicSchemaManager';
1819
import { RecordingStorageAdapter } from './RecordingStorageAdapter';
19-
import { TokenConnector } from './TokenConnector';
2020
import { RustClientInterceptor } from './RustClientInterceptor';
21-
import React from 'react';
21+
import { TokenConnector } from './TokenConnector';
2222

2323
const baseLogger = createBaseLogger();
2424
baseLogger.useDefaults();
@@ -72,8 +72,8 @@ export async function connect() {
7272
const remote = new WebRemote(connector);
7373
const adapter =
7474
client == SyncClientImplementation.JAVASCRIPT
75-
? new RecordingStorageAdapter(db.database, schemaManager)
76-
: new RustClientInterceptor(db.database, remote, schemaManager);
75+
? new RecordingStorageAdapter(db, schemaManager)
76+
: new RustClientInterceptor(db, remote, schemaManager);
7777

7878
const syncOptions: WebStreamingSyncImplementationOptions = {
7979
adapter,
@@ -99,7 +99,7 @@ export async function clearData() {
9999
await sync?.disconnect();
100100
await db.disconnectAndClear();
101101
await schemaManager.clear();
102-
await schemaManager.refreshSchema(db.database);
102+
await schemaManager.refreshSchema(db);
103103
if (connector.hasCredentials()) {
104104
const params = getParams();
105105
await sync?.connect({ params });

tools/diagnostics-app/src/library/powersync/DynamicSchemaManager.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
import { Column, ColumnType, DBAdapter, OpTypeEnum, Schema, SyncDataBatch, Table } from '@powersync/web';
1+
import {
2+
AbstractPowerSyncDatabase,
3+
Column,
4+
ColumnType,
5+
OpTypeEnum,
6+
Schema,
7+
SyncDataBatch,
8+
Table
9+
} from '@powersync/web';
210
import { AppSchema } from './AppSchema';
311
import { JsSchemaGenerator } from './JsSchemaGenerator';
412

@@ -65,10 +73,10 @@ export class DynamicSchemaManager {
6573
}
6674
}
6775

68-
async refreshSchema(db: DBAdapter) {
76+
async refreshSchema(db: AbstractPowerSyncDatabase) {
6977
if (this.dirty) {
70-
const json = this.buildSchema().toJSON();
71-
await db.execute('SELECT powersync_replace_schema(?)', [JSON.stringify(json)]);
78+
// Use the PowerSyncDatabase since this will refresh all watched queries
79+
await db.updateSchema(this.buildSchema());
7280
this.dirty = false;
7381
console.log('Updated dynamic schema:', this.tables);
7482
}

tools/diagnostics-app/src/library/powersync/RecordingStorageAdapter.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,16 @@
1-
import {
2-
AbstractPowerSyncDatabase,
3-
Checkpoint,
4-
ColumnType,
5-
DBAdapter,
6-
SqliteBucketStorage,
7-
SyncDataBatch
8-
} from '@powersync/web';
1+
import { AbstractPowerSyncDatabase, Checkpoint, ColumnType, SqliteBucketStorage, SyncDataBatch } from '@powersync/web';
92
import { DynamicSchemaManager } from './DynamicSchemaManager';
103

114
export class RecordingStorageAdapter extends SqliteBucketStorage {
12-
private rdb: DBAdapter;
5+
private rdb: AbstractPowerSyncDatabase;
136

147
public tables: Record<string, Record<string, ColumnType>> = {};
158

169
constructor(
17-
db: DBAdapter,
10+
db: AbstractPowerSyncDatabase,
1811
private schemaManager: DynamicSchemaManager
1912
) {
20-
super(db, (AbstractPowerSyncDatabase as any).transactionMutex);
13+
super(db.database, (AbstractPowerSyncDatabase as any).transactionMutex);
2114
this.rdb = db;
2215
}
2316

tools/diagnostics-app/src/library/powersync/RustClientInterceptor.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import {
44
BucketChecksum,
55
Checkpoint,
66
ColumnType,
7-
DBAdapter,
87
isStreamingSyncCheckpoint,
8+
isStreamingSyncCheckpointComplete,
99
isStreamingSyncCheckpointDiff,
10+
isStreamingSyncCheckpointPartiallyComplete,
1011
isStreamingSyncData,
1112
PowerSyncControlCommand,
1213
SqliteBucketStorage,
@@ -23,17 +24,17 @@ import { DynamicSchemaManager } from './DynamicSchemaManager';
2324
* `powersync_control` calls to decode sync lines and derive progress information.
2425
*/
2526
export class RustClientInterceptor extends SqliteBucketStorage {
26-
private rdb: DBAdapter;
27+
private rdb: AbstractPowerSyncDatabase;
2728
private lastStartedCheckpoint: Checkpoint | null = null;
2829

2930
public tables: Record<string, Record<string, ColumnType>> = {};
3031

3132
constructor(
32-
db: DBAdapter,
33+
db: AbstractPowerSyncDatabase,
3334
private remote: AbstractRemote,
3435
private schemaManager: DynamicSchemaManager
3536
) {
36-
super(db, (AbstractPowerSyncDatabase as any).transactionMutex);
37+
super(db.database, (AbstractPowerSyncDatabase as any).transactionMutex);
3738
this.rdb = db;
3839
}
3940

@@ -102,6 +103,12 @@ export class RustClientInterceptor extends SqliteBucketStorage {
102103
});
103104

104105
await this.schemaManager.updateFromOperations(batch);
106+
} else if (isStreamingSyncCheckpointPartiallyComplete(line) || isStreamingSyncCheckpointComplete(line)) {
107+
// Refresh schema asynchronously, to allow us to better measure
108+
// performance of initial sync.
109+
setTimeout(() => {
110+
this.schemaManager.refreshSchema(this.rdb);
111+
}, 60);
105112
}
106113
}
107114

0 commit comments

Comments
 (0)