Skip to content

Commit

Permalink
update lockfile
Browse files Browse the repository at this point in the history
  • Loading branch information
stevensJourney committed Jul 29, 2024
2 parents 0b33c63 + 32e342a commit d1dffad
Show file tree
Hide file tree
Showing 7 changed files with 266 additions and 30 deletions.
6 changes: 6 additions & 0 deletions .changeset/few-hounds-return.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@powersync/common': patch
'@powersync/web': patch
---

Fix: correctly apply SQLOpen flags. This fixes an issue where `PowerSyncDatabase` constructor `flags` options were not used when opening SQLite connections in web.
2 changes: 2 additions & 0 deletions demos/example-electron/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
},
"license": "MIT",
"dependencies": {
"@emotion/react": "^11.13.0",
"@emotion/styled": "^11.13.0",
"@journeyapps/wa-sqlite": "~0.2.0",
"@mui/icons-material": "^5.15.16",
"@mui/material": "^5.15.16",
Expand Down
22 changes: 15 additions & 7 deletions packages/common/src/client/AbstractPowerSyncDatabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ import { SyncStatus } from '../db/crud/SyncStatus';
import { UploadQueueStats } from '../db/crud/UploadQueueStatus';
import { Schema } from '../db/schema/Schema';
import { BaseObserver } from '../utils/BaseObserver';
import { ControlledExecutor } from '../utils/ControlledExecutor';
import { mutexRunExclusive } from '../utils/mutex';
import { quoteIdentifier } from '../utils/strings';
import { SQLOpenFactory, SQLOpenOptions, isDBAdapter, isSQLOpenFactory, isSQLOpenOptions } from './SQLOpenFactory';
import { PowerSyncBackendConnector } from './connection/PowerSyncBackendConnector';
import { BucketStorageAdapter, PSInternalTable } from './sync/bucket/BucketStorageAdapter';
import { CrudBatch } from './sync/bucket/CrudBatch';
Expand All @@ -24,12 +26,10 @@ import { CrudTransaction } from './sync/bucket/CrudTransaction';
import {
AbstractStreamingSyncImplementation,
DEFAULT_CRUD_UPLOAD_THROTTLE_MS,
StreamingSyncImplementationListener,
PowerSyncConnectionOptions,
StreamingSyncImplementation,
PowerSyncConnectionOptions
StreamingSyncImplementationListener
} from './sync/stream/AbstractStreamingSyncImplementation';
import { ControlledExecutor } from '../utils/ControlledExecutor';
import { SQLOpenFactory, SQLOpenOptions, isDBAdapter, isSQLOpenFactory, isSQLOpenOptions } from './SQLOpenFactory';

export interface DisconnectAndClearOptions {
/** When set to false, data in local-only tables is preserved. */
Expand Down Expand Up @@ -139,6 +139,14 @@ export const DEFAULT_POWERSYNC_DB_OPTIONS = {
*/
export const DEFAULT_LOCK_TIMEOUT_MS = 120_000; // 2 mins

/**
* Tests if the input is a {@link PowerSyncDatabaseOptionsWithSettings}
* @internal
*/
export const isPowerSyncDatabaseOptionsWithSettings = (test: any): test is PowerSyncDatabaseOptionsWithSettings => {
return typeof test == 'object' && isSQLOpenOptions(test.database);
};

export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDBListener> {
/**
* Transactions should be queued in the DBAdapter, but we also want to prevent
Expand Down Expand Up @@ -182,8 +190,8 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
this._database = database;
} else if (isSQLOpenFactory(database)) {
this._database = database.openDB();
} else if (isSQLOpenOptions(database)) {
this._database = this.openDBAdapter(database);
} else if (isPowerSyncDatabaseOptionsWithSettings(options)) {
this._database = this.openDBAdapter(options);
}

this.bucketStorageAdapter = this.generateBucketStorageAdapter();
Expand Down Expand Up @@ -223,7 +231,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
/**
* Opens the DBAdapter given open options using a default open factory
*/
protected abstract openDBAdapter(options: SQLOpenOptions): DBAdapter;
protected abstract openDBAdapter(options: PowerSyncDatabaseOptionsWithSettings): DBAdapter;

protected abstract generateSyncStreamImplementation(
connector: PowerSyncBackendConnector
Expand Down
10 changes: 5 additions & 5 deletions packages/react-native/src/db/PowerSyncDatabase.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {
AbstractPowerSyncDatabase,
AbstractStreamingSyncImplementation,
PowerSyncBackendConnector,
SqliteBucketStorage,
BucketStorageAdapter,
DBAdapter,
SQLOpenOptions
PowerSyncBackendConnector,
PowerSyncDatabaseOptionsWithSettings,
SqliteBucketStorage
} from '@powersync/common';
import { ReactNativeRemote } from '../sync/stream/ReactNativeRemote';
import { ReactNativeStreamingSyncImplementation } from '../sync/stream/ReactNativeStreamingSyncImplementation';
Expand All @@ -32,8 +32,8 @@ export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
* Opens a DBAdapter using React Native Quick SQLite as the
* default SQLite open factory.
*/
protected openDBAdapter(options: SQLOpenOptions): DBAdapter {
const defaultFactory = new ReactNativeQuickSqliteOpenFactory(options);
protected openDBAdapter(options: PowerSyncDatabaseOptionsWithSettings): DBAdapter {
const defaultFactory = new ReactNativeQuickSqliteOpenFactory(options.database);
return defaultFactory.openDB();
}

Expand Down
22 changes: 12 additions & 10 deletions packages/web/src/db/PowerSyncDatabase.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
import {
type AbstractStreamingSyncImplementation,
type PowerSyncBackendConnector,
type BucketStorageAdapter,
type PowerSyncBackendConnector,
type PowerSyncCloseOptions,
type PowerSyncConnectionOptions,
AbstractPowerSyncDatabase,
SqliteBucketStorage,
DEFAULT_POWERSYNC_CLOSE_OPTIONS,
DBAdapter,
SQLOpenOptions,
DEFAULT_POWERSYNC_CLOSE_OPTIONS,
PowerSyncDatabaseOptions,
PowerSyncDatabaseOptionsWithDBAdapter,
PowerSyncDatabaseOptionsWithOpenFactory,
PowerSyncDatabaseOptionsWithSettings,
PowerSyncDatabaseOptions
SqliteBucketStorage
} from '@powersync/common';
import { Mutex } from 'async-mutex';
import { WebRemote } from './sync/WebRemote';
import { WASQLiteOpenFactory } from './adapters/wa-sqlite/WASQLiteOpenFactory';
import { DEFAULT_WEB_SQL_FLAGS, resolveWebSQLFlags, WebSQLFlags } from './adapters/web-sql-flags';
import { SharedWebStreamingSyncImplementation } from './sync/SharedWebStreamingSyncImplementation';
import { SSRStreamingSyncImplementation } from './sync/SSRWebStreamingSyncImplementation';
import { WebRemote } from './sync/WebRemote';
import {
WebStreamingSyncImplementation,
WebStreamingSyncImplementationOptions
} from './sync/WebStreamingSyncImplementation';
import { WASQLiteOpenFactory } from './adapters/wa-sqlite/WASQLiteOpenFactory';
import { DEFAULT_WEB_SQL_FLAGS, resolveWebSQLFlags, WebSQLFlags } from './adapters/web-sql-flags';

export interface WebPowerSyncFlags extends WebSQLFlags {
/**
Expand Down Expand Up @@ -92,8 +91,11 @@ export class PowerSyncDatabase extends AbstractPowerSyncDatabase {

async _initialize(): Promise<void> {}

protected openDBAdapter(options: SQLOpenOptions): DBAdapter {
const defaultFactory = new WASQLiteOpenFactory({ ...options, flags: this.resolvedFlags });
protected openDBAdapter(options: WebPowerSyncDatabaseOptionsWithSettings): DBAdapter {
const defaultFactory = new WASQLiteOpenFactory({
...options.database,
flags: resolveWebPowerSyncFlags(options.flags)
});
return defaultFactory.openDB();
}

Expand Down
87 changes: 84 additions & 3 deletions packages/web/tests/open.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { describe, expect, it } from 'vitest';
import { AbstractPowerSyncDatabase } from '@powersync/common';
import {
PowerSyncDatabase,
WASQLiteDBAdapter,
WASQLitePowerSyncDatabaseOpenFactory,
WASQLiteOpenFactory
WASQLiteOpenFactory,
WASQLitePowerSyncDatabaseOpenFactory
} from '@powersync/web';
import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
import { testSchema } from './utils/testDb';

const testId = '2290de4f-0488-4e50-abed-f8e8eb1d0b42';
Expand All @@ -18,6 +18,45 @@ export const basicTest = async (db: AbstractPowerSyncDatabase) => {
};

describe('Open Methods', () => {
let originalSharedWorker: typeof SharedWorker;
let originalWorker: typeof Worker;

const sharedWorkerProxyHandler = {
construct(target: typeof SharedWorker, args: any[]) {
const [url, options] = args;

// Call the original constructor
const instance = new target(url, options);
return instance;
}
};
const workerProxyHandler = {
construct(target: typeof Worker, args: any[]) {
const [url, options] = args;

// Call the original constructor
const instance = new target(url, options);
return instance;
}
};

beforeAll(() => {
// Store the original SharedWorker constructor
originalSharedWorker = SharedWorker;
originalWorker = Worker;

// Create a proxy to intercept the worker constructors
// The vi.SpyOn does not work well with constructors
window.SharedWorker = new Proxy(SharedWorker, sharedWorkerProxyHandler);
window.Worker = new Proxy(Worker, workerProxyHandler);
});

afterAll(() => {
// Restore Worker
window.SharedWorker = originalSharedWorker;
window.Worker = originalWorker;
});

it('Should open PowerSync clients from old factory methods', async () => {
const db = new WASQLitePowerSyncDatabaseOpenFactory({
dbFilename: `test-legacy.db`,
Expand Down Expand Up @@ -46,4 +85,46 @@ describe('Open Methods', () => {

await basicTest(db);
});

it('Should use shared worker for multiple tabs', async () => {
const sharedSpy = vi.spyOn(sharedWorkerProxyHandler, 'construct');

const db = new PowerSyncDatabase({ database: { dbFilename: 'options-test.db' }, schema: testSchema });

await basicTest(db);

expect(sharedSpy).toBeCalledTimes(1);
});

it('Should use dedicated worker when multiple tabs disabled', async () => {
const sharedSpy = vi.spyOn(sharedWorkerProxyHandler, 'construct');
const dedicatedSpy = vi.spyOn(workerProxyHandler, 'construct');

const db = new PowerSyncDatabase({
database: { dbFilename: 'options-test.db' },
schema: testSchema,
flags: { enableMultiTabs: false }
});

await basicTest(db);

expect(sharedSpy).toBeCalledTimes(0);
expect(dedicatedSpy).toBeCalledTimes(1);
});

it('Should not use workers when specified', async () => {
const sharedSpy = vi.spyOn(sharedWorkerProxyHandler, 'construct');
const dedicatedSpy = vi.spyOn(workerProxyHandler, 'construct');

const db = new PowerSyncDatabase({
database: { dbFilename: 'options-test.db' },
schema: testSchema,
flags: { useWebWorker: false }
});

await basicTest(db);

expect(sharedSpy).toBeCalledTimes(0);
expect(dedicatedSpy).toBeCalledTimes(0);
});
});
Loading

0 comments on commit d1dffad

Please sign in to comment.