diff --git a/App/app/features/db-sync/DBSyncManager.tsx b/App/app/features/db-sync/DBSyncManager.tsx
index 397f2034..bcef68db 100644
--- a/App/app/features/db-sync/DBSyncManager.tsx
+++ b/App/app/features/db-sync/DBSyncManager.tsx
@@ -15,6 +15,20 @@ import useLogger from '@app/hooks/useLogger';
import { DBSyncServerEditableData } from './slice';
+const SYNC_FILTER_DDOC_NAME = 'app_sync_v0';
+const SYNC_ONLY_PRIMARY_FILTER_NAME = 'only_primary';
+const SYNC_ONLY_IMAGES_FILTER_NAME = 'only_images';
+
+const SYNC_FILTER_DDOC = {
+ _id: `_design/${SYNC_FILTER_DDOC_NAME}`,
+ filters: {
+ [SYNC_ONLY_PRIMARY_FILTER_NAME]:
+ "function (doc) { return !doc._id.startsWith('zz'); }",
+ [SYNC_ONLY_IMAGES_FILTER_NAME]:
+ "function (doc) { return doc._id.startsWith('zz20-image'); }",
+ },
+};
+
const BATCH_SIZE = 16;
const BATCHES_LIMIT = 4;
@@ -137,6 +151,24 @@ export default function DBSyncManager() {
return null;
}
}
+
+ let createSyncFilterDDocRetries = 0;
+ while (true) {
+ try {
+ await remoteDB.get(`_design/${SYNC_FILTER_DDOC_NAME}`);
+ break;
+ } catch (e) {
+ if (createSyncFilterDDocRetries >= 5) throw e;
+ try {
+ await remoteDB.put(SYNC_FILTER_DDOC);
+ } catch (ee) {
+ if (createSyncFilterDDocRetries >= 5) throw ee;
+ await new Promise(resolve => setTimeout(resolve, 1000));
+ }
+ createSyncFilterDDocRetries += 1;
+ }
+ }
+
return remoteDB;
} catch (e) {
fLogger.error(
@@ -225,9 +257,11 @@ export default function DBSyncManager() {
params: PouchDB.Replication.SyncOptions,
server: ServerData,
{
+ filter,
onChange,
onComplete,
}: {
+ filter?: string;
onChange?: (arg: {
localDBUpdateSeq?: number | undefined;
remoteDBUpdateSeq?: number | undefined;
@@ -247,6 +281,7 @@ export default function DBSyncManager() {
const syncHandler = localDB.sync(remoteDB, {
...params,
retry: true,
+ filter,
// The patched PouchDB will accept a logger for logging during the sync
...({ logger: fLogger } as any),
});
@@ -256,21 +291,27 @@ export default function DBSyncManager() {
const lastSeq = getSeqValue(info.change.last_seq);
let localDBUpdateSeq;
let remoteDBUpdateSeq;
+ let localDBDocCount;
+ let remoteDBDocCount;
const logDetails1: any = { info, lastSeq };
const logDetails2: any = {};
try {
const localDBInfo = await localDB.info();
localDBUpdateSeq = getSeqValue(localDBInfo.update_seq);
+ localDBDocCount = localDBInfo.doc_count;
logDetails2.localDBInfo = localDBInfo;
logDetails1.localDBUpdateSeq = localDBUpdateSeq;
+ logDetails1.localDBDocCount = localDBDocCount;
} catch (e) {
logDetails1.localDBInfoError = e;
}
try {
const remoteDBInfo = await remoteDB.info();
remoteDBUpdateSeq = getSeqValue(remoteDBInfo.update_seq);
+ remoteDBDocCount = remoteDBInfo.doc_count;
logDetails2.remoteDBInfo = remoteDBInfo;
logDetails1.remoteDBUpdateSeq = remoteDBUpdateSeq;
+ logDetails1.remoteDBDocCount = remoteDBDocCount;
} catch (e) {
logDetails1.remoteDBInfoError = e;
}
@@ -279,6 +320,8 @@ export default function DBSyncManager() {
// Only update the local or remote seq based on the current operation
...(direction === 'push' ? { localDBUpdateSeq } : {}),
...(direction === 'pull' ? { remoteDBUpdateSeq } : {}),
+ localDBDocCount,
+ remoteDBDocCount,
[direction === 'push' ? 'pushLastSeq' : 'pullLastSeq']: lastSeq,
};
updateSyncProgress([server.id, payload]);
@@ -418,6 +461,7 @@ export default function DBSyncManager() {
}
if (shouldCancel) return;
dispatch(actions.dbSync.updateServerStatus([server.id, 'Syncing']));
+
startupSyncHandler = _startSync(
localDB,
remoteDB,
@@ -428,6 +472,7 @@ export default function DBSyncManager() {
},
server,
{
+ filter: `${SYNC_FILTER_DDOC_NAME}/${SYNC_ONLY_PRIMARY_FILTER_NAME}`,
onChange: assignSeqs,
onComplete: payload => {
assignSeqs(payload);
@@ -436,6 +481,60 @@ export default function DBSyncManager() {
},
},
);
+ await new Promise(resolve => {
+ startupSyncHandler?.on('complete', resolve);
+ });
+ logger.info('Start-up sync: primary data synced', {
+ function: server.id,
+ });
+ if (shouldCancel) return;
+
+ startupSyncHandler = _startSync(
+ localDB,
+ remoteDB,
+ {
+ live: false,
+ batch_size: 1,
+ batches_limit: 2,
+ },
+ server,
+ {
+ filter: `${SYNC_FILTER_DDOC_NAME}/${SYNC_ONLY_IMAGES_FILTER_NAME}`,
+ onChange: assignSeqs,
+ onComplete: payload => {
+ assignSeqs(payload);
+ initialPullLastSeq = payload.pushLastSeq;
+ initialPullLastSeq = payload.pullLastSeq;
+ },
+ },
+ );
+ await new Promise(resolve => {
+ startupSyncHandler?.on('complete', resolve);
+ });
+ logger.info('Start-up sync: images synced', {
+ function: server.id,
+ });
+ if (shouldCancel) return;
+
+ startupSyncHandler = _startSync(
+ localDB,
+ remoteDB,
+ {
+ live: false,
+ batch_size: BATCH_SIZE,
+ batches_limit: BATCHES_LIMIT,
+ },
+ server,
+ {
+ onChange: assignSeqs,
+ onComplete: payload => {
+ assignSeqs(payload);
+ initialPullLastSeq = payload.pushLastSeq;
+ initialPullLastSeq = payload.pullLastSeq;
+ },
+ },
+ );
+
startupSyncHandler.on('complete', info => {
if (shouldCancel) return;
if (
@@ -465,8 +564,8 @@ export default function DBSyncManager() {
remoteDB,
{
live: true,
- batch_size: BATCH_SIZE,
- batches_limit: BATCHES_LIMIT,
+ batch_size: 2,
+ batches_limit: 2,
},
server,
{
diff --git a/App/app/features/db-sync/screens/DBSyncServerDetailScreen.tsx b/App/app/features/db-sync/screens/DBSyncServerDetailScreen.tsx
index 16705ea6..5eb09b3d 100644
--- a/App/app/features/db-sync/screens/DBSyncServerDetailScreen.tsx
+++ b/App/app/features/db-sync/screens/DBSyncServerDetailScreen.tsx
@@ -48,6 +48,8 @@ function DBSyncServerDetailScreen({
});
}, []);
+ const [showAdvancedStatus, setShowAdvancedStatus] = useState(false);
+
return (
-
+
-
+ {!showAdvancedStatus ? (
+ setShowAdvancedStatus(true)}
+ button
+ />
+ ) : (
+ <>
+
+
+
+ >
+ )}
,
@@ -311,6 +315,8 @@ reducer.dehydrateSensitive = (state: DBSyncState) => {
remoteDBUpdateSeq: server.remoteDBUpdateSeq,
pushLastSeq: server.pushLastSeq,
pullLastSeq: server.pullLastSeq,
+ localDBDocCount: server.localDBDocCount,
+ remoteDBDocCount: server.remoteDBDocCount,
}),
),
};
diff --git a/App/app/screens/OnboardingScreen.tsx b/App/app/screens/OnboardingScreen.tsx
index d353692c..02bfb8a1 100644
--- a/App/app/screens/OnboardingScreen.tsx
+++ b/App/app/screens/OnboardingScreen.tsx
@@ -54,7 +54,6 @@ import useScrollViewAutomaticallyAdjustKeyboardInsetsFix from '@app/hooks/useScr
import Button from '@app/components/Button';
import Configuration from '@app/components/Configuration';
import FullWidthImage from '@app/components/FullWidthImage';
-import Icon from '@app/components/Icon';
import Text, { Link } from '@app/components/Text';
import UIGroup from '@app/components/UIGroup';
@@ -1445,33 +1444,6 @@ function OnboardingScreen({
return 'ERROR';
}, [syncServerStatus.lastSyncedAt, syncServerStatus.status]);
- const [initialPullLastSeq, setInitialPullLastSeq] = useState(-1);
- const initialPullLastSeqRef = useRef(initialPullLastSeq);
- initialPullLastSeqRef.current = initialPullLastSeq;
- useEffect(() => {
- if (initialPullLastSeqRef.current >= 0) {
- return;
- }
-
- if (typeof syncServerStatus.pullLastSeq === 'number') {
- setInitialPullLastSeq(syncServerStatus.pullLastSeq);
- }
- }, [syncServerStatus.pullLastSeq]);
- const initialSyncDoneProgress =
- initialPullLastSeq >= 0
- ? (syncServerStatus.pullLastSeq || 0) - initialPullLastSeq
- : syncServerStatus.pullLastSeq || 0;
- const initialSyncRemainingProgress =
- initialPullLastSeq >= 0
- ? (syncServerStatus.remoteDBUpdateSeq || 0) - initialPullLastSeq
- : syncServerStatus.remoteDBUpdateSeq || 0;
- const prevInitialSyncDoneProgress = useRef(0);
- useEffect(() => {
- if (initialSyncDoneProgress !== prevInitialSyncDoneProgress.current) {
- LayoutAnimation.configureNext(DEFAULT_LAYOUT_ANIMATION_CONFIG);
- prevInitialSyncDoneProgress.current = initialSyncDoneProgress;
- }
- }, [initialSyncDoneProgress]);
const restoreFromCouchDBScrollViewRef = useRef(null);
const { kiaTextInputProps: restoreFromCouchDBKiaTextInputProps } =
@@ -1605,15 +1577,12 @@ function OnboardingScreen({
{(() => {
if (dbSyncHasBeenSetupStatus === 'WORKING') {
- // TODO: Show progress bar
return (
<>
0
- ? initialSyncDoneProgress /
- initialSyncRemainingProgress
- : 0
+ (syncServerStatus.localDBDocCount || 0) /
+ (syncServerStatus.remoteDBDocCount || 1)
}
style={[
commonStyles.alignSelfStretch,
@@ -1628,8 +1597,9 @@ function OnboardingScreen({
commonStyles.mt2,
]}
>
- {initialSyncDoneProgress}/{initialSyncRemainingProgress}{' '}
- documents synced
+ {syncServerStatus.localDBDocCount || '?'}/
+ {syncServerStatus.remoteDBDocCount || '?'} documents
+ synced
{!isSetupNotDone && (
@@ -1690,13 +1660,13 @@ function OnboardingScreen({
},
[
backgroundColor,
+ scrollViewContentContainerPaddingTop,
dbSyncHasBeenSetupStatus,
- initialSyncDoneProgress,
- initialSyncRemainingProgress,
+ syncServerStatus.lastErrorMessage,
+ syncServerStatus.localDBDocCount,
+ syncServerStatus.remoteDBDocCount,
isSetupNotDone,
navigation,
- scrollViewContentContainerPaddingTop,
- syncServerStatus.lastErrorMessage,
],
);
const dbSyncWorkingMarkCurrentProfileAsSetupDoneEffectRef = useRef(false);
@@ -1719,7 +1689,7 @@ function OnboardingScreen({
})();
} else if (
dbSyncHasBeenSetupStatus === 'WORKING' &&
- initialSyncDoneProgress > 100
+ (syncServerStatus.localDBDocCount || 0) > 100
) {
if (dbSyncWorkingMarkCurrentProfileAsSetupDoneEffectRef.current) return;
const getConfig = getGetConfig({ db });
@@ -1744,8 +1714,8 @@ function OnboardingScreen({
dbSyncHasBeenSetupStatus,
dispatch,
navigation,
- initialSyncDoneProgress,
logger,
+ syncServerStatus.localDBDocCount,
]);
// Load form values from config