From 656b0d27bf815c2f639098c181770f889470e596 Mon Sep 17 00:00:00 2001 From: Ldoppea Date: Tue, 26 Nov 2024 17:48:05 +0100 Subject: [PATCH 1/4] feat: Debounce PouchDB replication In #1209 we added CozyPouchLink to CozyClient's instance By default CozyPouchLink starts replicating all its database directly after being initialized This is problematic as this happens during the App's startup and so it will unnecessary slow the startup process This is unnecessary because on startup, either the app is offline and so replication cannot be done, either the app is online and so it will use the cozy-stack. So replication can be delayed We want to defer the replication to a short delay after the startup (for now 30s) --- .../authentication/services/AuthService.ts | 22 +++++++++++++++++++ src/pouchdb/getLinks.ts | 9 ++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/app/domain/authentication/services/AuthService.ts b/src/app/domain/authentication/services/AuthService.ts index 10c38fc78..58cd35ba1 100644 --- a/src/app/domain/authentication/services/AuthService.ts +++ b/src/app/domain/authentication/services/AuthService.ts @@ -2,6 +2,7 @@ import { Linking } from 'react-native' import type CozyClient from 'cozy-client' import Minilog from 'cozy-minilog' +import PouchLink from 'cozy-pouch-link' import { asyncLogoutNoClient } from '/app/domain/authentication/utils/asyncLogoutNoClient' @@ -28,8 +29,29 @@ export const handleSupportEmail = (): void => { } } +const handleLogin = (): void => { + try { + authLogger.info('Debounce replication') + if (clientInstance === null) throw new Error('No client instance set') + + const pouchLink = getPouchLink(clientInstance) + pouchLink?.startReplicationWithDebounce() + } catch (error) { + authLogger.error('Error while handling login', error) + } +} + export const startListening = (client: CozyClient): void => { authLogger.info('Start listening to cozy-client events') clientInstance = client clientInstance.on('revoked', handleTokenError) + clientInstance.on('login', handleLogin) +} + +const getPouchLink = (client?: CozyClient): PouchLink | null => { + if (!client) { + return null + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return client.links.find(link => link instanceof PouchLink) || null } diff --git a/src/pouchdb/getLinks.ts b/src/pouchdb/getLinks.ts index 78158644f..cbe4e3a38 100644 --- a/src/pouchdb/getLinks.ts +++ b/src/pouchdb/getLinks.ts @@ -12,6 +12,9 @@ import { default as PouchLink } from 'cozy-pouch-link' const log = Minilog('🔗 GetLinks') +export const REPLICATION_DEBOUNCE = 30 * 1000 // 30s +export const REPLICATION_DEBOUNCE_MAX_DELAY = 600 * 1000 // 10min + export const offlineDoctypes = [ // cozy-home 'io.cozy.accounts', @@ -37,8 +40,10 @@ export const offlineDoctypes = [ export const getLinks = (): CozyLink[] => { const pouchLinkOptions = { doctypes: offlineDoctypes, - initialSync: true, - periodicSync: true, + initialSync: false, + periodicSync: false, + syncDebounceDelayInMs: REPLICATION_DEBOUNCE, + syncDebounceMaxDelayInMs: REPLICATION_DEBOUNCE_MAX_DELAY, platform: platformReactNative, ignoreWarmup: true, doctypesReplicationOptions: Object.fromEntries( From 533f5661fb8dde311265dcc1e39efb4d3c7f14ad Mon Sep 17 00:00:00 2001 From: Ldoppea Date: Tue, 26 Nov 2024 17:48:17 +0100 Subject: [PATCH 2/4] feat: Delay important files downloading 30s after startup Downloading important files on startup may slow down the startup process, so we want to delay it (for now 30s after the startup) --- src/app/domain/io.cozy.files/importantFiles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/domain/io.cozy.files/importantFiles.ts b/src/app/domain/io.cozy.files/importantFiles.ts index 3a1d0d0f1..2054d096c 100644 --- a/src/app/domain/io.cozy.files/importantFiles.ts +++ b/src/app/domain/io.cozy.files/importantFiles.ts @@ -15,7 +15,7 @@ import { getErrorMessage } from '/libs/functions/getErrorMessage' const log = Minilog('📁 Offline Files') -const IMPORTANT_FILES_DOWNLOAD_DELAY_IN_MS = 100 +const IMPORTANT_FILES_DOWNLOAD_DELAY_IN_MS = 30 * 1000 const NB_OF_MONTH_BEFORE_EXPIRATION = 1 export const makeImportantFilesAvailableOfflineInBackground = ( From 15831d5869d379c9a358f036c1e6637b01478931 Mon Sep 17 00:00:00 2001 From: Ldoppea Date: Wed, 27 Nov 2024 18:17:21 +0100 Subject: [PATCH 3/4] feat: Delay clients `synchronize()` call 10s after startup Call to `synchronize()` may slow down the startup process but is not necessary for the app to work It is here only to update the cozy-settings's OAuth clients list to display the last connexion to the app So we chose to delay this call a short delay after the startup (for now 10s) By doing so, we may fail calling the `synchronize()` method if the user closes the app less than 10s after opening it, but as this is used only for display purpose, we chose to consider this as not-critical --- .../services/SynchronizeService.spec.ts | 3 +++ .../authentication/services/SynchronizeService.ts | 12 ++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/app/domain/authentication/services/SynchronizeService.spec.ts b/src/app/domain/authentication/services/SynchronizeService.spec.ts index 973ba518d..ec50dd640 100644 --- a/src/app/domain/authentication/services/SynchronizeService.spec.ts +++ b/src/app/domain/authentication/services/SynchronizeService.spec.ts @@ -11,6 +11,9 @@ const { synchronizeOnInit } = SynchronizeService +// @ts-expect-error TS see this as a const but we can edit it on tests runtime +SynchronizeService.SYNCHRONIZE_DELAY_IN_MS = 0 + jest.mock('cozy-client') describe('SynchronizeService', () => { diff --git a/src/app/domain/authentication/services/SynchronizeService.ts b/src/app/domain/authentication/services/SynchronizeService.ts index ba6aa0d2e..d314b8e60 100644 --- a/src/app/domain/authentication/services/SynchronizeService.ts +++ b/src/app/domain/authentication/services/SynchronizeService.ts @@ -9,6 +9,8 @@ import { saveClient } from '/libs/clientHelpers/persistClient' export const syncLog = Minilog('📱 SynchronizeService') +export const SYNCHRONIZE_DELAY_IN_MS = 10 * 1000 + export const synchronizeDevice = async (client: CozyClient): Promise => { try { await client.getStackClient().fetchJSON('POST', '/settings/synchronized') @@ -50,6 +52,12 @@ export const checkClientName = async (client: CozyClient): Promise => { } export const synchronizeOnInit = async (client: CozyClient): Promise => { - await checkClientName(client) - await synchronizeDevice(client) + return new Promise(resolve => { + // eslint-disable-next-line @typescript-eslint/no-misused-promises + setTimeout(async (): Promise => { + await checkClientName(client) + await synchronizeDevice(client) + resolve() + }, SYNCHRONIZE_DELAY_IN_MS) + }) } From 630aa428ca025ff3685f1a86c9980bd7b80dc157 Mon Sep 17 00:00:00 2001 From: Ldoppea Date: Wed, 4 Dec 2024 16:16:04 +0100 Subject: [PATCH 4/4] feat: Delay icon's caching manager 30s after startup Icons caching may slow down the startup process but is not necessary for the app to work If not called in time, this would only impact cozy-apps opening animation that will use generic icons (if never called before) or potentially old icons (in the rare cases when we update a cozy-app icon) So we chose to delay this call a short delay after the startup (for now 30s) --- src/hooks/useAppBootstrap.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hooks/useAppBootstrap.js b/src/hooks/useAppBootstrap.js index 9f82c090b..41ced75bb 100644 --- a/src/hooks/useAppBootstrap.js +++ b/src/hooks/useAppBootstrap.js @@ -25,6 +25,8 @@ import { useHomeStateContext } from '/screens/home/HomeStateProvider' const log = Minilog('useAppBootstrap') +const MANAGE_ICON_CACHE_DELAY_IN_MS = 30 * 1000 + export const useAppBootstrap = client => { const [markName] = useState(() => rnperformance.mark('useAppBootstrap')) const [initialRoute, setInitialRoute] = useState('fetching') @@ -176,7 +178,8 @@ export const useAppBootstrap = client => { return } - client && manageIconCache(client) + client && + setTimeout(() => manageIconCache(client), MANAGE_ICON_CACHE_DELAY_IN_MS) client && setSentryTag(SentryCustomTags.Instance, client.stackClient?.uri) const subscription = Linking.addEventListener('url', ({ url }) => {