Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue login without sync #1977

Merged
merged 2 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 32 additions & 28 deletions addons/dexie-cloud/src/dexie-cloud-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
DBRealmMember,
getDbNameFromDbUrl,
} from 'dexie-cloud-common';
import { BehaviorSubject, combineLatest, from, fromEvent, Subject } from 'rxjs';
import { BehaviorSubject, combineLatest, firstValueFrom, from, fromEvent, Subject } from 'rxjs';
import { filter, map, skip, startWith, switchMap, take } from 'rxjs/operators';
import { login } from './authentication/login';
import { UNAUTHORIZED_USER } from './authentication/UNAUTHORIZED_USER';
Expand Down Expand Up @@ -174,16 +174,15 @@ export function dexieCloud(dexie: Dexie) {
const syncState = db.cloud.persistedSyncState.value;
triggerSync(db, purpose);
if (wait) {
const newSyncState = await db.cloud.persistedSyncState
.pipe(
const newSyncState = await firstValueFrom(
db.cloud.persistedSyncState.pipe(
filter(
(newSyncState) =>
newSyncState?.timestamp != null &&
(!syncState || newSyncState.timestamp > syncState.timestamp!)
),
take(1)
)
)
.toPromise();
);
if (newSyncState?.error) {
throw new Error(`Sync error: ` + newSyncState.error);
}
Expand All @@ -193,23 +192,20 @@ export function dexieCloud(dexie: Dexie) {
triggerSync(db, purpose);
if (wait) {
console.debug('db.cloud.login() is waiting for sync completion...');
await from(
liveQuery(async () => {
const syncNeeded = await isSyncNeeded(db);
const newSyncState = await db.getPersistedSyncState();
if (
newSyncState?.timestamp !== syncState?.timestamp &&
newSyncState?.error
)
throw new Error(`Sync error: ` + newSyncState.error);
return syncNeeded;
})
)
.pipe(
filter((isNeeded) => !isNeeded),
take(1)
)
.toPromise();
await firstValueFrom(
from(
liveQuery(async () => {
const syncNeeded = await isSyncNeeded(db);
const newSyncState = await db.getPersistedSyncState();
if (
newSyncState?.timestamp !== syncState?.timestamp &&
newSyncState?.error
)
throw new Error(`Sync error: ` + newSyncState.error);
return syncNeeded;
})
).pipe(filter((isNeeded) => !isNeeded))
);
console.debug(
'Done waiting for sync completion because we have nothing to push anymore'
);
Expand Down Expand Up @@ -277,7 +273,7 @@ export function dexieCloud(dexie: Dexie) {
? await navigator.serviceWorker.getRegistrations()
: [];

const initiallySynced = await db.transaction(
const [initiallySynced, lastSyncedRealms] = await db.transaction(
'rw',
db.$syncState,
async () => {
Expand Down Expand Up @@ -362,7 +358,7 @@ export function dexieCloud(dexie: Dexie) {
// Let's assign all props as the newPersistedSchems should be what we should be working with.
Object.assign(schema, newPersistedSchema);
}
return persistedSyncState?.initiallySynced;
return [persistedSyncState?.initiallySynced, persistedSyncState?.realms];
}
);

Expand Down Expand Up @@ -393,20 +389,28 @@ export function dexieCloud(dexie: Dexie) {
// with things from the database and not just the default values.
// This is so that when db.open() completes, user should be safe
// to subscribe to these observables and get actual data.
await combineLatest([
await firstValueFrom(combineLatest([
currentUserEmitter.pipe(skip(1), take(1)),
db.cloud.persistedSyncState.pipe(skip(1), take(1)),
]).toPromise();
]));
}

// HERE: If requireAuth, do athentication now.
let changedUser = false;
const user = await db.getCurrentUser();
if (db.cloud.options?.requireAuth) {
const user = await db.getCurrentUser();
if (!user.isLoggedIn) {
changedUser = await login(db);
}
}
if (user.isLoggedIn && (!lastSyncedRealms || !lastSyncedRealms.includes(user.userId!))) {
// User has been logged in but this is not reflected in the sync state.
// This can happen if page is reloaded after login but before the sync call following
// the login was complete.
// The user is to be viewed as changed becuase current syncState does not reflect the presence
// of the logged-in user.
changedUser = true; // Set changedUser to true to trigger a pull-sync later down.
}

if (localSyncWorker) localSyncWorker.stop();
localSyncWorker = null;
Expand Down
4 changes: 2 additions & 2 deletions addons/dexie-cloud/src/sync/connectWebSocket.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BehaviorSubject, from, Observable, of, throwError } from 'rxjs';
import { BehaviorSubject, firstValueFrom, from, Observable, of, throwError } from 'rxjs';
import {
catchError,
debounceTime,
Expand Down Expand Up @@ -39,7 +39,7 @@ async function waitAndReconnectWhenUserDoesSomething(error: Error) {
await sleep(3000);
// Wait til user does something (move mouse, tap, scroll, click etc)
console.debug('waiting for someone to do something');
await userDoesSomething.pipe(take(1)).toPromise();
await firstValueFrom(userDoesSomething);
console.debug('someone did something!');
}

Expand Down
11 changes: 5 additions & 6 deletions addons/dexie-cloud/src/sync/messagesFromServerQueue.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BehaviorSubject } from 'rxjs';
import { BehaviorSubject, firstValueFrom } from 'rxjs';
import { filter, take } from 'rxjs/operators';
import { DexieCloudDB } from '../db/DexieCloudDB';
import { WSConnectionMsg } from '../WSObservable';
Expand Down Expand Up @@ -73,12 +73,11 @@ export function MessagesFromServerConsumer(db: DexieCloudDB) {
// If the sync worker or service worker is syncing, wait 'til thei're done.
// It's no need to have two channels at the same time - even though it wouldnt
// be a problem - this is an optimization.
await db.cloud.syncState
.pipe(
filter(({ phase }) => phase === 'in-sync' || phase === 'error'),
take(1)
await firstValueFrom(
db.cloud.syncState.pipe(
filter(({ phase }) => phase === 'in-sync' || phase === 'error')
)
.toPromise();
);
console.debug('processing msg', msg);
const persistedSyncState = db.cloud.persistedSyncState.value;
//syncState.
Expand Down
Loading