Skip to content

Commit e2fab7f

Browse files
added waitForReady method
1 parent 1391a69 commit e2fab7f

File tree

3 files changed

+39
-28
lines changed

3 files changed

+39
-28
lines changed

.changeset/five-turtles-dream.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
'@journeyapps/powersync-sdk-common': patch
33
---
44

5-
- Removed `user-id` header from backend connector and remote headers
6-
- Mark PowerSync client as pending initialization before `init` has been called.
5+
- Removed `user-id` header from backend connector and remote headers.
6+
- Added `waitForReady` method on PowerSyncDatabase client which resolves once initialization is complete.

packages/powersync-sdk-common/src/client/AbstractPowerSyncDatabase.ts

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
6363
protected static transactionMutex: Mutex = new Mutex();
6464

6565
closed: boolean;
66+
ready: boolean;
6667

6768
currentStatus?: SyncStatus;
6869
syncStreamImplementation?: AbstractStreamingSyncImplementation;
@@ -71,28 +72,16 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
7172
private abortController: AbortController | null;
7273
protected bucketStorageAdapter: BucketStorageAdapter;
7374
private syncStatusListenerDisposer?: () => void;
74-
protected initialized: Promise<void>;
75+
protected _isReadyPromise: Promise<void> | null;
7576

7677
constructor(protected options: PowerSyncDatabaseOptions) {
7778
super();
7879
this.currentStatus = null;
7980
this.closed = true;
81+
this.ready = false;
8082
this.options = { ...DEFAULT_POWERSYNC_DB_OPTIONS, ...options };
8183
this.bucketStorageAdapter = this.generateBucketStorageAdapter();
8284
this.sdkVersion = '';
83-
/**
84-
* This will resolve once the DB has been initialized
85-
* This allows methods such as `execute` to await initialization before
86-
* executing statements
87-
*/
88-
this.initialized = new Promise((resolve) => {
89-
const l = this.registerListener({
90-
initialized: () => {
91-
resolve();
92-
l?.();
93-
}
94-
});
95-
});
9685
}
9786

9887
get schema() {
@@ -113,6 +102,28 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
113102

114103
protected abstract generateBucketStorageAdapter(): BucketStorageAdapter;
115104

105+
/**
106+
* @returns A promise which will resolve once initialization is completed.
107+
*/
108+
async waitForReady(): Promise<void> {
109+
if (this.ready) {
110+
return;
111+
}
112+
113+
return (
114+
this._isReadyPromise ||
115+
(this._isReadyPromise = new Promise((resolve) => {
116+
const l = this.registerListener({
117+
initialized: () => {
118+
this.ready = true;
119+
resolve();
120+
l?.();
121+
}
122+
});
123+
}))
124+
);
125+
}
126+
116127
abstract _init(): Promise<void>;
117128

118129
/**
@@ -134,7 +145,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
134145
// close connection if one is open
135146
await this.disconnect();
136147

137-
await this.initialized;
148+
await this.waitForReady();
138149
this.syncStreamImplementation = this.generateSyncStreamImplementation(connector);
139150
this.syncStatusListenerDisposer = this.syncStreamImplementation.registerListener({
140151
statusChanged: (status) => {
@@ -192,7 +203,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
192203
* must be constructed.
193204
*/
194205
async close() {
195-
await this.initialized;
206+
await this.waitForReady();
196207

197208
await this.disconnect();
198209
this.database.close();
@@ -322,31 +333,31 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
322333
* Execute a statement and optionally return results
323334
*/
324335
async execute(sql: string, parameters?: any[]) {
325-
await this.initialized;
336+
await this.waitForReady();
326337
return this.database.execute(sql, parameters);
327338
}
328339

329340
/**
330341
* Execute a read-only query and return results
331342
*/
332343
async getAll<T>(sql: string, parameters?: any[]): Promise<T[]> {
333-
await this.initialized;
344+
await this.waitForReady();
334345
return this.database.getAll(sql, parameters);
335346
}
336347

337348
/**
338349
* Execute a read-only query and return the first result, or null if the ResultSet is empty.
339350
*/
340351
async getOptional<T>(sql: string, parameters?: any[]): Promise<T | null> {
341-
await this.initialized;
352+
await this.waitForReady();
342353
return this.database.getOptional(sql, parameters);
343354
}
344355

345356
/**
346357
* Execute a read-only query and return the first result, error if the ResultSet is empty.
347358
*/
348359
async get<T>(sql: string, parameters?: any[]): Promise<T> {
349-
await this.initialized;
360+
await this.waitForReady();
350361
return this.database.get(sql, parameters);
351362
}
352363

@@ -356,7 +367,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
356367
* In most cases, [readTransaction] should be used instead.
357368
*/
358369
async readLock<T>(callback: (db: DBAdapter) => Promise<T>) {
359-
await this.initialized;
370+
await this.waitForReady();
360371
return mutexRunExclusive(AbstractPowerSyncDatabase.transactionMutex, () => callback(this.database));
361372
}
362373

@@ -365,7 +376,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
365376
* In most cases, [writeTransaction] should be used instead.
366377
*/
367378
async writeLock<T>(callback: (db: DBAdapter) => Promise<T>) {
368-
await this.initialized;
379+
await this.waitForReady();
369380
return mutexRunExclusive(AbstractPowerSyncDatabase.transactionMutex, async () => {
370381
const res = await callback(this.database);
371382
_.defer(() => this.syncStreamImplementation?.triggerCrudUpload());
@@ -377,7 +388,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
377388
callback: (tx: Transaction) => Promise<T>,
378389
lockTimeout: number = DEFAULT_LOCK_TIMEOUT_MS
379390
): Promise<T> {
380-
await this.initialized;
391+
await this.waitForReady();
381392
return this.database.readTransaction(
382393
async (tx) => {
383394
const res = await callback({ ...tx });
@@ -392,7 +403,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
392403
callback: (tx: Transaction) => Promise<T>,
393404
lockTimeout: number = DEFAULT_LOCK_TIMEOUT_MS
394405
): Promise<T> {
395-
await this.initialized;
406+
await this.waitForReady();
396407
return this.database.writeTransaction(
397408
async (tx) => {
398409
const res = await callback(tx);
@@ -478,7 +489,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
478489
}
479490

480491
private async executeReadOnly(sql: string, params: any[]) {
481-
await this.initialized;
492+
await this.waitForReady();
482493
return this.database.readLock((tx) => tx.execute(sql, params));
483494
}
484495
}

packages/powersync-sdk-react-native/src/db/PowerSyncDatabase.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
2424
adapter: this.bucketStorageAdapter,
2525
remote,
2626
uploadCrud: async () => {
27-
await this.initialized;
27+
await this.waitForReady();
2828
await connector.uploadData(this);
2929
},
3030
retryDelayMs: this.options.retryDelay

0 commit comments

Comments
 (0)