diff --git a/src/browser/application.coffee b/src/browser/application.coffee index 885da706b..42b9f704d 100644 --- a/src/browser/application.coffee +++ b/src/browser/application.coffee @@ -158,7 +158,6 @@ class Application buttons: ['OK'] fs.unlink path.join(configDirPath,'edgehill.db'), (err) => @setDatabasePhase('setup') - @config.set("nylas.sync-state", {}) @windowManager.showMainWindow() # Registers basic application commands, non-idempotent. diff --git a/src/flux/nylas-sync-worker.coffee b/src/flux/nylas-sync-worker.coffee index f54037345..961c1edb3 100644 --- a/src/flux/nylas-sync-worker.coffee +++ b/src/flux/nylas-sync-worker.coffee @@ -1,6 +1,6 @@ _ = require 'underscore' NylasLongConnection = require './nylas-long-connection' - +DatabaseStore = require './stores/database-store' {Publisher} = require './modules/reflux-coffee' CoffeeHelpers = require './coffee-helpers' @@ -18,9 +18,13 @@ class NylasSyncWorker @_terminated = false @_connection = new NylasLongConnection(api, namespace.id) - @_state = atom.config.get("nylas.sync-state.#{namespace.id}") ? {} - for model, modelState of @_state - modelState.busy = false + + @_state = null + DatabaseStore.findJSONObject("NylasSyncWorker:#{@_namespace.id}").then (json) => + @_state = json ? {} + for model, modelState of @_state + modelState.busy = false + @resumeFetches() @ @@ -34,6 +38,7 @@ class NylasSyncWorker @_state busy: -> + return false unless @_state for key, state of @_state if state.busy return true @@ -51,6 +56,7 @@ class NylasSyncWorker @ resumeFetches: => + return unless @_state @fetchCollection('threads') @fetchCollection('calendars') @fetchCollection('contacts') @@ -61,6 +67,7 @@ class NylasSyncWorker @fetchCollection('folders') fetchCollection: (model, options = {}) -> + return unless @_state return if @_state[model]?.complete and not options.force? return if @_state[model]?.busy @@ -113,7 +120,7 @@ class NylasSyncWorker writeState: -> @_writeState ?= _.debounce => - atom.config.set("nylas.sync-state.#{@_namespace.id}", @_state) + DatabaseStore.persistJSONObject("NylasSyncWorker:#{@_namespace.id}", @_state) ,100 @_writeState() @trigger() diff --git a/src/flux/stores/contact-store.coffee b/src/flux/stores/contact-store.coffee index a9d44a225..72d431ff3 100644 --- a/src/flux/stores/contact-store.coffee +++ b/src/flux/stores/contact-store.coffee @@ -32,7 +32,7 @@ If you do not wish to refresh the value, do not call the callback. When you create an instance of a JSONCache, you need to provide several settings: -- `localPath`: path on disk to keep the cache +- `key`: A unique key identifying this object. - `version`: a version number. If the local cache has a different version number it will be thrown out. Useful if you want to change the format of the data @@ -43,63 +43,42 @@ When you create an instance of a JSONCache, you need to provide several settings ### class JSONCache @include: CoffeeHelpers.includeModule - @include Publisher - constructor: ({@localPath, @version, @maxAge}) -> + constructor: ({@key, @version, @maxAge}) -> @_value = null - @readLocal() + DatabaseStore.findJSONObject(@key).then (json) => + return @refresh() unless json + return @refresh() unless json.version is @version + @_value = json.value + @trigger() - detatch: => - clearInterval(@_interval) if @_interval + age = (new Date).getTime() - json.time + if age > @maxAge + @refresh() + else + setTimeout(@refresh, @maxAge - age) value: -> @_value reset: -> - fs.unlink @localPath, (err) -> - console.error(err) + DatabaseStore.persistJSONObject(@key, {}) + clearInterval(@_interval) if @_interval + @_interval = null @_value = null - readLocal: => - fs.exists @localPath, (exists) => - return @refresh() unless exists - fs.readFile @localPath, (err, contents) => - return @refresh() unless contents and not err - try - json = JSON.parse(contents) - if json.version isnt @version - throw new Error("Outdated schema") - if not json.time - throw new Error("No fetch time present") - @_value = json.value - @trigger() - - age = (new Date).getTime() - json.time - if age > @maxAge - @refresh() - else - setTimeout(@refresh, @maxAge - age) - - catch err - console.error(err) - @reset() - @refresh() - - writeLocal: => - json = - version: @version - time: (new Date).getTime() - value: @_value - fs.writeFile(@localPath, JSON.stringify(json)) - refresh: => clearInterval(@_interval) if @_interval @_interval = setInterval(@refresh, @maxAge) @refreshValue (newValue) => @_value = newValue - @writeLocal() + DatabaseStore.persistJSONObject(@key, { + version: @version + time: (new Date).getTime() + value: @_value + }) @trigger() refreshValue: (callback) => @@ -108,6 +87,9 @@ class JSONCache class RankingsJSONCache extends JSONCache + constructor: -> + super(key: 'RankingsJSONCache', version: 1, maxAge: 60 * 60 * 1000 * 24) + refreshValue: (callback) => return unless atom.isMainWindow() @@ -154,11 +136,7 @@ class ContactStore extends NylasStore @_contactCache = [] @_namespaceId = null - @_rankingsCache = new RankingsJSONCache - localPath: path.join(atom.getConfigDirPath(), 'contact-rankings.json') - maxAge: 60 * 60 * 1000 * 24 # one day - version: 1 - + @_rankingsCache = new RankingsJSONCache() @listenTo DatabaseStore, @_onDatabaseChanged @listenTo NamespaceStore, @_onNamespaceChanged @listenTo @_rankingsCache, @_sortContactsCacheWithRankings diff --git a/src/flux/stores/database-setup-query-builder.coffee b/src/flux/stores/database-setup-query-builder.coffee index 8e9d9da2e..e4ca0fee7 100644 --- a/src/flux/stores/database-setup-query-builder.coffee +++ b/src/flux/stores/database-setup-query-builder.coffee @@ -22,6 +22,10 @@ class DatabaseSetupQueryBuilder attributes = _.values(klass.attributes) queries = [] + # Add table for storing generic JSON blobs + queries.push("CREATE TABLE IF NOT EXISTS `JSONObject` (key TEXT PRIMARY KEY, data BLOB)") + queries.push("CREATE UNIQUE INDEX IF NOT EXISTS `JSONObject_id` ON `JSONObject` (`key`)") + # Identify attributes of this class that can be matched against. These # attributes need their own columns in the table columnAttributes = _.filter attributes, (attr) -> diff --git a/src/flux/stores/database-store.coffee b/src/flux/stores/database-store.coffee index ad5e19b15..1dc70ee4c 100644 --- a/src/flux/stores/database-store.coffee +++ b/src/flux/stores/database-store.coffee @@ -503,6 +503,17 @@ class DatabaseStore extends NylasStore }) @_triggerSoon({objectClass: newModel.constructor.name, objects: [oldModel, newModel], type: 'swap'}) + persistJSONObject: (key, json) -> + @_query(BEGIN_TRANSACTION) + @_query("REPLACE INTO `JSONObject` (`key`,`data`) VALUES (?,?)", [key, JSON.stringify(json)]) + @_query(COMMIT) + + findJSONObject: (key) -> + @_query("SELECT `data` FROM `JSONObject` WHERE key = ? LIMIT 1", [key]).then (results) => + return Promise.resolve(null) unless results[0] + data = JSON.parse(results[0].data) + Promise.resolve(data) + ######################################################################## ########################### PRIVATE METHODS ############################ ########################################################################