fix: close IDB connections when page is frozen (#1196)
OK let's try this
This commit is contained in:
parent
70da9a92a6
commit
43baaf36ae
|
@ -68,7 +68,6 @@
|
|||
"file-drop-element": "0.2.0",
|
||||
"form-data": "^2.3.3",
|
||||
"glob": "^7.1.3",
|
||||
"idb-keyval": "^3.2.0",
|
||||
"indexeddb-getall-shim": "^1.3.5",
|
||||
"intersection-observer": "^0.6.0",
|
||||
"localstorage-memory": "^1.0.3",
|
||||
|
|
|
@ -2,6 +2,7 @@ import { DB_VERSION_CURRENT } from './constants'
|
|||
import { addKnownInstance, deleteKnownInstance } from './knownInstances'
|
||||
import { migrations } from './migrations'
|
||||
import { clearAllCaches } from './cache'
|
||||
import lifecycle from 'page-lifecycle/dist/lifecycle.mjs'
|
||||
|
||||
const openReqs = {}
|
||||
const databaseCache = {}
|
||||
|
@ -77,7 +78,6 @@ export function deleteDatabase (instanceName) {
|
|||
.then(() => clearAllCaches(instanceName))
|
||||
}
|
||||
|
||||
// this should probably only be used in unit tests
|
||||
export function closeDatabase (instanceName) {
|
||||
// close any open requests
|
||||
let openReq = openReqs[instanceName]
|
||||
|
@ -88,3 +88,14 @@ export function closeDatabase (instanceName) {
|
|||
delete databaseCache[instanceName]
|
||||
clearAllCaches(instanceName)
|
||||
}
|
||||
|
||||
if (process.browser) {
|
||||
lifecycle.addEventListener('statechange', event => {
|
||||
if (event.newState === 'frozen') { // page is frozen, close IDB connections
|
||||
Object.keys(openReqs).forEach(instanceName => {
|
||||
closeDatabase(instanceName)
|
||||
console.log('closed instance DBs')
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { set, keys, del } from 'idb-keyval'
|
||||
import { set, keys, del, close } from '../_thirdparty/idb-keyval/idb-keyval'
|
||||
import lifecycle from 'page-lifecycle/dist/lifecycle.mjs'
|
||||
|
||||
const PREFIX = 'known-instance-'
|
||||
|
||||
|
@ -15,3 +16,12 @@ export async function addKnownInstance (instanceName) {
|
|||
export async function deleteKnownInstance (instanceName) {
|
||||
return del(PREFIX + instanceName)
|
||||
}
|
||||
|
||||
if (process.browser) {
|
||||
lifecycle.addEventListener('statechange', async event => {
|
||||
if (event.newState === 'frozen') { // page is frozen, close IDB connections
|
||||
await close()
|
||||
console.log('closed knownInstances DB')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
13
src/routes/_thirdparty/idb-keyval/LICENCE
vendored
Normal file
13
src/routes/_thirdparty/idb-keyval/LICENCE
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
Copyright 2016, Jake Archibald
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
98
src/routes/_thirdparty/idb-keyval/idb-keyval.js
vendored
Normal file
98
src/routes/_thirdparty/idb-keyval/idb-keyval.js
vendored
Normal file
|
@ -0,0 +1,98 @@
|
|||
// Forked from https://github.com/jakearchibald/idb-keyval/commit/ea7d507
|
||||
// Adds a function for closing the database, ala https://github.com/jakearchibald/idb-keyval/pull/65
|
||||
class Store {
|
||||
constructor (dbName = 'keyval-store', storeName = 'keyval') {
|
||||
this.storeName = storeName
|
||||
this._dbName = dbName
|
||||
this._storeName = storeName
|
||||
this._init()
|
||||
}
|
||||
|
||||
_withIDBStore (type, callback) {
|
||||
this._init()
|
||||
return this._dbp.then(db => new Promise((resolve, reject) => {
|
||||
const transaction = db.transaction(this.storeName, type)
|
||||
transaction.oncomplete = () => resolve()
|
||||
transaction.onabort = transaction.onerror = () => reject(transaction.error)
|
||||
callback(transaction.objectStore(this.storeName))
|
||||
}))
|
||||
}
|
||||
|
||||
_init () {
|
||||
if (this._dbp) {
|
||||
return
|
||||
}
|
||||
this._dbp = new Promise((resolve, reject) => {
|
||||
const openreq = indexedDB.open(this._dbName, 1)
|
||||
openreq.onerror = () => reject(openreq.error)
|
||||
openreq.onsuccess = () => resolve(openreq.result)
|
||||
// First time setup: create an empty object store
|
||||
openreq.onupgradeneeded = () => {
|
||||
openreq.result.createObjectStore(this._storeName)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
_close () {
|
||||
this._init()
|
||||
return this._dbp.then(db => {
|
||||
db.close()
|
||||
this._dbp = undefined
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
let store
|
||||
|
||||
function getDefaultStore () {
|
||||
if (!store) {
|
||||
store = new Store()
|
||||
}
|
||||
return store
|
||||
}
|
||||
|
||||
function get (key, store = getDefaultStore()) {
|
||||
let req
|
||||
return store._withIDBStore('readonly', store => {
|
||||
req = store.get(key)
|
||||
}).then(() => req.result)
|
||||
}
|
||||
|
||||
function set (key, value, store = getDefaultStore()) {
|
||||
return store._withIDBStore('readwrite', store => {
|
||||
store.put(value, key)
|
||||
})
|
||||
}
|
||||
|
||||
function del (key, store = getDefaultStore()) {
|
||||
return store._withIDBStore('readwrite', store => {
|
||||
store.delete(key)
|
||||
})
|
||||
}
|
||||
|
||||
function clear (store = getDefaultStore()) {
|
||||
return store._withIDBStore('readwrite', store => {
|
||||
store.clear()
|
||||
})
|
||||
}
|
||||
|
||||
function keys (store = getDefaultStore()) {
|
||||
const keys = []
|
||||
return store._withIDBStore('readonly', store => {
|
||||
// This would be store.getAllKeys(), but it isn't supported by Edge or Safari.
|
||||
// And openKeyCursor isn't supported by Safari.
|
||||
(store.openKeyCursor || store.openCursor).call(store).onsuccess = function () {
|
||||
if (!this.result) {
|
||||
return
|
||||
}
|
||||
keys.push(this.result.key)
|
||||
this.result.continue()
|
||||
}
|
||||
}).then(() => keys)
|
||||
}
|
||||
|
||||
function close (store = getDefaultStore()) {
|
||||
return store._close()
|
||||
}
|
||||
|
||||
export { Store, get, set, del, clear, keys, close }
|
Loading…
Reference in a new issue