From 5f54be45eeac681ee6cd8b1ad83a2fcbb1e4bd81 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 22 Dec 2016 10:25:44 -0800 Subject: [PATCH] feat: drop localStorage usage BREAKING CHANGE: `connectionStatus.isChecking` is now a property (as described in README). It was implemented as function before BREAKING CHANGE: `connectionStatus.ok` does not return false if a connection error was persisted before until `connectionStatus.ready` resolved BREAKING CHANGE: `new ConnectionStatus(options)`: `options.cache.timeout` is now `options.cacheTimeout` --- client/index.js | 26 +++++++------------ lib/check.js | 52 ++++++++++++++++++++------------------ lib/reset.js | 33 +++++++++++++----------- lib/start-checking.js | 14 ++++++---- lib/stop-checking.js | 8 ++++-- lib/utils/cache.js | 27 ++++++++++++-------- lib/utils/parse-options.js | 50 +++++++++++++++++++++++++----------- lib/utils/request.js | 1 - 8 files changed, 122 insertions(+), 89 deletions(-) diff --git a/client/index.js b/client/index.js index beee5e8..856f530 100644 --- a/client/index.js +++ b/client/index.js @@ -12,37 +12,29 @@ var off = require('../lib/off') var reset = require('../lib/reset') var parseOptions = require('../lib/utils/parse-options') -var getCache = require('../lib/utils/cache').get function Connection (options) { var state = parseOptions(options) - var cached = getCache(state) state.emitter = new EventEmitter() - if (cached) { - var cachedTime = +new Date(cached.timestamp) - var currentTime = +new Date() - if (state.cache.timeout && currentTime >= cachedTime + state.cache.timeout) { - process.nextTick(function () { - state.emitter.emit('reset', cached) - }) - } else { - state.error = cached.error - state.timestamp = cached.timestamp - } - } - - return { + var api = { + get ready () { + return state.ready.then(function () { return api }) + }, get ok () { return getOk(state) }, + get isChecking () { + return isChecking(state) + }, check: check.bind(null, state), - isChecking: isChecking.bind(null, state), stopChecking: stopChecking.bind(null, state), startChecking: startChecking.bind(null, state), on: on.bind(null, state), off: off.bind(null, state), reset: reset.bind(null, state) } + + return api } diff --git a/lib/check.js b/lib/check.js index 8d4eb8c..78e2412 100644 --- a/lib/check.js +++ b/lib/check.js @@ -5,35 +5,39 @@ internals.cache = require('./utils/cache') internals.request = require('./utils/request') function check (state) { - if (state.request) { - state.request.abort() - } + return state.ready - state.request = internals.request({ - method: state.method, - url: state.url, - timeout: state.timeout - }) + .then(function () { + if (state.request) { + state.request.abort() + } - // once request finishes, remove it from state - state.request.catch(function (error) { - delete state.request - state.timestamp = new Date().toISOString() - handleError(state, error) - }) + state.request = internals.request({ + method: state.method, + url: state.url, + timeout: state.timeout + }) - return state.request.then(function () { - delete state.request - state.timestamp = new Date().toISOString() + // once request finishes, remove it from state + state.request.catch(function (error) { + delete state.request + state.timestamp = new Date().toISOString() + handleError(state, error) + }) - if (state.error) { - process.nextTick(function () { - state.emitter.emit('reconnect') - }) - delete state.error - } + return state.request.then(function () { + delete state.request + state.timestamp = new Date().toISOString() - internals.cache.set(state) + if (state.error) { + process.nextTick(function () { + state.emitter.emit('reconnect') + }) + delete state.error + } + + internals.cache.set(state) + }) }) } diff --git a/lib/reset.js b/lib/reset.js index 02db2c8..eacc16d 100644 --- a/lib/reset.js +++ b/lib/reset.js @@ -1,28 +1,31 @@ module.exports = reset -var Promise = require('lie') var cache = require('./utils/cache') function reset (state, o) { - var options = o || {} - state.timestamp = undefined - state.error = undefined + return state.ready - if (typeof options.interval === 'number') { - var intervalTimeValue = options.interval - state.interval = { - connected: intervalTimeValue, - disconnected: intervalTimeValue + .then(function () { + var options = o || {} + state.timestamp = undefined + state.error = undefined + + if (typeof options.interval === 'number') { + var intervalTimeValue = options.interval + state.interval = { + connected: intervalTimeValue, + disconnected: intervalTimeValue + } } - } - cache.set(state) + if (state.request) { + state.request.abort() + } - if (state.request) { - state.request.abort() - } + return cache.unset(state) + }) - return Promise.resolve().then(function () { + .then(function () { state.emitter.emit('reset') }) } diff --git a/lib/start-checking.js b/lib/start-checking.js index 9d9b769..e24752e 100644 --- a/lib/start-checking.js +++ b/lib/start-checking.js @@ -5,12 +5,16 @@ internals.check = require('./check') internals.getOk = require('./get-ok') function startChecking (state, options) { - options = parse(options) - if (!state.method || !state.url) { - return - } + return state.ready + + .then(function () { + options = parse(options) + if (!state.method || !state.url) { + return + } - handleInterval(state, options) + handleInterval(state, options) + }) } function timeoutHandler (state, options) { diff --git a/lib/stop-checking.js b/lib/stop-checking.js index d397da0..5d6015c 100644 --- a/lib/stop-checking.js +++ b/lib/stop-checking.js @@ -1,6 +1,10 @@ module.exports = stopChecking function stopChecking (state) { - clearTimeout(state.checkTimeout) - delete state.checkTimeout + return state.ready + + .then(function () { + clearTimeout(state.checkTimeout) + delete state.checkTimeout + }) } diff --git a/lib/utils/cache.js b/lib/utils/cache.js index 9de26cd..a8f0ba8 100644 --- a/lib/utils/cache.js +++ b/lib/utils/cache.js @@ -1,31 +1,38 @@ module.exports = { get: getCache, - set: setCache + set: setCache, + unset: clearCache } -var internals = module.exports.internals = {} -internals.store = require('humble-localstorage') - function setCache (state, error) { if (state.cache === false) { - return + return Promise.resolve() } var data = { timestamp: state.timestamp, error: state.error } - var key = state.cache.prefix + state.url - internals.store.setObject(key, data) + return state.cache.set(data) } function getCache (state) { if (state.cache === false) { - return + return Promise.resolve({}) } - var key = state.cache.prefix + state.url + return state.cache.get() + + .then(function (data) { + return data + }) +} + +function clearCache (state) { + if (state.cache === false) { + return Promise.resolve({}) + } - return internals.store.getObject(key) + return state.cache.unset() } diff --git a/lib/utils/parse-options.js b/lib/utils/parse-options.js index ab7f959..89350c6 100644 --- a/lib/utils/parse-options.js +++ b/lib/utils/parse-options.js @@ -1,10 +1,12 @@ module.exports = parseOptions +var Store = require('async-get-set-store') + +var cache = require('./cache') + var DEFAULTS = { - cache: { - prefix: 'connection_', - timeout: undefined - }, + cache: {}, + cacheTimeout: 7200000, // 2h in milliseconds method: 'HEAD', checkTimeout: undefined, interval: { @@ -25,14 +27,7 @@ function parseOptions (options) { } if (options.cache === undefined) { - options.cache = {} - } - - if (options.cache.prefix === undefined) { - options.cache.prefix = DEFAULTS.cache.prefix - } - if (options.cache.timeout === undefined) { - options.cache.timeout = DEFAULTS.cache.timeout + options.cache = new Store('connection_' + url) } if (typeof options.interval === 'number') { @@ -43,11 +38,36 @@ function parseOptions (options) { } } - return { + var state = { url: url, + cache: options.cache, method: options.method || DEFAULTS.method, checkTimeout: options.checkTimeout || DEFAULTS.checkTimeout, - cache: options.cache, - interval: options.interval || DEFAULTS.interval + interval: options.interval || DEFAULTS.interval, + cacheTimeout: options.cacheTimeout || DEFAULTS.cacheTimeout, + ready: cache.get({ + cache: options.cache + }) + .then(function (cache) { + if (cache.timestamp) { + var cachedTime = +new Date(cache.timestamp) + var currentTime = +new Date() + if (state.cacheTimeout && currentTime >= cachedTime + state.cacheTimeout) { + process.nextTick(function () { + state.emitter.emit('reset', cache) + }) + } else { + state.error = cache.error + state.timestamp = cache.timestamp + } + } + }) + .catch(function (error) { + error.name = 'SetupError' + error.message = 'Error while initialising: ' + error.message + throw error + }) } + + return state } diff --git a/lib/utils/request.js b/lib/utils/request.js index f1a6f9f..4c34709 100644 --- a/lib/utils/request.js +++ b/lib/utils/request.js @@ -2,7 +2,6 @@ module.exports = request var internals = module.exports.internals = {} internals.nets = require('nets') -var Promise = require('lie') function request (options) { var requestState