From 06ff03718942ee00eca4482b734ca830040e0690 Mon Sep 17 00:00:00 2001 From: Josh Harvey Date: Wed, 26 Oct 2016 17:13:09 +0300 Subject: [PATCH] update idempotentcy --- lib/plugins.js | 18 ++++-- lib/routes.js | 156 ++++++++++++++++--------------------------------- todo.txt | 6 +- 3 files changed, 65 insertions(+), 115 deletions(-) diff --git a/lib/plugins.js b/lib/plugins.js index 88fe5ca6..5ba4c578 100644 --- a/lib/plugins.js +++ b/lib/plugins.js @@ -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) { diff --git a/lib/routes.js b/lib/routes.js index 3cb4ce20..9fffb710 100644 --- a/lib/routes.js +++ b/lib/routes.js @@ -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,13 +199,13 @@ 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})) - .catch(err => { - logger.error(err) - if (err.name === 'BadNumberError') return res.sendStatus(410) - return res.sendStatus(500) - }) + .then(code => cacheAndRespond(req, res, {code})) + .catch(err => { + if (err.name === 'BadNumberError') throw httpError('Bad number', 410) + throw err + }) } function updatePhone (req, res) { @@ -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)) + return plugins.requestDispense(tx) + .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 diff --git a/todo.txt b/todo.txt index 8694c76b..866885b7 100644 --- a/todo.txt +++ b/todo.txt @@ -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