2018-02-14 04:34:37 +01:00
|
|
|
import { dbPromise, getDatabase } from './databaseLifecycle'
|
|
|
|
import {
|
|
|
|
ACCOUNTS_STORE,
|
|
|
|
NOTIFICATION_TIMELINES_STORE,
|
|
|
|
NOTIFICATIONS_STORE,
|
2018-03-09 08:18:18 +01:00
|
|
|
PINNED_STATUSES_STORE,
|
2018-02-14 04:34:37 +01:00
|
|
|
RELATIONSHIPS_STORE,
|
|
|
|
STATUS_TIMELINES_STORE,
|
|
|
|
STATUSES_STORE,
|
2018-03-09 03:31:59 +01:00
|
|
|
THREADS_STORE,
|
2018-02-14 04:34:37 +01:00
|
|
|
TIMESTAMP
|
|
|
|
} from './constants'
|
2018-04-06 02:57:36 +02:00
|
|
|
import debounce from 'lodash-es/debounce'
|
2018-02-14 04:34:37 +01:00
|
|
|
import { mark, stop } from '../_utils/marks'
|
2018-03-11 05:24:07 +01:00
|
|
|
import { deleteAll } from './utils'
|
|
|
|
import { createPinnedStatusKeyRange, createThreadKeyRange } from './keys'
|
2018-08-30 04:03:12 +02:00
|
|
|
import { getKnownInstances } from './knownInstances'
|
2019-03-04 03:34:10 +01:00
|
|
|
import noop from 'lodash-es/noop'
|
2019-09-08 02:49:58 +02:00
|
|
|
import { CLEANUP_DELAY, CLEANUP_TIME_AGO } from '../_static/database'
|
2019-09-08 05:27:54 +02:00
|
|
|
import { scheduleIdleTask } from '../_utils/scheduleIdleTask'
|
2018-02-14 04:34:37 +01:00
|
|
|
|
|
|
|
const BATCH_SIZE = 20
|
|
|
|
|
2018-02-14 04:35:46 +01:00
|
|
|
function batchedGetAll (callGetAll, callback) {
|
|
|
|
function nextBatch () {
|
2018-02-14 04:34:37 +01:00
|
|
|
callGetAll().onsuccess = function (e) {
|
2019-08-03 22:49:37 +02:00
|
|
|
const results = e.target.result
|
2018-02-14 04:34:37 +01:00
|
|
|
callback(results)
|
|
|
|
if (results.length) {
|
|
|
|
nextBatch()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nextBatch()
|
|
|
|
}
|
|
|
|
|
2018-03-09 03:31:59 +01:00
|
|
|
function cleanupStatuses (statusesStore, statusTimelinesStore, threadsStore, cutoff) {
|
2018-02-14 04:34:37 +01:00
|
|
|
batchedGetAll(
|
2018-03-11 05:24:07 +01:00
|
|
|
() => statusesStore.index(TIMESTAMP).getAllKeys(IDBKeyRange.upperBound(cutoff), BATCH_SIZE),
|
2018-02-14 04:34:37 +01:00
|
|
|
results => {
|
2018-03-11 05:24:07 +01:00
|
|
|
results.forEach(statusId => {
|
|
|
|
statusesStore.delete(statusId)
|
|
|
|
deleteAll(
|
|
|
|
statusTimelinesStore,
|
|
|
|
statusTimelinesStore.index('statusId'),
|
|
|
|
IDBKeyRange.only(statusId)
|
|
|
|
)
|
|
|
|
deleteAll(
|
|
|
|
threadsStore,
|
|
|
|
threadsStore,
|
|
|
|
createThreadKeyRange(statusId)
|
|
|
|
)
|
2018-02-14 04:34:37 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2018-02-14 04:35:46 +01:00
|
|
|
function cleanupNotifications (notificationsStore, notificationTimelinesStore, cutoff) {
|
2018-02-14 04:34:37 +01:00
|
|
|
batchedGetAll(
|
2018-03-11 05:24:07 +01:00
|
|
|
() => notificationsStore.index(TIMESTAMP).getAllKeys(IDBKeyRange.upperBound(cutoff), BATCH_SIZE),
|
2018-02-14 04:34:37 +01:00
|
|
|
results => {
|
2018-03-11 05:24:07 +01:00
|
|
|
results.forEach(notificationId => {
|
|
|
|
notificationsStore.delete(notificationId)
|
|
|
|
deleteAll(
|
|
|
|
notificationTimelinesStore,
|
|
|
|
notificationTimelinesStore.index('notificationId'),
|
|
|
|
IDBKeyRange.only(notificationId)
|
|
|
|
)
|
2018-02-14 04:34:37 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2018-03-09 08:18:18 +01:00
|
|
|
function cleanupAccounts (accountsStore, pinnedStatusesStore, cutoff) {
|
2018-02-14 04:34:37 +01:00
|
|
|
batchedGetAll(
|
2018-03-11 05:24:07 +01:00
|
|
|
() => accountsStore.index(TIMESTAMP).getAllKeys(IDBKeyRange.upperBound(cutoff), BATCH_SIZE),
|
|
|
|
results => {
|
|
|
|
results.forEach(accountId => {
|
|
|
|
accountsStore.delete(accountId)
|
|
|
|
deleteAll(
|
|
|
|
pinnedStatusesStore,
|
|
|
|
pinnedStatusesStore,
|
|
|
|
createPinnedStatusKeyRange(accountId)
|
|
|
|
)
|
2018-02-14 04:34:37 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2018-02-14 04:35:46 +01:00
|
|
|
function cleanupRelationships (relationshipsStore, cutoff) {
|
2018-02-14 04:34:37 +01:00
|
|
|
batchedGetAll(
|
2018-03-11 05:24:07 +01:00
|
|
|
() => relationshipsStore.index(TIMESTAMP).getAllKeys(IDBKeyRange.upperBound(cutoff), BATCH_SIZE),
|
|
|
|
results => {
|
|
|
|
results.forEach(relationshipId => {
|
|
|
|
relationshipsStore.delete(relationshipId)
|
2018-02-14 04:34:37 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-03-04 03:34:10 +01:00
|
|
|
export async function cleanup (instanceName) {
|
2018-02-14 04:34:37 +01:00
|
|
|
console.log('cleanup', instanceName)
|
|
|
|
mark(`cleanup:${instanceName}`)
|
2019-08-03 22:49:37 +02:00
|
|
|
const db = await getDatabase(instanceName)
|
|
|
|
const storeNames = [
|
2018-02-14 04:34:37 +01:00
|
|
|
STATUSES_STORE,
|
|
|
|
STATUS_TIMELINES_STORE,
|
|
|
|
NOTIFICATIONS_STORE,
|
|
|
|
NOTIFICATION_TIMELINES_STORE,
|
|
|
|
ACCOUNTS_STORE,
|
2018-03-09 03:31:59 +01:00
|
|
|
RELATIONSHIPS_STORE,
|
2018-03-09 08:18:18 +01:00
|
|
|
THREADS_STORE,
|
|
|
|
PINNED_STATUSES_STORE
|
2018-02-14 04:34:37 +01:00
|
|
|
]
|
|
|
|
await dbPromise(db, storeNames, 'readwrite', (stores) => {
|
2019-08-03 22:49:37 +02:00
|
|
|
const [
|
2018-02-14 04:34:37 +01:00
|
|
|
statusesStore,
|
|
|
|
statusTimelinesStore,
|
|
|
|
notificationsStore,
|
|
|
|
notificationTimelinesStore,
|
|
|
|
accountsStore,
|
2018-03-09 03:31:59 +01:00
|
|
|
relationshipsStore,
|
2018-03-09 08:18:18 +01:00
|
|
|
threadsStore,
|
|
|
|
pinnedStatusesStore
|
2018-02-14 04:34:37 +01:00
|
|
|
] = stores
|
|
|
|
|
2019-09-08 02:49:58 +02:00
|
|
|
const cutoff = Date.now() - CLEANUP_TIME_AGO
|
2018-02-14 04:34:37 +01:00
|
|
|
|
2018-03-09 03:31:59 +01:00
|
|
|
cleanupStatuses(statusesStore, statusTimelinesStore, threadsStore, cutoff)
|
2018-02-14 04:34:37 +01:00
|
|
|
cleanupNotifications(notificationsStore, notificationTimelinesStore, cutoff)
|
2018-03-09 08:18:18 +01:00
|
|
|
cleanupAccounts(accountsStore, pinnedStatusesStore, cutoff)
|
2018-02-14 04:34:37 +01:00
|
|
|
cleanupRelationships(relationshipsStore, cutoff)
|
|
|
|
})
|
|
|
|
stop(`cleanup:${instanceName}`)
|
|
|
|
}
|
|
|
|
|
2018-02-14 04:35:46 +01:00
|
|
|
function doCleanup (instanceName) {
|
2019-09-08 05:27:54 +02:00
|
|
|
scheduleIdleTask(() => cleanup(instanceName))
|
2018-02-14 04:34:37 +01:00
|
|
|
}
|
|
|
|
|
2018-08-30 04:03:12 +02:00
|
|
|
async function scheduledCleanup () {
|
2018-02-14 04:34:37 +01:00
|
|
|
console.log('scheduledCleanup')
|
2019-08-03 22:49:37 +02:00
|
|
|
const knownInstances = await getKnownInstances()
|
|
|
|
for (const instance of knownInstances) {
|
2018-02-14 04:34:37 +01:00
|
|
|
doCleanup(instance)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-04 03:34:10 +01:00
|
|
|
// we have unit tests that test indexedDB; we don't want this thing to run forever
|
2019-09-08 02:49:58 +02:00
|
|
|
export const scheduleCleanup = process.browser ? debounce(scheduledCleanup, CLEANUP_DELAY) : noop
|