Improve IndexedDB versioning and recover from version mismatch

pull/602/head
Thibaut Courouble 8 years ago
parent d63aadb27e
commit 684355cc52

@ -201,7 +201,6 @@
return if @quotaExceeded return if @quotaExceeded
@quotaExceeded = true @quotaExceeded = true
new app.views.Notif 'QuotaExceeded', autoHide: null new app.views.Notif 'QuotaExceeded', autoHide: null
Raven.captureMessage 'QuotaExceededError', level: 'warning'
return return
onCookieBlocked: (key, value, actual) -> onCookieBlocked: (key, value, actual) ->

@ -1,9 +1,9 @@
class app.DB class app.DB
NAME = 'docs' NAME = 'docs'
VERSION = 15
constructor: -> constructor: ->
@useIndexedDB = @useIndexedDB() @useIndexedDB = @useIndexedDB()
@appVersion = @appVersion()
@callbacks = [] @callbacks = []
db: (fn) -> db: (fn) ->
@ -13,7 +13,7 @@ class app.DB
try try
@open = true @open = true
req = indexedDB.open(NAME, @schemaVersion()) req = indexedDB.open(NAME, VERSION * 1e9 + @userVersion())
req.onsuccess = @onOpenSuccess req.onsuccess = @onOpenSuccess
req.onerror = @onOpenError req.onerror = @onOpenError
req.onupgradeneeded = @onUpgradeNeeded req.onupgradeneeded = @onUpgradeNeeded
@ -26,21 +26,16 @@ class app.DB
if db.objectStoreNames.length is 0 if db.objectStoreNames.length is 0
try db.close() try db.close()
@open = false
@fail 'empty' @fail 'empty'
return else if error = @buggyIDB(db)
try db.close()
unless @checkedBuggyIDB @open = false
@checkedBuggyIDB = true @fail 'buggy', error
try else
@idbTransaction(db, stores: $.makeArray(db.objectStoreNames)[0..1], mode: 'readwrite').abort() # https://bugs.webkit.org/show_bug.cgi?id=136937 @runCallbacks(db)
catch error @open = false
try db.close() db.close()
@fail 'buggy', error
return
@runCallbacks(db)
@open = false
db.close()
return return
onOpenError: (event) => onOpenError: (event) =>
@ -48,15 +43,17 @@ class app.DB
@open = false @open = false
error = event.target.error error = event.target.error
if error.name is 'QuotaExceededError' switch error.name
@reset() when 'QuotaExceededError'
@db() @onQuotaExceededError()
app.onQuotaExceeded() when 'VersionError'
else @onVersionError()
@fail 'cant_open', error else
@fail 'cant_open', error
return return
fail: (reason, error) -> fail: (reason, error) ->
@cachedDocs = null
@useIndexedDB = false @useIndexedDB = false
@reason or= reason @reason or= reason
@error or= error @error or= error
@ -65,6 +62,39 @@ class app.DB
Raven.captureException error, level: 'warning' if error Raven.captureException error, level: 'warning' if error
return return
onQuotaExceededError: ->
@reset()
@db()
app.onQuotaExceeded()
Raven.captureMessage 'QuotaExceededError', level: 'warning'
return
onVersionError: ->
req = indexedDB.open(NAME)
req.onsuccess = (event) =>
@handleVersionMismatch event.target.result.version
req.onerror = (event) ->
event.preventDefault()
@fail 'cant_open', error
return
handleVersionMismatch: (actualVersion) ->
if Math.floor(actualVersion / 1e9) isnt VERSION
@fail 'version'
else
@setUserVersion actualVersion - VERSION * 1e9
@db()
return
buggyIDB: (db) ->
return if @checkedBuggyIDB
@checkedBuggyIDB = true
try
@idbTransaction(db, stores: $.makeArray(db.objectStoreNames)[0..1], mode: 'readwrite').abort() # https://bugs.webkit.org/show_bug.cgi?id=136937
return
catch error
return error
runCallbacks: (db) -> runCallbacks: (db) ->
fn(db) while fn = @callbacks.shift() fn(db) while fn = @callbacks.shift()
return return
@ -340,11 +370,9 @@ class app.DB
app.settings.set('schema', @userVersion() + 1) app.settings.set('schema', @userVersion() + 1)
return return
schemaVersion: -> setUserVersion: (version) ->
@appVersion * 10 + @userVersion() app.settings.set('schema', version)
return
userVersion: -> userVersion: ->
app.settings.get('schema') app.settings.get('schema')
appVersion: ->
if app.config.env is 'production' then app.config.version else Math.floor(Date.now() / 1000)

@ -40,6 +40,9 @@ app.templates.offlineError = (reason, exception) ->
""" An error occured when trying to open the IndexedDB database:<br> """ An error occured when trying to open the IndexedDB database:<br>
<code class="_label">#{exception.name}: #{exception.message}</code><br> <code class="_label">#{exception.name}: #{exception.message}</code><br>
This could be because you're browsing in private mode or have disallowed offline storage on the domain. """ This could be because you're browsing in private mode or have disallowed offline storage on the domain. """
when 'version'
""" The IndexedDB database was modified with a newer version of the app.<br>
<a href="#" data-behavior="reload">Reload the page</a> to use offline mode. """
when 'empty' when 'empty'
""" The IndexedDB database appears to be corrupted. Try <a href="#" data-behavior="reset">resetting the app</a>. """ """ The IndexedDB database appears to be corrupted. Try <a href="#" data-behavior="reset">resetting the app</a>. """

Loading…
Cancel
Save