History

Improve resiliency of IDB database

Thibaut Courouble committed 10 years ago

Commit 80062201 parent a120b882 files · +44 −7Browse files

Unified · Split

2 files
  1. assets/javascripts/app/app.coffee +1 −1
  2. assets/javascripts/app/db.coffee +43 −6
assets/javascripts/app/app.coffee+1−1
@@ -252,7 +252,7 @@ · 251 unmodified lines
252 false252 false
253 253
254 isSingleDoc: ->254 isSingleDoc: ->
255 !!(@DOC or @doc)255 document.body.hasAttribute('data-doc')
256 256
257 isMobile: ->257 isMobile: ->
258 @_isMobile ?= app.views.Mobile.detect()258 @_isMobile ?= app.views.Mobile.detect()
assets/javascripts/app/db.coffee+43−6
@@ -25,8 +25,8 @@ class app.DB · 24 unmodified lines
25 try25 try
26 db = event.target.result26 db = event.target.result
27 unless @checkedBuggyIDB27 unless @checkedBuggyIDB
28 @idbTransaction(db, stores: ['docs', app.docs.all()[0].slug], mode: 'readwrite').abort() # https://bugs.webkit.org/show_bug.cgi?id=136937
29 @checkedBuggyIDB = true28 @checkedBuggyIDB = true
29 @idbTransaction(db, stores: $.makeArray(db.objectStoreNames)[0..1], mode: 'readwrite').abort() # https://bugs.webkit.org/show_bug.cgi?id=136937
30 catch30 catch
31 try db.close()31 try db.close()
32 @reason = 'apple'32 @reason = 'apple'
@@ -124,11 +124,11 @@ class app.DB · 91 unmodified lines
124 onError(event)124 onError(event)
125 return125 return
126 126
127 store = txn.objectStore(doc.slug)
128 store.clear()
129
130 store = txn.objectStore('docs')127 store = txn.objectStore('docs')
131 store.delete(doc.slug)128 store.delete(doc.slug)
129
130 store = txn.objectStore(doc.slug)
131 store.clear()
132 return132 return
133 return133 return
134 134
@@ -239,9 +239,11 @@ class app.DB · 104 unmodified lines
239 @cachedDocs = {}239 @cachedDocs = {}
240 240
241 txn = @idbTransaction db, stores: ['docs'], mode: 'readonly'241 txn = @idbTransaction db, stores: ['docs'], mode: 'readonly'
242 store = txn.objectStore('docs')242 txn.oncomplete = =>
243 setTimeout(@checkForCorruptedDocs, 50)
244 return
243 245
244 req = store.openCursor()246 req = txn.objectStore('docs').openCursor()
245 req.onsuccess = (event) =>247 req.onsuccess = (event) =>
246 return unless cursor = event.target.result248 return unless cursor = event.target.result
247 @cachedDocs[cursor.key] = cursor.value249 @cachedDocs[cursor.key] = cursor.value
@@ -252,6 +254,41 @@ class app.DB · 4 unmodified lines
252 return254 return
253 return255 return
254 256
257 checkForCorruptedDocs: =>
258 @db (db) =>
259 @corruptedDocs = []
260 docs = (key for key, value of @cachedDocs when value)
261 return if docs.length is 0
262
263 for slug in docs when not app.docs.findBy('slug', slug)
264 @corruptedDocs.push(slug)
265
266 for slug in @corruptedDocs
267 $.arrayDelete(docs, slug)
268
269 txn = @idbTransaction(db, stores: docs, mode: 'readonly', ignoreError: false)
270 txn.oncomplete = =>
271 setTimeout(@deleteCorruptedDocs, 0) if @corruptedDocs.length > 0
272 return
273
274 for doc in docs
275 txn.objectStore(doc).get('index').onsuccess = (event) =>
276 @corruptedDocs.push(event.target.source.name) unless event.target.result
277 return
278 return
279 return
280
281 deleteCorruptedDocs: =>
282 @db (db) =>
283 txn = @idbTransaction(db, stores: ['docs'], mode: 'readwrite', ignoreError: false)
284 store = txn.objectStore('docs')
285 while doc = @corruptedDocs.pop()
286 @cachedDocs[doc] = false
287 store.delete(doc)
288 return
289 Raven.captureMessage 'corruptedDocs', extra: { docs: @corruptedDocs.join(',') }
290 return
291
255 shouldLoadWithIDB: (entry) ->292 shouldLoadWithIDB: (entry) ->
256 @useIndexedDB and (not @cachedDocs or @cachedDocs[entry.doc.slug])293 @useIndexedDB and (not @cachedDocs or @cachedDocs[entry.doc.slug])
257 294