Skip to content

Commit

Permalink
feat: drop localStorage usage
Browse files Browse the repository at this point in the history
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`
  • Loading branch information
gr2m committed Dec 23, 2016
1 parent 7d76539 commit 5f54be4
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 89 deletions.
26 changes: 9 additions & 17 deletions client/index.js
Expand Up @@ -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
}
52 changes: 28 additions & 24 deletions lib/check.js
Expand Up @@ -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)
})
})
}

Expand Down
33 changes: 18 additions & 15 deletions 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')
})
}
14 changes: 9 additions & 5 deletions lib/start-checking.js
Expand Up @@ -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) {
Expand Down
8 changes: 6 additions & 2 deletions 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
})
}
27 changes: 17 additions & 10 deletions 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()
}
50 changes: 35 additions & 15 deletions 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: {
Expand All @@ -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') {
Expand All @@ -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
}
1 change: 0 additions & 1 deletion lib/utils/request.js
Expand Up @@ -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
Expand Down

0 comments on commit 5f54be4

Please sign in to comment.