Merge pull request #1691 from siiky/feat/lam-1062/save-unsuccessful-qr-scans
LAM-1062 Save frames from unsuccessful QR scanning attempts
This commit is contained in:
commit
8381b3d9ec
4 changed files with 108 additions and 10 deletions
|
|
@ -487,11 +487,18 @@ function updateDiagnostics (deviceId, images) {
|
|||
const directory = `${OPERATOR_DATA_DIR}/diagnostics/${deviceId}/`
|
||||
const { scan, front } = images
|
||||
|
||||
return updatePhotos(scan, front, directory)
|
||||
return updatePhotos(directory, [['scan.jpg', scan], ['front.jpg', front]])
|
||||
.then(() => db.none(sql, [deviceId, !!scan, !!front]))
|
||||
.catch(err => logger.error('while running machine diagnostics: ', err))
|
||||
}
|
||||
|
||||
const updateFailedQRScans = (deviceId, frames) => {
|
||||
const timestamp = (new Date()).toISOString()
|
||||
const directory = `${OPERATOR_DATA_DIR}/failedQRScans/${deviceId}/`
|
||||
const filenames = _.map(no => `${timestamp}-${no}.jpg`, _.range(0, _.size(frames)))
|
||||
return updatePhotos(directory, _.zip(filenames, frames))
|
||||
}
|
||||
|
||||
function createPhoto (name, data, dir) {
|
||||
if (!data) {
|
||||
logger.error(`Diagnostics error: No data to save for ${name} photo`)
|
||||
|
|
@ -503,16 +510,12 @@ function createPhoto (name, data, dir) {
|
|||
return fsPromises.writeFile(filename, decodedImageData)
|
||||
}
|
||||
|
||||
function updatePhotos (scan, front, dir) {
|
||||
function updatePhotos (dir, photoPairs) {
|
||||
const dirname = path.join(dir)
|
||||
_.attempt(() => makeDir.sync(dirname))
|
||||
|
||||
const promises = [
|
||||
createPhoto('scan.jpg', scan, dirname),
|
||||
createPhoto('front.jpg', front, dirname)
|
||||
]
|
||||
|
||||
return Promise.all(promises)
|
||||
return Promise.all(photoPairs.map(
|
||||
([filename, data]) => createPhoto(filename, data, dirname)
|
||||
))
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
@ -530,5 +533,6 @@ module.exports = {
|
|||
getMachineIds,
|
||||
emptyMachineUnits,
|
||||
refillMachineUnits,
|
||||
updateDiagnostics
|
||||
updateDiagnostics,
|
||||
updateFailedQRScans
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
const fs = require('fs/promises')
|
||||
const path = require('path')
|
||||
const _ = require('lodash/fp')
|
||||
const Queue = require('queue-promise')
|
||||
const plugins = require('./plugins')
|
||||
|
|
@ -32,6 +34,7 @@ const RADAR_UPDATE_INTERVAL = 5 * T.minutes
|
|||
const PRUNE_MACHINES_HEARTBEAT = 1 * T.day
|
||||
const TRANSACTION_BATCH_LIFECYCLE = 20 * T.minutes
|
||||
const TICKER_RATES_INTERVAL = 59 * T.seconds
|
||||
const FAILED_SCANS_INTERVAL = 1 * T.day
|
||||
const EXTERNAL_COMPLIANCE_INTERVAL = 1 * T.minutes
|
||||
|
||||
const CHECK_NOTIFICATION_INTERVAL = 20 * T.seconds
|
||||
|
|
@ -41,6 +44,8 @@ const CACHE_ENTRY_TTL = 3600 // seconds
|
|||
const FAST_QUEUE_WAIT = 1 * T.seconds
|
||||
const SLOW_QUEUE_WAIT = 10 * T.seconds
|
||||
|
||||
const OPERATOR_DATA_DIR = process.env.OPERATOR_DATA_DIR
|
||||
|
||||
const FAST_QUEUE = new Queue({
|
||||
concurrent: 600,
|
||||
interval: FAST_QUEUE_WAIT
|
||||
|
|
@ -129,6 +134,77 @@ function updateCoinAtmRadar () {
|
|||
.then(rates => coinAtmRadar.update(rates, settings()))
|
||||
}
|
||||
|
||||
const readdir = dirpath =>
|
||||
fs.readdir(dirpath, { withFileTypes: true })
|
||||
.then(_.map(entry => _.set('path', path.join(dirpath, entry.name), entry)))
|
||||
|
||||
const readdirRec = rootPath =>
|
||||
readdir(rootPath)
|
||||
.then(entries => Promise.all(
|
||||
entries.map(entry => entry.isDirectory() ? readdirRec(entry.path) : [entry])
|
||||
))
|
||||
.then(_.flatten)
|
||||
|
||||
const stat = path => fs.stat(path).then(_.set('path', path))
|
||||
const pathComponents = p => path.normalize(p).split(path.sep)
|
||||
|
||||
// @see lib/customers.js:updateIdCardData()
|
||||
const cleanOldFailedPDF417Scans = () => {
|
||||
const matcher = (c, pat) => typeof pat === 'function' ? pat(c) : c === pat
|
||||
const PDF417ScanPathPattern = _.concat(
|
||||
pathComponents(OPERATOR_DATA_DIR),
|
||||
["id-operator", s => /* customerid*/ true, "idcarddata", fname => path.extname(fname) === 'jpg']
|
||||
)
|
||||
const isPDF417Scan = entry => {
|
||||
entry = pathComponents(entry.path)
|
||||
return entry.length === PDF417ScanPathPattern.length
|
||||
&& _.isMatchWith(matcher, PDF417ScanPathPattern, pathComponents(entry.path))
|
||||
}
|
||||
|
||||
let old = new Date()
|
||||
old.setDate(old.getDate() - 2) // 2 days ago
|
||||
old = old.getTime()
|
||||
|
||||
/* NOTE: Small caveat to mtime: last time the file was written to. */
|
||||
const isOld = filestat => filestat.mtimeMs < old
|
||||
|
||||
readdirRec(path.join(OPERATOR_DATA_DIR, 'id-operator'))
|
||||
.then(entries => Promise.all(
|
||||
entries
|
||||
.filter(entry => entry.isFile() && isPDF417Scan(entry))
|
||||
.map(entry => stat(entry.path))
|
||||
))
|
||||
.then(filestats => Promise.all(
|
||||
filestats
|
||||
.filter(isOld)
|
||||
.map(_.flow(_.get(['path']), fs.unlink))
|
||||
))
|
||||
.catch(err => {
|
||||
console.log("Error cleaning up failed PDF417 scans:", err)
|
||||
})
|
||||
}
|
||||
|
||||
// @see lib/machine-loader.js:updateFailedQRScans()
|
||||
const cleanOldFailedQRScans = () => {
|
||||
const old = new Date()
|
||||
old.setDate(old.getDate() - 2) // 2 days ago
|
||||
|
||||
const isOld = filepath => {
|
||||
const then = new Date(path.basename(filepath).replace(/-[0-9]+\.jpg$/, ''))
|
||||
return then < old
|
||||
}
|
||||
|
||||
readdirRec(path.join(OPERATOR_DATA_DIR, 'failedQRScans'))
|
||||
.then(entries => Promise.all(
|
||||
entries
|
||||
.filter(entry => entry.isFile() && isOld(entry.path))
|
||||
.map(entry => fs.unlink(entry.path))
|
||||
))
|
||||
.catch(err => {
|
||||
console.log("Error cleaning up failed QR scans:", err)
|
||||
})
|
||||
}
|
||||
|
||||
// function checkExternalCompliance (settings) {
|
||||
// return customers.checkExternalCompliance(settings)
|
||||
// }
|
||||
|
|
@ -213,6 +289,8 @@ function doPolling (schema) {
|
|||
addToQueue(updateAndLoadSanctions, SANCTIONS_UPDATE_INTERVAL, schema, QUEUE.SLOW)
|
||||
addToQueue(updateCoinAtmRadar, RADAR_UPDATE_INTERVAL, schema, QUEUE.SLOW)
|
||||
addToQueue(pi().pruneMachinesHeartbeat, PRUNE_MACHINES_HEARTBEAT, schema, QUEUE.SLOW, settings)
|
||||
addToQueue(cleanOldFailedQRScans, FAILED_SCANS_INTERVAL, schema, QUEUE.SLOW, settings)
|
||||
addToQueue(cleanOldFailedPDF417Scans, FAILED_SCANS_INTERVAL, schema, QUEUE.SLOW, settings)
|
||||
// addToQueue(checkExternalCompliance, EXTERNAL_COMPLIANCE_INTERVAL, schema, QUEUE.SLOW, settings)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ const verifyUserRoutes = require('./routes/verifyUserRoutes')
|
|||
const verifyTxRoutes = require('./routes/verifyTxRoutes')
|
||||
const verifyPromoCodeRoutes = require('./routes/verifyPromoCodeRoutes')
|
||||
const probeRoutes = require('./routes/probeLnRoutes')
|
||||
const failedQRScansRoutes = require('./routes/failedQRScans')
|
||||
|
||||
const graphQLServer = require('./graphql/server')
|
||||
|
||||
|
|
@ -75,6 +76,7 @@ app.use('/cashbox', cashboxRoutes)
|
|||
|
||||
app.use('/network', performanceRoutes)
|
||||
app.use('/diagnostics', diagnosticsRoutes)
|
||||
app.use('/failedqrscans', failedQRScansRoutes)
|
||||
|
||||
app.use('/verify_user', verifyUserRoutes)
|
||||
app.use('/verify_transaction', verifyTxRoutes)
|
||||
|
|
|
|||
14
lib/routes/failedQRScans.js
Normal file
14
lib/routes/failedQRScans.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
const express = require('express')
|
||||
const router = express.Router()
|
||||
|
||||
const { updateFailedQRScans } = require('../machine-loader')
|
||||
|
||||
function failedQRScans (req, res, next) {
|
||||
return updateFailedQRScans(req.deviceId, req.body)
|
||||
.then(() => res.status(200).send({ status: 'OK' }))
|
||||
.catch(next)
|
||||
}
|
||||
|
||||
router.post('/', failedQRScans)
|
||||
|
||||
module.exports = router
|
||||
Loading…
Add table
Add a link
Reference in a new issue