From ebd10a43d2fc16eb4025a8286c80a47f86b165f0 Mon Sep 17 00:00:00 2001 From: Nolan Lawson Date: Thu, 29 Aug 2019 18:41:36 -0700 Subject: [PATCH] perf: fetch lists from database on page load (#1450) * perf: fetch lists from database on page load follow-up to #1448, I would like for there not to be a flash on the /community page where the lists suddenly load in, but I would still like to avoid the network request if possible. So when the page first loads, we can load the lists from the database and only fetch them from the network if not in the cache. * add comment --- src/routes/_actions/lists.js | 14 +++++++++++--- .../_store/observers/instanceObservers.js | 2 ++ src/routes/_utils/sync.js | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/routes/_actions/lists.js b/src/routes/_actions/lists.js index 8dba682b..96a04c82 100644 --- a/src/routes/_actions/lists.js +++ b/src/routes/_actions/lists.js @@ -1,13 +1,13 @@ import { store } from '../_store/store' import { getLists } from '../_api/lists' -import { cacheFirstUpdateAfter } from '../_utils/sync' +import { cacheFirstUpdateAfter, cacheFirstUpdateOnlyIfNotInCache } from '../_utils/sync' import { database } from '../_database/database' -export async function updateListsForInstance (instanceName) { +async function syncLists (instanceName, syncMethod) { const { loggedInInstances } = store.get() const accessToken = loggedInInstances[instanceName].access_token - await cacheFirstUpdateAfter( + await syncMethod( () => getLists(instanceName, accessToken), () => database.getLists(instanceName), lists => database.setLists(instanceName, lists), @@ -18,3 +18,11 @@ export async function updateListsForInstance (instanceName) { } ) } + +export async function updateListsForInstance (instanceName) { + await syncLists(instanceName, cacheFirstUpdateAfter) +} + +export async function setupListsForInstance (instanceName) { + await syncLists(instanceName, cacheFirstUpdateOnlyIfNotInCache) +} diff --git a/src/routes/_store/observers/instanceObservers.js b/src/routes/_store/observers/instanceObservers.js index 80b98ac4..a17dcd56 100644 --- a/src/routes/_store/observers/instanceObservers.js +++ b/src/routes/_store/observers/instanceObservers.js @@ -1,4 +1,5 @@ import { updateInstanceInfo, updateVerifyCredentialsForInstance } from '../../_actions/instances' +import { setupListsForInstance } from '../../_actions/lists' import { createStream } from '../../_actions/stream/streaming' import { updatePushSubscriptionForInstance } from '../../_actions/pushSubscription' import { updateCustomEmojiForInstance } from '../../_actions/emoji' @@ -41,6 +42,7 @@ async function doRefreshInstanceDataAndStream (store, instanceName) { async function refreshInstanceData (instanceName) { // these are all low-priority scheduleIdleTask(() => updateCustomEmojiForInstance(instanceName)) + scheduleIdleTask(() => setupListsForInstance(instanceName)) scheduleIdleTask(() => updatePushSubscriptionForInstance(instanceName)) // these are the only critical ones diff --git a/src/routes/_utils/sync.js b/src/routes/_utils/sync.js index 8c7ce059..ec511bb5 100644 --- a/src/routes/_utils/sync.js +++ b/src/routes/_utils/sync.js @@ -20,3 +20,21 @@ export async function cacheFirstUpdateAfter (networkFetcher, dbFetcher, dbUpdate } } } + +// Try the cache first. If we get a hit, set the state and do nothing. If we don't get a cache hit, +// then go to the network, update the cache, and set the state. +export async function cacheFirstUpdateOnlyIfNotInCache (networkFetcher, dbFetcher, dbUpdater, stateSetter) { + let dbResponse + try { + dbResponse = await dbFetcher() + } catch (err) { + console.error('ignored DB error', err) + } + if (dbResponse) { + stateSetter(dbResponse) + } else { + const networkResponse = await networkFetcher() + /* no await */ dbUpdater(networkResponse) + stateSetter(networkResponse) + } +}