update idempotentcy

This commit is contained in:
Josh Harvey 2016-10-26 17:13:09 +03:00
parent 9c57b1de87
commit 06ff037189
3 changed files with 65 additions and 115 deletions

View file

@ -128,10 +128,6 @@ function loadPlugin (name, config) {
return plugin
}
function pp (o) {
console.log(require('util').inspect(o, {depth: null}))
}
function loadOrConfigPlugin (pluginHandle, pluginType, cryptoCode, config, accounts, options,
onChangeCallback) {
const currentName = config.cryptoServices[pluginType]
@ -689,11 +685,21 @@ function executeTrades (cryptoCode) {
* ID Verifier functions
*/
exports.verifyUser = function verifyUser (data, cb) {
idVerifierPlugin.verifyUser(data, cb)
return new Promise((resolve, reject) => {
idVerifierPlugin.verifyUser(data, (err, res) => {
if (err) return reject(err)
return resolve(res)
})
})
}
exports.verifyTx = function verifyTx (data, cb) {
idVerifierPlugin.verifyTransaction(data, cb)
return new Promise((resolve, reject) => {
idVerifierPlugin.verifyTransaction(data, (err, res) => {
if (err) return reject(err)
return resolve(res)
})
})
}
function sendMessage (rec) {

View file

@ -5,8 +5,6 @@ const logger = require('./logger')
const configManager = require('./config-manager')
const db = require('./db')
let mock = false
let plugins
module.exports = {
@ -127,19 +125,12 @@ function trade (req, res, next) {
tx.cryptoAtoms = new BigNumber(tx.cryptoAtoms)
plugins.trade(getDeviceId(req), tx)
.then(() => {
updateCachedAction(req, {}, 201)
res.status(201).json({})
})
.then(() => cacheAndRespond(req, res))
}
function stateChange (req, res) {
plugins.stateChange(getDeviceId(req), getDeviceTime(req), req.body)
.then(() => res.json({success: true}))
.catch(err => {
console.error(err)
res.json({success: false})
})
.then(() => cacheAndRespond(req, res))
}
function send (req, res) {
@ -149,8 +140,7 @@ function send (req, res) {
return plugins.sendCoins(getDeviceId(req), tx)
.then(status => {
const body = {txId: status && status.txId}
updateCachedAction(req, body, 200)
.then(() => res.json(body))
return cacheAndRespond(req, res, body)
})
}
@ -160,50 +150,27 @@ function cashOut (req, res) {
tx.cryptoAtoms = new BigNumber(tx.cryptoAtoms)
return plugins.cashOut(getDeviceId(req), tx)
.then(cryptoAddress => res.json({toAddress: cryptoAddress}))
.catch(err => {
res.json({
err: err.message,
errType: err.name
})
logger.error(err)
})
.then(cryptoAddress => cacheAndRespond(req, res, {toAddress: cryptoAddress}))
}
function dispenseAck (req, res) {
plugins.dispenseAck(getDeviceId(req), req.body.tx)
res.json({success: true})
.then(() => cacheAndRespond(req, res))
}
function deviceEvent (req, res) {
plugins.logEvent(getDeviceId(req), req.body)
res.json({err: null})
.then(() => cacheAndRespond(req, res))
}
function verifyUser (req, res) {
if (mock) return res.json({success: true})
plugins.verifyUser(req.body, (err, idResult) => {
if (err) {
logger.error(err)
return res.json({err: 'Verification failed'})
}
res.json(idResult)
})
plugins.verifyUser(req.body)
.then(idResult => cacheAndRespond(req, res, idResult))
}
function verifyTx (req, res) {
if (mock) return res.json({success: true})
plugins.verifyTx(req.body, (err, idResult) => {
if (err) {
logger.error(err)
return res.json({err: 'Verification failed'})
}
res.json(idResult)
})
plugins.verifyTransaction(req.body)
.then(idResult => cacheAndRespond(req, res, idResult))
}
function ca (req, res) {
@ -223,14 +190,8 @@ function pair (req, res) {
return pair.pair(token, deviceId)
.then(valid => {
updateCachedAction(req, {})
if (valid) {
updateCachedAction(req, {}, 200)
return res.json({})
}
updateCachedAction(req, {}, 408)
return res.status(408).json({})
if (valid) return cacheAndRespond(req, res)
throw httpError('Invalid token', 408)
})
}
@ -238,12 +199,12 @@ function phoneCode (req, res) {
const phone = req.body.phone
logger.debug('Phone code requested for: ' + phone)
return plugins.getPhoneCode(phone)
.then(code => res.json({code}))
.then(code => cacheAndRespond(req, res, {code}))
.catch(err => {
logger.error(err)
if (err.name === 'BadNumberError') return res.sendStatus(410)
return res.sendStatus(500)
if (err.name === 'BadNumberError') throw httpError('Bad number', 410)
throw err
})
}
@ -252,11 +213,7 @@ function updatePhone (req, res) {
const tx = req.body
return plugins.updatePhone(tx, notified)
.then(r => res.json(r))
.catch(err => {
logger.error(err)
res.sendStatus(500)
})
.then(r => cacheAndRespond(req, res, r))
}
function fetchPhoneTx (req, res) {
@ -271,11 +228,7 @@ function fetchPhoneTx (req, res) {
function registerRedeem (req, res) {
const txId = req.params.txId
return plugins.registerRedeem(txId)
.then(() => res.json({success: true}))
.catch(err => {
logger.error(err)
res.sendStatus(500)
})
.then(() => cacheAndRespond(req, res))
}
function waitForDispense (req, res) {
@ -296,38 +249,9 @@ function waitForDispense (req, res) {
function dispense (req, res) {
const tx = req.body.tx
const txId = tx.id
const deviceId = getDeviceId(req)
console.log('DEBUG17')
return cachedResponse(deviceId, txId, req)
.then(cached => {
console.log('DEBUG18: %j', cached)
// Cache hit
if (cached && cached.pendingRequest) return res.sendStatus(409)
console.log('DEBUG18.5')
if (cached) res.json(cached)
console.log('DEBUG19')
// No cache hit
return plugins.requestDispense(tx)
.then(dispenseRec => {
console.log('DEBUG20: %j', dispenseRec)
return cacheResponse(deviceId, txId, req, dispenseRec)
.then(() => res.json(dispenseRec))
})
.catch(err => {
console.log('DEBUG21')
logger.error(err)
res.sendStatus(500)
})
})
.catch(err => logger.error(err))
.then(dispenseRec => cacheAndRespond(req, res, dispenseRec))
}
function isUniqueViolation (err) {
@ -355,22 +279,42 @@ function cacheAction (req, res, next) {
})
}
function cachedActionError (req, err, status) {
return updateCachedAction(req, {error: err}, status || 500)
}
function updateCachedAction (req, body, status) {
const sql = 'update idempotents set body=$1, status=$2, pending=$3 where request_id=$4 and device_id=$5'
const sql = `update idempotents set body=$1, status=$2, pending=$3
where request_id=$4 and device_id=$5 and pending=$6`
const requestId = req.headers['request-id']
const deviceId = getDeviceId(req)
return db.none(sql, [body, status, false, requestId, deviceId])
return db.none(sql, [body, status, false, requestId, deviceId, true])
}
function postErrorHandler (err, req, res, next) {
const statusCode = err.code || 500
const json = {error: err.message}
return updateCachedAction(req, json, statusCode)
.then(() => res.status(statusCode).json({}))
}
function cacheAndRespond (req, res, _body, _status) {
const status = _status || 200
const body = _body || {}
return updateCachedAction(req, body, status)
.then(() => res.status(status).json(body))
}
function httpError (msg, code) {
const err = new Error(msg)
err.name = 'HTTPError'
err.code = code || 500
return err
}
function init (opts) {
plugins = opts.plugins
mock = opts.mock
const authMiddleware = opts.authMiddleware
const app = opts.app
@ -400,7 +344,7 @@ function init (opts) {
app.get('/await_dispense/:txId', authMiddleware, waitForDispense)
app.post('/dispense', authMiddleware, dispense)
app.post('*', updateCachedAction)
app.post('*', postErrorHandler)
localApp.get('/pid', (req, res) => {
const deviceId = req.query.device_id

View file

@ -111,6 +111,6 @@ v need to create CA: http://stackoverflow.com/questions/19665863/how-do-i-use-a-
--------------------------------
- consistent error handling
- usage of http status codes (good for got)
- finish idempotency for all calls
v consistent error handling
v usage of http status codes (good for got)
v finish idempotency for all calls