Improve resiliency of IDB database

pull/438/merge
Thibaut Courouble 9 years ago
parent a120b88545
commit 800622099f

@ -252,7 +252,7 @@
false false
isSingleDoc: -> isSingleDoc: ->
!!(@DOC or @doc) document.body.hasAttribute('data-doc')
isMobile: -> isMobile: ->
@_isMobile ?= app.views.Mobile.detect() @_isMobile ?= app.views.Mobile.detect()

@ -25,8 +25,8 @@ class app.DB
try try
db = event.target.result db = event.target.result
unless @checkedBuggyIDB unless @checkedBuggyIDB
@idbTransaction(db, stores: ['docs', app.docs.all()[0].slug], mode: 'readwrite').abort() # https://bugs.webkit.org/show_bug.cgi?id=136937
@checkedBuggyIDB = true @checkedBuggyIDB = true
@idbTransaction(db, stores: $.makeArray(db.objectStoreNames)[0..1], mode: 'readwrite').abort() # https://bugs.webkit.org/show_bug.cgi?id=136937
catch catch
try db.close() try db.close()
@reason = 'apple' @reason = 'apple'
@ -124,11 +124,11 @@ class app.DB
onError(event) onError(event)
return return
store = txn.objectStore(doc.slug)
store.clear()
store = txn.objectStore('docs') store = txn.objectStore('docs')
store.delete(doc.slug) store.delete(doc.slug)
store = txn.objectStore(doc.slug)
store.clear()
return return
return return
@ -239,9 +239,11 @@ class app.DB
@cachedDocs = {} @cachedDocs = {}
txn = @idbTransaction db, stores: ['docs'], mode: 'readonly' txn = @idbTransaction db, stores: ['docs'], mode: 'readonly'
store = txn.objectStore('docs') txn.oncomplete = =>
setTimeout(@checkForCorruptedDocs, 50)
return
req = store.openCursor() req = txn.objectStore('docs').openCursor()
req.onsuccess = (event) => req.onsuccess = (event) =>
return unless cursor = event.target.result return unless cursor = event.target.result
@cachedDocs[cursor.key] = cursor.value @cachedDocs[cursor.key] = cursor.value
@ -252,6 +254,41 @@ class app.DB
return return
return return
checkForCorruptedDocs: =>
@db (db) =>
@corruptedDocs = []
docs = (key for key, value of @cachedDocs when value)
return if docs.length is 0
for slug in docs when not app.docs.findBy('slug', slug)
@corruptedDocs.push(slug)
for slug in @corruptedDocs
$.arrayDelete(docs, slug)
txn = @idbTransaction(db, stores: docs, mode: 'readonly', ignoreError: false)
txn.oncomplete = =>
setTimeout(@deleteCorruptedDocs, 0) if @corruptedDocs.length > 0
return
for doc in docs
txn.objectStore(doc).get('index').onsuccess = (event) =>
@corruptedDocs.push(event.target.source.name) unless event.target.result
return
return
return
deleteCorruptedDocs: =>
@db (db) =>
txn = @idbTransaction(db, stores: ['docs'], mode: 'readwrite', ignoreError: false)
store = txn.objectStore('docs')
while doc = @corruptedDocs.pop()
@cachedDocs[doc] = false
store.delete(doc)
return
Raven.captureMessage 'corruptedDocs', extra: { docs: @corruptedDocs.join(',') }
return
shouldLoadWithIDB: (entry) -> shouldLoadWithIDB: (entry) ->
@useIndexedDB and (not @cachedDocs or @cachedDocs[entry.doc.slug]) @useIndexedDB and (not @cachedDocs or @cachedDocs[entry.doc.slug])

Loading…
Cancel
Save