diff --git a/dev/double-dispense.js b/dev/double-dispense.js new file mode 100644 index 00000000..34b8f5e0 --- /dev/null +++ b/dev/double-dispense.js @@ -0,0 +1,19 @@ +const got = require('got') + +const tx = { + sessionId: 'a9fdfedc-1d45-11e6-be13-2f68ff6306b9', + toAddress: '1DrK44np3gMKuvcGeFVv9Jk67zodP52eMu', + fiat: 10 +} + +const headers = { + 'content-type': 'application/json', + 'session-id': '36f17fbe-1d44-11e6-a1a9-bbe8a5a41617' +} + +const body = JSON.stringify({tx: tx}) +got('http://localhost:3000/dispense', {body: body, json: true, headers: headers}) +.then(res => { + console.log(res.body) +}) +.catch(console.log) diff --git a/lib/plugins.js b/lib/plugins.js index 561d2a27..c2e541ba 100644 --- a/lib/plugins.js +++ b/lib/plugins.js @@ -829,3 +829,11 @@ exports.fetchTx = function fetchTx (session) { exports.requestDispense = function requestDispense (session, tx) { return db.addDispenseRequest(session, tx) } + +exports.cachedResponse = function (session, path, method) { + return db.cachedResponse(session, path, method) +} + +exports.cacheResponse = function (session, path, method, body) { + return db.cacheResponse(session, path, method, body) +} diff --git a/lib/postgresql_interface.js b/lib/postgresql_interface.js index 5a00bdcb..71d6198f 100644 --- a/lib/postgresql_interface.js +++ b/lib/postgresql_interface.js @@ -568,6 +568,7 @@ exports.addDispenseRequest = function addDispenseRequest (session, tx) { 'dispense', 'pending') ], function (err) { done() + if (err) return reject(err) resolve() }) @@ -582,7 +583,8 @@ function updateDispense (client, session, dispensed, cb) { var values = [dispensed, 'initial_request', 'pending', session.fingerprint, session.id, true] query(client, sql, values, function (err, results) { if (err) return cb(err) - if (results.rowCount === 0) return cb(new Error('No pending tx')) + // DEBUG10 + // if (results.rowCount === 0) return cb(new Error('No pending tx')) cb() }) } @@ -768,6 +770,50 @@ exports.updateNotify = function updateNotify (tx) { }) } +function insertCachedRequest (session, path, method, body) { + const fields = [ + 'device_fingerprint', + 'session_id', + 'path', + 'method', + 'body' + ] + + const sql = getInsertQuery('cached_requests', fields) + return pquery(sql, [session.fingerprint, session.id, path, method, body]) +} + +exports.cachedResponse = function (session, path, method) { + const sql = `select body from cached_requests + where device_fingerprint=$1 + and session_id=$2 + and path=$3 + and method=$4` + + const values = [session.fingerprint, session.id, path, method] + + return insertCachedRequest(session, path, method, {pendingRequest: true}) + .then(() => ({})) + .catch(err => { + if (!isUniqueViolation(err)) throw err + return pquery(sql, values) + .then(r => ({body: r.rows[0].body})) + }) +} + +exports.cacheResponse = function (session, path, method, body) { + const sql = `update cached_requests + set body=$1 + where device_fingerprint=$2 + and session_id=$3 + and path=$4 + and method=$5` + + const values = [body, session.fingerprint, session.id, path, method] + + return pquery(sql, values) +} + /* exports.init('postgres://lamassu:lamassu@localhost/lamassu') connect(function(err, client, done) { diff --git a/lib/routes.js b/lib/routes.js index d211d3e8..41ccbf9e 100644 --- a/lib/routes.js +++ b/lib/routes.js @@ -283,8 +283,11 @@ function waitForDispense (req, res) { function dispense (req, res) { const tx = req.body.tx + const body = {dispense: true} + return plugins.requestDispense(session(req), tx) - .then(() => res.json(200)) + .then(() => cacheResponse(req, body)) + .then(() => res.json(body)) .catch(err => { logger.error(err) res.sendStatus(500) @@ -318,7 +321,7 @@ function init (localConfig) { app.get('/phone_tx', authMiddleware, fetchPhoneTx) app.post('/register_redeem', authMiddleware, registerRedeem) app.get('/await_dispense', authMiddleware, waitForDispense) - app.post('/dispense', authMiddleware, dispense) + app.post('/dispense', authMiddleware, cachedResponse, dispense) localApp.get('/pid', function (req, res) { var machineFingerprint = req.query.fingerprint @@ -354,3 +357,12 @@ function getFingerprint (req) { return (typeof req.connection.getPeerCertificate === 'function' && req.connection.getPeerCertificate().fingerprint) || 'unknown' } + +function cachedResponse (req, res, next) { + return plugins.cachedResponse(session(req), req.path, req.method) + .then(r => r.body ? res.json(r.body) : next()) +} + +function cacheResponse (req, body) { + return plugins.cacheResponse(session(req), req.path, req.method, body) +} diff --git a/migrations/010-cached-requests.js b/migrations/010-cached-requests.js new file mode 100644 index 00000000..794fd9d9 --- /dev/null +++ b/migrations/010-cached-requests.js @@ -0,0 +1,19 @@ +'use strict' + +var db = require('./db') + +exports.up = function (next) { + db.query('CREATE TABLE IF NOT EXISTS cached_requests ( ' + + 'id serial PRIMARY KEY, ' + + 'device_fingerprint text NOT NULL, ' + + 'session_id uuid NOT NULL, ' + + 'path text NOT NULL, ' + + 'method text NOT NULL, ' + + 'body json NOT NULL, ' + + 'UNIQUE (device_fingerprint, session_id, path, method) ' + + ')', next) +} + +exports.down = function (next) { + next() +}