Skip to content

Commit

Permalink
Fix bug: dexieCloud addon did not work when
Browse files Browse the repository at this point in the history
used from within a service worker.
Observables were not setup correctly.
  • Loading branch information
dfahlander committed May 20, 2022
1 parent 33bb7f9 commit a28f2b3
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 20 deletions.
1 change: 1 addition & 0 deletions addons/dexie-cloud/src/DexieCloudAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface DexieCloudAPI {
//realms: Rx.Observable<DBRealm[]>;
//loginState: Rx.BehaviorSubject<LoginState>;
usingServiceWorker?: boolean;
isServiceWorkerDB?: boolean;

/** Login using Dexie Cloud OTP or Demo user.
*
Expand Down
1 change: 1 addition & 0 deletions addons/dexie-cloud/src/DexieCloudOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface DexieCloudOptions {
unsyncedTables?: string[];
periodicSync?: PeriodicSyncOptions;
nameSuffix?: boolean;
disableWebSocket?: boolean;
fetchTokens?: (tokenParams: {
public_key: string;
hints?: { userId?: string; email?: string };
Expand Down
24 changes: 14 additions & 10 deletions addons/dexie-cloud/src/dexie-cloud-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ export {
} from 'dexie-cloud-common';
export { Invite } from './Invite';


const DEFAULT_OPTIONS: Partial<DexieCloudOptions> = {
nameSuffix: true,
};
Expand Down Expand Up @@ -227,10 +226,12 @@ export function dexieCloud(dexie: Dexie) {
closed = false; // As Dexie calls us, we are not closed anymore. Maybe reopened? Remember db.ready event is registered with sticky flag!
const db = DexieCloudDB(dexie);
// Setup default GUI:
if (!IS_SERVICE_WORKER) {
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
if (!db.cloud.options?.customLoginGui) {
subscriptions.push(setupDefaultGUI(dexie));
}
}
if (!db.cloud.isServiceWorkerDB) {
subscriptions.push(computeSyncState(db).subscribe(dexie.cloud.syncState));
}

Expand Down Expand Up @@ -282,7 +283,10 @@ export function dexieCloud(dexie: Dexie) {
// Not configured for using service worker or no service worker
// registration exists. Don't rely on service worker to do any job.
// Use LocalSyncWorker instead.
if (db.cloud.options?.tryUseServiceWorker && !IS_SERVICE_WORKER) {
if (
db.cloud.options?.tryUseServiceWorker &&
!db.cloud.isServiceWorkerDB
) {
console.debug(
'dexie-cloud-addon: Not using service worker.',
swRegistrations.length === 0
Expand Down Expand Up @@ -339,7 +343,7 @@ export function dexieCloud(dexie: Dexie) {

// Manage CurrentUser observable:
throwIfClosed();
if (!IS_SERVICE_WORKER) {
if (!db.cloud.isServiceWorkerDB) {
subscriptions.push(
liveQuery(() => db.getCurrentUser()).subscribe(currentUserEmitter)
);
Expand Down Expand Up @@ -373,7 +377,7 @@ export function dexieCloud(dexie: Dexie) {
} else if (
db.cloud.options?.databaseUrl &&
db.cloud.schema &&
!IS_SERVICE_WORKER
!db.cloud.isServiceWorkerDB
) {
// There's no SW. Start SyncWorker instead.
localSyncWorker = LocalSyncWorker(db, db.cloud.options, db.cloud.schema!);
Expand All @@ -383,7 +387,7 @@ export function dexieCloud(dexie: Dexie) {

// Listen to online event and do sync.
throwIfClosed();
if (!IS_SERVICE_WORKER) {
if (!db.cloud.isServiceWorkerDB) {
subscriptions.push(
fromEvent(self, 'online').subscribe(() => {
console.debug('online!');
Expand All @@ -401,11 +405,11 @@ export function dexieCloud(dexie: Dexie) {
);
}

// Connect WebSocket only if we're a browser window
// Connect WebSocket unless we
if (
typeof window !== 'undefined' &&
!IS_SERVICE_WORKER &&
db.cloud.options?.databaseUrl
db.cloud.options?.databaseUrl &&
!db.cloud.options?.disableWebSocket &&
!IS_SERVICE_WORKER
) {
subscriptions.push(connectWebSocket(db));
}
Expand Down
11 changes: 7 additions & 4 deletions addons/dexie-cloud/src/service-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ function syncDB(dbName: string, purpose: 'push' | 'pull') {
syncDBSemaphore.delete(dbName + '/' + purpose);
return Promise.reject(error);
});
syncDBSemaphore.set(dbName + '/' + purpose, promise);
syncDBSemaphore.set(dbName + '/' + purpose, promise!);
}
return promise;
return promise!;

async function _syncDB(dbName: string, purpose: 'push' | 'pull') {
let db = managedDBs.get(dbName);
Expand All @@ -44,12 +44,15 @@ function syncDB(dbName: string, purpose: 'push' | 'pull') {
console.debug('Dexie Cloud SW: Creating new Dexie instance for', dbName);
const dexie = new Dexie(dbName, { addons: [dexieCloud] });
db = DexieCloudDB(dexie);
db.cloud.isServiceWorkerDB = true;
dexie.on('versionchange', stopManagingDB);
await db.dx.open(); // Makes sure db.cloud.options and db.cloud.schema are read from db,
if (!managedDBs.get(dbName)) {
if (managedDBs.get(dbName)) {
// Avoid race conditions.
managedDBs.set(dbName, db);
db.close();
return await _syncDB(dbName, purpose);
}
managedDBs.set(dbName, db);
}
if (!db.cloud.options?.databaseUrl) {
console.error(`Dexie Cloud: No databaseUrl configured`);
Expand Down
14 changes: 8 additions & 6 deletions addons/dexie-cloud/src/sync/syncIfPossible.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { performGuardedJob } from './performGuardedJob';
import { DexieCloudDB } from '../db/DexieCloudDB';
import { sync, CURRENT_SYNC_WORKER, SyncOptions } from './sync';
import { DexieCloudOptions } from '../DexieCloudOptions';
import { DexieCloudSchema } from 'dexie-cloud-common';
import { assert, DexieCloudSchema } from 'dexie-cloud-common';

const ongoingSyncs = new WeakMap<
DexieCloudDB,
Expand Down Expand Up @@ -67,16 +67,18 @@ export function syncIfPossible(

async function _syncIfPossible() {
try {
if (db.cloud.usingServiceWorker) {
if (IS_SERVICE_WORKER) {
await sync(db, cloudOptions, cloudSchema, options);
}
} else {
if (db.cloud.isServiceWorkerDB) {
// We are the dedicated sync SW:
await sync(db, cloudOptions, cloudSchema, options);
} else if (!db.cloud.usingServiceWorker) {
// We use a flow that is better suited for the case when multiple workers want to
// do the same thing.
await performGuardedJob(db, CURRENT_SYNC_WORKER, '$jobs', () =>
sync(db, cloudOptions, cloudSchema, options)
);
} else {
assert(false);
throw new Error('Internal _syncIfPossible() - invalid precondition - should not have been called.');
}
ongoingSyncs.delete(db);
console.debug('Done sync');
Expand Down

0 comments on commit a28f2b3

Please sign in to comment.