Skip to content

Commit

Permalink
First pass of porting comments from FLutter into sdk-common
Browse files Browse the repository at this point in the history
  • Loading branch information
benitav committed Feb 8, 2024
1 parent 0f1d246 commit b3bcf01
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,25 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
this._isReadyPromise = this.initialize();
}

/**
* Schema used for the local database.
*/
get schema() {
return this._schema;
}

/**
* The underlying database.
*
* For the most part, behavior is the same whether querying on the underlying database, or on [AbstractPowerSyncDatabase]. The main difference is in update notifications: the underlying database reports updates to the underlying tables, while AbstractPowerSyncDatabase reports updates to the higher-level views.
*/
protected get database() {
return this.options.database;
}

/**
* Whether a connection to the PowerSync service is currently open.
*/
get connected() {
return this.currentStatus?.connected || false;
}
Expand Down Expand Up @@ -163,6 +174,11 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
this.iterateListeners((cb) => cb.initialized?.());
}

/**
* Replace the schema with a new version. This is for advanced use cases - typically the schema should just be specified once in the constructor.
*
* Cannot be used while connected - this should only be called before [AbstractPowerSyncDatabase.connect].
*/
async updateSchema(schema: Schema) {
if (this.abortController) {
throw new Error('Cannot update schema while connected');
Expand Down Expand Up @@ -226,6 +242,11 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
this.watchCrudUploads();
}

/**
* Close the sync connection.
*
* Use [connect] to connect again.
*/
async disconnect() {
this.abortController?.abort();
this.syncStatusListenerDisposer?.();
Expand All @@ -237,6 +258,8 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
* Use this when logging out.
* The database can still be queried after this is called, but the tables
* would be empty.
*
* To preserve data in local-only tables, set clearLocal to false.
*/
async disconnectAndClear(options = DEFAULT_DISCONNECT_CLEAR_OPTIONS) {
await this.disconnect();
Expand Down Expand Up @@ -307,7 +330,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
*
* Returns null if there is no data to upload.
*
* Use this from the [PowerSyncBackendConnector.uploadData]` callback.
* Use this from the [PowerSyncBackendConnector.uploadData] callback.
*
* Once the data have been successfully uploaded, call [CrudBatch.complete] before
* requesting the next batch.
Expand Down Expand Up @@ -446,7 +469,6 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB

/**
* Takes a read lock, without starting a transaction.
*
* In most cases, [readTransaction] should be used instead.
*/
async readLock<T>(callback: (db: DBAdapter) => Promise<T>) {
Expand All @@ -466,6 +488,12 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
});
}

/**
* Open a read-only transaction.
* TODO: Up to maxReaders read transactions can run concurrently. After that, read transactions are queued.
* Read transactions can run concurrently to a write transaction.
* Changes from any write transaction are not visible to read transactions started before it.
*/
async readTransaction<T>(
callback: (tx: Transaction) => Promise<T>,
lockTimeout: number = DEFAULT_LOCK_TIMEOUT_MS
Expand All @@ -481,6 +509,11 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
);
}

/**
* Open a read-write transaction.
* This takes a global lock - only one write transaction can execute against the database at a time.
* TODO: Statements within the transaction must be done on the provided SqliteWriteContext - attempting statements on the SqliteConnection instance will error.
*/
async writeTransaction<T>(
callback: (tx: Transaction) => Promise<T>,
lockTimeout: number = DEFAULT_LOCK_TIMEOUT_MS
Expand All @@ -496,6 +529,11 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
);
}

/**
* Execute a read query every time the source tables are modified.
* TODO: Use throttle to specify the minimum interval between queries.
* TODO: Source tables are automatically detected using `EXPLAIN QUERY PLAN`.
*/
async *watch(sql: string, parameters?: any[], options?: SQLWatchOptions): AsyncIterable<QueryResult> {
//Fetch initial data
yield await this.executeReadOnly(sql, parameters);
Expand Down Expand Up @@ -582,6 +620,9 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
});
}

/**
* TODO
*/
private async executeReadOnly(sql: string, params: any[]) {
await this.waitForReady();
return this.database.readLock((tx) => tx.execute(sql, params));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ export abstract class AbstractPowerSyncDatabaseOpenFactory {
options.logger = options.logger ?? Logger.get(`PowerSync ${this.options.dbFilename}`);
}

/**
* Schema used for the local database.
*/
get schema() {
return this.options.schema;
}
Expand Down
12 changes: 12 additions & 0 deletions packages/powersync-sdk-common/src/client/sync/bucket/CrudBatch.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
import { CrudEntry } from './CrudEntry';

/**
* TODO
*/
export class CrudBatch {
constructor(
/**
* List of client-side changes.
*/
public crud: CrudEntry[],
/**
* true if there are more changes in the local queue.
*/
public haveMore: boolean,
/**
* Call to remove the changes from the local queue, once successfully uploaded.
*/
public complete: (writeCheckpoint?: string) => Promise<void>
) {}
}
27 changes: 27 additions & 0 deletions packages/powersync-sdk-common/src/client/sync/bucket/CrudEntry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,33 @@ export type CrudEntryOutputJSON = {
data: Record<string, any>;
};

/**
* A single client-side change.
*/
export class CrudEntry {
/**
* Auto-incrementing client-side id.
*/
clientId: number;
/**
* ID of the changed row.
*/
id: string;
/**
* Type of change.
*/
op: UpdateType;
/**
* Data associated with the change.
*/
opData?: Record<string, any>;
/**
* Table that contained the change.
*/
table: string;
/**
* Auto-incrementing transaction id. This is the same for all operations within the same transaction.
*/
transactionId?: number;

static fromRow(dbRow: CrudEntryJSON) {
Expand All @@ -67,6 +88,9 @@ export class CrudEntry {
this.transactionId = transactionId;
}

/**
* TODO: Converts the change to JSON format, as required by the dev crud API.
*/
toJSON(): CrudEntryOutputJSON {
return {
op_id: this.clientId,
Expand All @@ -78,6 +102,9 @@ export class CrudEntry {
};
}

/**
* The hash code for this object.
*/
hashCode() {
return hash([this.transactionId, this.clientId, this.op, this.table, this.id, this.opData]);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
import { CrudBatch } from './CrudBatch';
import { CrudEntry } from './CrudEntry';

/**
* TODO
*/
export class CrudTransaction extends CrudBatch {
constructor(
/**
* List of client-side changes.
*/
public crud: CrudEntry[],
/**
* Call to remove the changes from the local queue, once successfully uploaded.
*/
public complete: (checkpoint?: string) => Promise<void>,
/**
* Unique transaction id.
*/
public transactionId?: number
) {
super(crud, false, complete);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ export class SqliteBucketStorage implements BucketStorageAdapter {

/**
* Mark a bucket for deletion.
*
* @param bucket
*/
private async deleteBucket(bucket: string) {
// Delete a bucket, but allow it to be re-created.
Expand Down
9 changes: 9 additions & 0 deletions packages/powersync-sdk-common/src/db/crud/SyncStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,23 @@ export type SyncStatusOptions = {
export class SyncStatus {
constructor(protected options: SyncStatusOptions) {}

/**
* true if currently connected.
*/
get connected() {
return this.options.connected ?? false;
}

/**
* TODO
*/
get lastSyncedAt() {
return this.options.lastSyncedAt;
}

/**
* TODO
*/
get dataFlowStatus() {
return (
this.options.dataFlow ?? {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
export class UploadQueueStats {
constructor(
/**
* Number of records in the upload queue.
*/
public count: number,
/**
* Size of the upload queue in bytes.
*/
public size: number = null
) {}

Expand Down

0 comments on commit b3bcf01

Please sign in to comment.