clean up actions, implement cache-first sync strategy

This commit is contained in:
Nolan Lawson 2018-02-08 17:51:48 -08:00
parent 1d25fa641e
commit fee954bf27
14 changed files with 69 additions and 67 deletions

View file

@ -1,6 +1,6 @@
import { getAccount, getRelationship } from '../../_api/user' import { getAccount, getRelationship } from '../_api/user'
import { database } from '../../_database/database' import { database } from '../_database/database'
import { store } from '../../_store/store' import { store } from '../_store/store'
async function updateAccount(accountId, instanceName, accessToken) { async function updateAccount(accountId, instanceName, accessToken) {
let localPromise = database.getAccount(instanceName, accountId) let localPromise = database.getAccount(instanceName, accountId)

View file

@ -1,10 +1,10 @@
import { getAccessTokenFromAuthCode, registerApplication, generateAuthLink } from '../../../_api/oauth' import { getAccessTokenFromAuthCode, registerApplication, generateAuthLink } from '../_api/oauth'
import { getInstanceInfo } from '../../../_api/instance' import { getInstanceInfo } from '../_api/instance'
import { goto } from 'sapper/runtime.js' import { goto } from 'sapper/runtime.js'
import { switchToTheme } from '../../../_utils/themeEngine' import { switchToTheme } from '../_utils/themeEngine'
import { database } from '../../../_database/database' import { database } from '../_database/database'
import { store } from '../../../_store/store' import { store } from '../_store/store'
import { updateVerifyCredentialsForInstance } from './[instanceName]' import { updateVerifyCredentialsForInstance } from './instances'
const REDIRECT_URI = (typeof location !== 'undefined' ? const REDIRECT_URI = (typeof location !== 'undefined' ?
location.origin : 'https://pinafore.social') + '/settings/instances/add' location.origin : 'https://pinafore.social') + '/settings/instances/add'

View file

@ -1,10 +1,10 @@
import { getVerifyCredentials } from '../../../_api/user' import { getVerifyCredentials } from '../_api/user'
import { store } from '../../../_store/store' import { store } from '../_store/store'
import { switchToTheme } from '../../../_utils/themeEngine' import { switchToTheme } from '../_utils/themeEngine'
import { toast } from '../../../_utils/toast' import { toast } from '../_utils/toast'
import { database } from '../../../_database/database' import { database } from '../_database/database'
import { goto } from 'sapper/runtime.js' import { goto } from 'sapper/runtime.js'
import pAny from 'p-any' import { cacheFirstUpdateAfter } from '../_utils/sync'
export function changeTheme(instanceName, newTheme) { export function changeTheme(instanceName, newTheme) {
let instanceThemes = store.get('instanceThemes') let instanceThemes = store.get('instanceThemes')
@ -55,14 +55,11 @@ function setStoreVerifyCredentials(instanceName, thisVerifyCredentials) {
export async function updateVerifyCredentialsForInstance(instanceName) { export async function updateVerifyCredentialsForInstance(instanceName) {
let loggedInInstances = store.get('loggedInInstances') let loggedInInstances = store.get('loggedInInstances')
let instanceData = loggedInInstances[instanceName] let accessToken = loggedInInstances[instanceName].access_token
await pAny([ await cacheFirstUpdateAfter(
database.getInstanceVerifyCredentials(instanceName).then(verifyCredentials => { () => getVerifyCredentials(instanceName, accessToken),
setStoreVerifyCredentials(instanceName, verifyCredentials) () => database.getInstanceVerifyCredentials(instanceName),
}), verifyCredentials => database.setInstanceVerifyCredentials(instanceName, verifyCredentials),
getVerifyCredentials(instanceName, instanceData.access_token).then(verifyCredentials => { verifyCredentials => setStoreVerifyCredentials(instanceName, verifyCredentials)
setStoreVerifyCredentials(instanceName, verifyCredentials) )
return database.setInstanceVerifyCredentials(instanceName, verifyCredentials)
})
])
} }

20
routes/_actions/lists.js Normal file
View file

@ -0,0 +1,20 @@
import { store } from '../_store/store'
import { database } from '../_database/database'
import { getLists } from '../_api/lists'
import { cacheFirstUpdateAfter } from '../_utils/sync'
export async function updateLists() {
let instanceName = store.get('currentInstance')
let accessToken = store.get('accessToken')
await cacheFirstUpdateAfter(
() => getLists(instanceName, accessToken),
() => database.getLists(instanceName),
lists => database.setLists(instanceName, lists),
lists => {
let instanceLists = store.get('instanceLists')
instanceLists[instanceName] = lists
store.set({instanceLists: instanceLists})
}
)
}

View file

@ -63,9 +63,6 @@ export function initializeTimeline() {
export async function setupTimeline() { export async function setupTimeline() {
mark('setupTimeline') mark('setupTimeline')
let timelineName = store.get('currentTimeline')
let instanceName = store.get('currentInstance')
let accessToken = store.get('accessToken')
if (!store.get('timelineItemIds').length) { if (!store.get('timelineItemIds').length) {
await fetchTimelineItemsAndPossiblyFallBack() await fetchTimelineItemsAndPossiblyFallBack()
} }

View file

@ -64,15 +64,8 @@
<script> <script>
import NavItem from './NavItem' import NavItem from './NavItem'
import { store } from '../_store/store' import { store } from '../_store/store'
import { fetchLists } from '../community/_actions/community'
export default { export default {
async oncreate() {
let pinnedPage = this.store.get('pinnedPage')
if (pinnedPage.startsWith('/lists')) {
await fetchLists()
}
},
store: () => store, store: () => store,
components: { components: {
NavItem NavItem

View file

@ -1,11 +1,11 @@
import { updateVerifyCredentialsForInstance } from '../settings/instances/_actions/[instanceName]' import { updateVerifyCredentialsForInstance } from '../_actions/instances'
import { fetchLists } from '../community/_actions/community' import { updateLists } from '../_actions/lists'
export function observers(store) { export function observers(store) {
store.observe('currentInstance', (currentInstance) => { store.observe('currentInstance', (currentInstance) => {
if (currentInstance) { if (currentInstance) {
updateVerifyCredentialsForInstance(currentInstance) updateVerifyCredentialsForInstance(currentInstance)
fetchLists() updateLists()
} }
}) })
} }

18
routes/_utils/sync.js Normal file
View file

@ -0,0 +1,18 @@
// Hit both the cache and the network, setting state for the cached version first,
// then the network version (as it's assumed to be fresher). Also update the db afterwards.
export async function cacheFirstUpdateAfter(networkFetcher, dbFetcher, dbUpdater, stateSetter) {
let networkPromise = networkFetcher() // kick off network request immediately
let dbResponse
try {
dbResponse = await dbFetcher()
stateSetter(dbResponse)
} finally {
let fetchAndUpdatePromise = networkPromise.then(networkResponse => {
/* no await */ dbUpdater(networkResponse)
stateSetter(networkResponse)
})
if (!dbResponse) { // no cached result available, await the network
await fetchAndUpdatePromise
}
}
}

View file

@ -31,9 +31,9 @@
import { store } from '../_store/store.js' import { store } from '../_store/store.js'
import HiddenFromSSR from '../_components/HiddenFromSSR' import HiddenFromSSR from '../_components/HiddenFromSSR'
import DynamicPageBanner from '../_components/DynamicPageBanner.html' import DynamicPageBanner from '../_components/DynamicPageBanner.html'
import { updateProfileAndRelationship } from './_actions/[accountId]' import { updateProfileAndRelationship } from '../_actions/accounts'
import AccountProfile from '../_components/AccountProfile.html' import AccountProfile from '../_components/AccountProfile.html'
import { updateVerifyCredentialsForInstance } from '../settings/instances/_actions/[instanceName]' import { updateVerifyCredentialsForInstance } from '../_actions/instances'
export default { export default {
oncreate() { oncreate() {

View file

@ -1,19 +0,0 @@
import { store } from '../../_store/store'
import pAny from 'p-any'
import { database } from '../../_database/database'
import { getLists } from '../../_api/lists'
export async function fetchLists() {
let instanceName = store.get('currentInstance')
let accessToken = store.get('accessToken')
let lists = await pAny([
getLists(instanceName, accessToken).then(lists => {
/* no await */ database.setLists(instanceName, lists)
return lists
}),
database.getLists(instanceName)
])
let instanceLists = store.get('instanceLists')
instanceLists[instanceName] = lists
store.set({instanceLists: instanceLists})
}

View file

@ -54,11 +54,11 @@
import HiddenFromSSR from '../_components/HiddenFromSSR' import HiddenFromSSR from '../_components/HiddenFromSSR'
import PageList from './_components/PageList.html' import PageList from './_components/PageList.html'
import PageListItem from './_components/PageListItem.html' import PageListItem from './_components/PageListItem.html'
import { fetchLists } from './_actions/community' import { updateLists } from '../_actions/lists'
export default { export default {
async oncreate() { async oncreate() {
await fetchLists() await updateLists()
}, },
store: () => store, store: () => store,
components: { components: {

View file

@ -25,12 +25,8 @@
import { store } from '../_store/store.js' import { store } from '../_store/store.js'
import HiddenFromSSR from '../_components/HiddenFromSSR' import HiddenFromSSR from '../_components/HiddenFromSSR'
import DynamicPageBanner from '../_components/DynamicPageBanner.html' import DynamicPageBanner from '../_components/DynamicPageBanner.html'
import { fetchLists } from '../community/_actions/community'
export default { export default {
async oncreate() {
await fetchLists()
},
computed: { computed: {
list: (params, $lists) => $lists && $lists.find(_ => _.id === params['listId']), list: (params, $lists) => $lists && $lists.find(_ => _.id === params['listId']),
listTitle: (list) => list ? list.title : '' listTitle: (list) => list ? list.title : ''

View file

@ -106,7 +106,7 @@
switchToInstance, switchToInstance,
logOutOfInstance, logOutOfInstance,
updateVerifyCredentialsForInstance updateVerifyCredentialsForInstance
} from './_actions/[instanceName]' } from '../../_actions/instances'
import { themes } from '../../_static/themes' import { themes } from '../../_static/themes'
export default { export default {

View file

@ -72,7 +72,7 @@
import SettingsLayout from '../_components/SettingsLayout.html' import SettingsLayout from '../_components/SettingsLayout.html'
import { store } from '../../_store/store' import { store } from '../../_store/store'
import LoadingMask from '../../_components/LoadingMask' import LoadingMask from '../../_components/LoadingMask'
import { logInToInstance, handleOauthCode } from './_actions/add' import { logInToInstance, handleOauthCode } from '../../_actions/addInstance'
import ExternalLink from '../../_components/ExternalLink.html' import ExternalLink from '../../_components/ExternalLink.html'
export default { export default {