improve incoming tx status updating

This commit is contained in:
Josh Harvey 2016-05-31 19:13:35 +03:00
parent 2dc332cf1a
commit 38e562bdd6
3 changed files with 49 additions and 17 deletions

View file

@ -406,12 +406,7 @@ function processTxStatus (tx) {
return resolve() // Resolve on error because we ignore errors return resolve() // Resolve on error because we ignore errors
} }
var status = res.status db.updateTxStatus(tx, res.status).then(resolve).catch(reject)
if (tx.status === status) return resolve()
const confirm = (status === 'instant' && tx.status !== 'confirmed') ||
(status === 'confirmed' && tx.status !== 'instant')
db.updateTxStatus(tx, status, confirm).then(resolve).catch(reject)
}) })
}) })
} }

View file

@ -1,3 +1,4 @@
// @flow weak
'use strict' 'use strict'
const BigNumber = require('bignumber.js') const BigNumber = require('bignumber.js')
@ -302,18 +303,51 @@ exports.fetchUnnotifiedTxs = function fetchUnnotifiedTxs (age, waitPeriod) {
.then(rows => normalizeTxs(rows)) .then(rows => normalizeTxs(rows))
} }
exports.updateTxStatus = function updateTxStatus (tx, status, confirm) { function ratchetStatus (oldStatus, newStatus) {
const sql = confirm const statusOrder = ['notSeen', 'published', 'rejected',
? 'UPDATE cash_out_txs SET status=$1, confirmation_time=now() WHERE session_id=$2' 'authorized', 'instant', 'confirmed']
: 'UPDATE cash_out_txs SET status=$1 WHERE session_id=$2'
const values = [status, tx.sessionId] if (oldStatus === newStatus) return oldStatus
if (newStatus === 'insufficientFunds') return newStatus
return db.none(sql, values) const idx = Math.max(statusOrder.indexOf(oldStatus), statusOrder.indexOf(newStatus))
.then(() => { return statusOrder[idx]
const sql2 = 'insert into cash_out_actions (session_id, action) values ($1, $2)' }
return db.none(sql2, [tx.sessionId, status])
}) exports.updateTxStatus = function updateTxStatus (tx, status) {
const TransactionMode = pgp.txMode.TransactionMode
const isolationLevel = pgp.txMode.isolationLevel
const tmSRD = new TransactionMode({tiLevel: isolationLevel.serializable})
function transaction (t) {
const sql = 'select status, confirmation_time from cash_out_txs where session_id=$1'
return t.one(sql, [tx.sessionId])
.then(row => {
const newStatus = ratchetStatus(row.status, status)
if (row.status === newStatus) return
const setConfirmationTime = !row.confirmation_time &&
(newStatus === 'instant' || newStatus === 'confirmed')
const sql2 = setConfirmationTime
? 'UPDATE cash_out_txs SET status=$1, confirmation_time=now() WHERE session_id=$2'
: 'UPDATE cash_out_txs SET status=$1 WHERE session_id=$2'
const values2 = [newStatus, tx.sessionId]
return t.none(sql2, values2)
.then(() => {
const sql3 = 'insert into cash_out_actions (session_id, action) values ($1, $2)'
return t.none(sql3, [tx.sessionId, newStatus])
})
})
}
transaction.txMode = tmSRD
// Note: don't worry about retrying failed transaction here
// It will be tried again on the next status check
return db.tx(transaction)
} }
exports.updateRedeem = function updateRedeem (session) { exports.updateRedeem = function updateRedeem (session) {

View file

@ -210,7 +210,10 @@ function pair (req, res) {
getFingerprint(req), getFingerprint(req),
name, name,
function (err) { function (err) {
if (err) return res.send(500).json({ err: err.message }) if (err) {
logger.error(err)
return res.json({err: err.message})
}
res.json({success: true}) res.json({success: true})
} }