From b231466fffb3eae2e6a2d288e65cdd72d01a42ba Mon Sep 17 00:00:00 2001 From: Nolan Lawson Date: Mon, 16 Apr 2018 20:56:21 -0700 Subject: [PATCH] Refactor database for better code-splitting (#144) --- routes/_actions/accounts.js | 15 +- routes/_actions/addInstance.js | 4 +- routes/_actions/addStatusOrNotification.js | 6 +- routes/_actions/compose.js | 4 +- routes/_actions/deleteStatuses.js | 6 +- routes/_actions/emoji.js | 9 +- routes/_actions/favorite.js | 6 +- routes/_actions/follow.js | 6 +- routes/_actions/instances.js | 18 +- routes/_actions/lists.js | 9 +- routes/_actions/pinnedStatuses.js | 13 +- routes/_actions/reblog.js | 4 +- routes/_actions/statuses.js | 14 +- routes/_actions/timeline.js | 13 +- .../compose/ComposeAutosuggest.html | 6 +- routes/_components/timeline/Timeline.html | 9 +- routes/_database/database.js | 3 - routes/_database/databaseCore.js | 4 - routes/_database/timelines.js | 470 ------------------ routes/_database/timelines/cacheStatus.js | 11 + routes/_database/timelines/deletion.js | 84 ++++ routes/_database/timelines/fetchAccount.js | 5 + .../_database/timelines/fetchNotification.js | 18 + routes/_database/timelines/fetchStatus.js | 17 + .../timelines/getStatusOrNotification.js | 37 ++ routes/_database/timelines/insertion.js | 122 +++++ routes/_database/timelines/lookup.js | 27 + routes/_database/timelines/pagination.js | 92 ++++ routes/_database/timelines/pinnedStatuses.js | 40 ++ routes/_database/timelines/updateStatus.js | 41 ++ 30 files changed, 588 insertions(+), 525 deletions(-) delete mode 100644 routes/_database/database.js delete mode 100644 routes/_database/databaseCore.js delete mode 100644 routes/_database/timelines.js create mode 100644 routes/_database/timelines/cacheStatus.js create mode 100644 routes/_database/timelines/deletion.js create mode 100644 routes/_database/timelines/fetchAccount.js create mode 100644 routes/_database/timelines/fetchNotification.js create mode 100644 routes/_database/timelines/fetchStatus.js create mode 100644 routes/_database/timelines/getStatusOrNotification.js create mode 100644 routes/_database/timelines/insertion.js create mode 100644 routes/_database/timelines/lookup.js create mode 100644 routes/_database/timelines/pagination.js create mode 100644 routes/_database/timelines/pinnedStatuses.js create mode 100644 routes/_database/timelines/updateStatus.js diff --git a/routes/_actions/accounts.js b/routes/_actions/accounts.js index 471e3889..f8e98136 100644 --- a/routes/_actions/accounts.js +++ b/routes/_actions/accounts.js @@ -1,11 +1,16 @@ import { getAccount, getRelationship } from '../_api/user' -import { database } from '../_database/database' +import { + getAccount as getAccountFromDatabase, + setAccount as setAccountInDatabase, + getRelationship as getRelationshipFromDatabase, + setRelationship as setRelationshipInDatabase +} from '../_database/accountsAndRelationships' import { store } from '../_store/store' async function updateAccount (accountId, instanceName, accessToken) { - let localPromise = database.getAccount(instanceName, accountId) + let localPromise = getAccountFromDatabase(instanceName, accountId) let remotePromise = getAccount(instanceName, accessToken, accountId).then(account => { - database.setAccount(instanceName, account) + /* no await */ setAccountInDatabase(instanceName, account) return account }) @@ -22,9 +27,9 @@ async function updateAccount (accountId, instanceName, accessToken) { } async function updateRelationship (accountId, instanceName, accessToken) { - let localPromise = database.getRelationship(instanceName, accountId) + let localPromise = getRelationshipFromDatabase(instanceName, accountId) let remotePromise = getRelationship(instanceName, accessToken, accountId).then(relationship => { - database.setRelationship(instanceName, relationship) + /* no await */ setRelationshipInDatabase(instanceName, relationship) return relationship }) try { diff --git a/routes/_actions/addInstance.js b/routes/_actions/addInstance.js index 0eba16e0..8fe69f9e 100644 --- a/routes/_actions/addInstance.js +++ b/routes/_actions/addInstance.js @@ -2,10 +2,10 @@ import { getAccessTokenFromAuthCode, registerApplication, generateAuthLink } fro import { getInstanceInfo } from '../_api/instance' import { goto } from 'sapper/runtime.js' import { switchToTheme } from '../_utils/themeEngine' -import { database } from '../_database/database' import { store } from '../_store/store' import { updateVerifyCredentialsForInstance } from './instances' import { updateCustomEmojiForInstance } from './emoji' +import { setInstanceInfo as setInstanceInfoInDatabase } from '../_database/meta' const REDIRECT_URI = (typeof location !== 'undefined' ? location.origin : 'https://pinafore.social') + '/settings/instances/add' @@ -20,7 +20,7 @@ async function redirectToOauth () { } let registrationPromise = registerApplication(instanceName, REDIRECT_URI) let instanceInfo = await getInstanceInfo(instanceName) - await database.setInstanceInfo(instanceName, instanceInfo) // cache for later + await setInstanceInfoInDatabase(instanceName, instanceInfo) // cache for later let instanceData = await registrationPromise store.set({ currentRegisteredInstanceName: instanceName, diff --git a/routes/_actions/addStatusOrNotification.js b/routes/_actions/addStatusOrNotification.js index f9fc8311..0f607808 100644 --- a/routes/_actions/addStatusOrNotification.js +++ b/routes/_actions/addStatusOrNotification.js @@ -1,5 +1,4 @@ import throttle from 'lodash-es/throttle' -import { database } from '../_database/database' import { mark, stop } from '../_utils/marks' import { store } from '../_store/store' import { scheduleIdleTask } from '../_utils/scheduleIdleTask' @@ -7,6 +6,9 @@ import uniqBy from 'lodash-es/uniqBy' import uniq from 'lodash-es/uniq' import isEqual from 'lodash-es/isEqual' import { isMobile } from '../_utils/isMobile' +import { + insertTimelineItems as insertTimelineItemsInDatabase +} from '../_database/timelines/insertion' const STREAMING_THROTTLE_DELAY = 3000 @@ -28,7 +30,7 @@ async function insertUpdatesIntoTimeline (instanceName, timelineName, updates) { return } - await database.insertTimelineItems(instanceName, timelineName, updates) + await insertTimelineItemsInDatabase(instanceName, timelineName, updates) let itemIdsToAdd = store.getForTimeline(instanceName, timelineName, 'itemIdsToAdd') || [] let newItemIdsToAdd = uniq([].concat(itemIdsToAdd).concat(updates.map(_ => _.id))) diff --git a/routes/_actions/compose.js b/routes/_actions/compose.js index a5b68a1b..78d4dfd1 100644 --- a/routes/_actions/compose.js +++ b/routes/_actions/compose.js @@ -2,13 +2,13 @@ import { store } from '../_store/store' import { toast } from '../_utils/toast' import { postStatus as postStatusToServer } from '../_api/statuses' import { addStatusOrNotification } from './addStatusOrNotification' -import { database } from '../_database/database' +import { getStatus as getStatusFromDatabase } from '../_database/timelines/getStatusOrNotification' import { emit } from '../_utils/eventBus' import { putMediaDescription } from '../_api/media' export async function insertHandleForReply (statusId) { let instanceName = store.get('currentInstance') - let status = await database.getStatus(instanceName, statusId) + let status = await getStatusFromDatabase(instanceName, statusId) let verifyCredentials = store.get('currentVerifyCredentials') let originalStatus = status.reblog || status let accounts = [originalStatus.account].concat(originalStatus.mentions || []) diff --git a/routes/_actions/deleteStatuses.js b/routes/_actions/deleteStatuses.js index 7655ebf3..72bdcf99 100644 --- a/routes/_actions/deleteStatuses.js +++ b/routes/_actions/deleteStatuses.js @@ -1,9 +1,11 @@ import { getIdsThatRebloggedThisStatus, getNotificationIdsForStatuses } from './statuses' import { store } from '../_store/store' import { scheduleIdleTask } from '../_utils/scheduleIdleTask' -import { database } from '../_database/database' import forEach from 'lodash-es/forEach' import isEqual from 'lodash-es/isEqual' +import { + deleteStatusesAndNotifications as deleteStatusesAndNotificationsFromDatabase +} from '../_database/timelines/deletion' function filterItemIdsFromTimelines (instanceName, timelineFilter, idFilter) { let keys = ['timelineItemIds', 'itemIdsToAdd'] @@ -43,7 +45,7 @@ function deleteNotificationIdsFromStore (instanceName, idsToDelete) { async function deleteStatusesAndNotifications (instanceName, statusIdsToDelete, notificationIdsToDelete) { deleteStatusIdsFromStore(instanceName, statusIdsToDelete) deleteNotificationIdsFromStore(instanceName, notificationIdsToDelete) - await database.deleteStatusesAndNotifications(instanceName, statusIdsToDelete, notificationIdsToDelete) + await deleteStatusesAndNotificationsFromDatabase(instanceName, statusIdsToDelete, notificationIdsToDelete) } async function doDeleteStatus (instanceName, statusId) { diff --git a/routes/_actions/emoji.js b/routes/_actions/emoji.js index 7b78b26d..8b48aeef 100644 --- a/routes/_actions/emoji.js +++ b/routes/_actions/emoji.js @@ -1,5 +1,8 @@ import { cacheFirstUpdateAfter } from '../_utils/sync' -import { database } from '../_database/database' +import { + getCustomEmoji as getCustomEmojiFromDatabase, + setCustomEmoji as setCustomEmojiInDatabase +} from '../_database/meta' import { getCustomEmoji } from '../_api/emoji' import { store } from '../_store/store' import { substring } from 'stringz' @@ -7,8 +10,8 @@ import { substring } from 'stringz' export async function updateCustomEmojiForInstance (instanceName) { await cacheFirstUpdateAfter( () => getCustomEmoji(instanceName), - () => database.getCustomEmoji(instanceName), - emoji => database.setCustomEmoji(instanceName, emoji), + () => getCustomEmojiFromDatabase(instanceName), + emoji => setCustomEmojiInDatabase(instanceName, emoji), emoji => { let customEmoji = store.get('customEmoji') customEmoji[instanceName] = emoji diff --git a/routes/_actions/favorite.js b/routes/_actions/favorite.js index f6c09d66..15f4eb7d 100644 --- a/routes/_actions/favorite.js +++ b/routes/_actions/favorite.js @@ -1,7 +1,9 @@ import { favoriteStatus, unfavoriteStatus } from '../_api/favorite' import { store } from '../_store/store' -import { database } from '../_database/database' import { toast } from '../_utils/toast' +import { + setStatusFavorited as setStatusFavoritedInDatabase +} from '../_database/timelines/updateStatus' export async function setFavorited (statusId, favorited) { if (!store.get('online')) { @@ -16,7 +18,7 @@ export async function setFavorited (statusId, favorited) { store.setStatusFavorited(instanceName, statusId, favorited) // optimistic update try { await networkPromise - await database.setStatusFavorited(instanceName, statusId, favorited) + await setStatusFavoritedInDatabase(instanceName, statusId, favorited) } catch (e) { console.error(e) toast.say(`Failed to ${favorited ? 'favorite' : 'unfavorite'}. ` + (e.message || '')) diff --git a/routes/_actions/follow.js b/routes/_actions/follow.js index e50f8115..95751d5a 100644 --- a/routes/_actions/follow.js +++ b/routes/_actions/follow.js @@ -1,8 +1,10 @@ import { store } from '../_store/store' import { followAccount, unfollowAccount } from '../_api/follow' -import { database } from '../_database/database' import { toast } from '../_utils/toast' import { updateProfileAndRelationship } from './accounts' +import { + getRelationship as getRelationshipFromDatabase +} from '../_database/accountsAndRelationships' export async function setAccountFollowed (accountId, follow, toastOnSuccess) { let instanceName = store.get('currentInstance') @@ -15,7 +17,7 @@ export async function setAccountFollowed (accountId, follow, toastOnSuccess) { account = await unfollowAccount(instanceName, accessToken, accountId) } await updateProfileAndRelationship(accountId) - let relationship = await database.getRelationship(instanceName, accountId) + let relationship = await getRelationshipFromDatabase(instanceName, accountId) if (toastOnSuccess) { if (follow) { if (account.locked && relationship.requested) { diff --git a/routes/_actions/instances.js b/routes/_actions/instances.js index 30574a87..d1ea0827 100644 --- a/routes/_actions/instances.js +++ b/routes/_actions/instances.js @@ -2,10 +2,16 @@ import { getVerifyCredentials } from '../_api/user' import { store } from '../_store/store' import { switchToTheme } from '../_utils/themeEngine' import { toast } from '../_utils/toast' -import { database } from '../_database/database' import { goto } from 'sapper/runtime.js' import { cacheFirstUpdateAfter } from '../_utils/sync' import { getInstanceInfo } from '../_api/instance' +import { clearDatabaseForInstance } from '../_database/clear' +import { + getInstanceVerifyCredentials as getInstanceVerifyCredentialsFromDatabase, + setInstanceVerifyCredentials as setInstanceVerifyCredentialsInDatabase, + getInstanceInfo as getInstanceInfoFromDatabase, + setInstanceInfo as setInstanceInfoInDatabase +} from '../_database/meta' export function changeTheme (instanceName, newTheme) { let instanceThemes = store.get('instanceThemes') @@ -53,7 +59,7 @@ export async function logOutOfInstance (instanceName) { store.save() toast.say(`Logged out of ${instanceName}`) switchToTheme(instanceThemes[newInstance] || 'default') - await database.clearDatabaseForInstance(instanceName) + await clearDatabaseForInstance(instanceName) goto('/settings/instances') } @@ -68,8 +74,8 @@ export async function updateVerifyCredentialsForInstance (instanceName) { let accessToken = loggedInInstances[instanceName].access_token await cacheFirstUpdateAfter( () => getVerifyCredentials(instanceName, accessToken), - () => database.getInstanceVerifyCredentials(instanceName), - verifyCredentials => database.setInstanceVerifyCredentials(instanceName, verifyCredentials), + () => getInstanceVerifyCredentialsFromDatabase(instanceName), + verifyCredentials => setInstanceVerifyCredentialsInDatabase(instanceName, verifyCredentials), verifyCredentials => setStoreVerifyCredentials(instanceName, verifyCredentials) ) } @@ -81,8 +87,8 @@ export async function updateVerifyCredentialsForCurrentInstance () { export async function updateInstanceInfo (instanceName) { await cacheFirstUpdateAfter( () => getInstanceInfo(instanceName), - () => database.getInstanceInfo(instanceName), - info => database.setInstanceInfo(instanceName, info), + () => getInstanceInfoFromDatabase(instanceName), + info => setInstanceInfoInDatabase(instanceName, info), info => { let instanceInfos = store.get('instanceInfos') instanceInfos[instanceName] = info diff --git a/routes/_actions/lists.js b/routes/_actions/lists.js index 80ec813a..a2429260 100644 --- a/routes/_actions/lists.js +++ b/routes/_actions/lists.js @@ -1,7 +1,10 @@ import { store } from '../_store/store' -import { database } from '../_database/database' import { getLists } from '../_api/lists' import { cacheFirstUpdateAfter } from '../_utils/sync' +import { + getLists as getListsFromDatabase, + setLists as setListsInDatabase +} from '../_database/meta' export async function updateLists () { let instanceName = store.get('currentInstance') @@ -9,8 +12,8 @@ export async function updateLists () { await cacheFirstUpdateAfter( () => getLists(instanceName, accessToken), - () => database.getLists(instanceName), - lists => database.setLists(instanceName, lists), + () => getListsFromDatabase(instanceName), + lists => setListsInDatabase(instanceName, lists), lists => { let instanceLists = store.get('instanceLists') instanceLists[instanceName] = lists diff --git a/routes/_actions/pinnedStatuses.js b/routes/_actions/pinnedStatuses.js index 9e6e10f9..87ac664f 100644 --- a/routes/_actions/pinnedStatuses.js +++ b/routes/_actions/pinnedStatuses.js @@ -1,7 +1,12 @@ import { store } from '../_store/store' import { cacheFirstUpdateAfter } from '../_utils/sync' -import { getPinnedStatuses } from '../_api/pinnedStatuses' -import { database } from '../_database/database' +import { + getPinnedStatuses as getPinnedStatusesFromDatabase, + insertPinnedStatuses as insertPinnedStatusesInDatabase +} from '../_database/timelines/pinnedStatuses' +import { + getPinnedStatuses +} from '../_api/pinnedStatuses' export async function updatePinnedStatusesForAccount (accountId) { let instanceName = store.get('currentInstance') @@ -9,8 +14,8 @@ export async function updatePinnedStatusesForAccount (accountId) { await cacheFirstUpdateAfter( () => getPinnedStatuses(instanceName, accessToken, accountId), - () => database.getPinnedStatuses(instanceName, accountId), - statuses => database.insertPinnedStatuses(instanceName, accountId, statuses), + () => getPinnedStatusesFromDatabase(instanceName, accountId), + statuses => insertPinnedStatusesInDatabase(instanceName, accountId, statuses), statuses => { let $pinnedStatuses = store.get('pinnedStatuses') $pinnedStatuses[instanceName] = $pinnedStatuses[instanceName] || {} diff --git a/routes/_actions/reblog.js b/routes/_actions/reblog.js index e751aa4c..5e91c78e 100644 --- a/routes/_actions/reblog.js +++ b/routes/_actions/reblog.js @@ -1,7 +1,7 @@ import { store } from '../_store/store' -import { database } from '../_database/database' import { toast } from '../_utils/toast' import { reblogStatus, unreblogStatus } from '../_api/reblog' +import { setStatusReblogged as setStatusRebloggedInDatabase } from '../_database/timelines/updateStatus' export async function setReblogged (statusId, reblogged) { if (!store.get('online')) { @@ -16,7 +16,7 @@ export async function setReblogged (statusId, reblogged) { store.setStatusReblogged(instanceName, statusId, reblogged) // optimistic update try { await networkPromise - await database.setStatusReblogged(instanceName, statusId, reblogged) + await setStatusRebloggedInDatabase(instanceName, statusId, reblogged) } catch (e) { console.error(e) toast.say(`Failed to ${reblogged ? 'boost' : 'unboost'}. ` + (e.message || '')) diff --git a/routes/_actions/statuses.js b/routes/_actions/statuses.js index de07418d..3d0cdec4 100644 --- a/routes/_actions/statuses.js +++ b/routes/_actions/statuses.js @@ -1,7 +1,13 @@ -import { database } from '../_database/database' +import { + getNotificationIdsForStatuses as getNotificationIdsForStatusesFromDatabase, + getReblogsForStatus as getReblogsForStatusFromDatabase +} from '../_database/timelines/lookup' +import { + getStatus as getStatusFromDatabase +} from '../_database/timelines/getStatusOrNotification' export async function getIdThatThisStatusReblogged (instanceName, statusId) { - let status = await database.getStatus(instanceName, statusId) + let status = await getStatusFromDatabase(instanceName, statusId) return status.reblog && status.reblog.id } @@ -13,9 +19,9 @@ export async function getIdsThatTheseStatusesReblogged (instanceName, statusIds) } export async function getIdsThatRebloggedThisStatus (instanceName, statusId) { - return database.getReblogsForStatus(instanceName, statusId) + return getReblogsForStatusFromDatabase(instanceName, statusId) } export async function getNotificationIdsForStatuses (instanceName, statusIds) { - return database.getNotificationIdsForStatuses(instanceName, statusIds) + return getNotificationIdsForStatusesFromDatabase(instanceName, statusIds) } diff --git a/routes/_actions/timeline.js b/routes/_actions/timeline.js index 20e80dc3..28bcdf4b 100644 --- a/routes/_actions/timeline.js +++ b/routes/_actions/timeline.js @@ -1,11 +1,16 @@ import { store } from '../_store/store' -import { database } from '../_database/database' import { getTimeline } from '../_api/timelines' import { toast } from '../_utils/toast' import { mark, stop } from '../_utils/marks' import { mergeArrays } from '../_utils/arrays' import { byItemIds } from '../_utils/sorting' import isEqual from 'lodash-es/isEqual' +import { + insertTimelineItems as insertTimelineItemsInDatabase +} from '../_database/timelines/insertion' +import { + getTimeline as getTimelineFromDatabase +} from '../_database/timelines/pagination' const FETCH_LIMIT = 20 @@ -14,16 +19,16 @@ async function fetchTimelineItems (instanceName, accessToken, timelineName, last let items let stale = false if (!online) { - items = await database.getTimeline(instanceName, timelineName, lastTimelineItemId, FETCH_LIMIT) + items = await getTimelineFromDatabase(instanceName, timelineName, lastTimelineItemId, FETCH_LIMIT) stale = true } else { try { items = await getTimeline(instanceName, accessToken, timelineName, lastTimelineItemId, FETCH_LIMIT) - /* no await */ database.insertTimelineItems(instanceName, timelineName, items) + /* no await */ insertTimelineItemsInDatabase(instanceName, timelineName, items) } catch (e) { console.error(e) toast.say('Internet request failed. Showing offline content.') - items = await database.getTimeline(instanceName, timelineName, lastTimelineItemId, FETCH_LIMIT) + items = await getTimelineFromDatabase(instanceName, timelineName, lastTimelineItemId, FETCH_LIMIT) stale = true } } diff --git a/routes/_components/compose/ComposeAutosuggest.html b/routes/_components/compose/ComposeAutosuggest.html index 51e3e5c8..8f2ce159 100644 --- a/routes/_components/compose/ComposeAutosuggest.html +++ b/routes/_components/compose/ComposeAutosuggest.html @@ -39,12 +39,14 @@