diff --git a/server/src/app.js b/server/src/app.js index 00f932a..75be4e7 100644 --- a/server/src/app.js +++ b/server/src/app.js @@ -80,4 +80,12 @@ app.use((err, req, res, _next) => { res.status(500).json(fail(3001, 'server_error')) }) +// Clean up stale records on startup (SCF cold start) +require('./dao/payment-order.dao').closeStaleOrders().catch(err => { + console.error('[STARTUP] closeStaleOrders failed:', err.message) +}) +require('./dao/binding.dao').closeExpiredPending().catch(err => { + console.error('[STARTUP] closeExpiredPending failed:', err.message) +}) + module.exports = app diff --git a/server/src/dao/binding.dao.js b/server/src/dao/binding.dao.js index edf6827..5dc9a0b 100644 --- a/server/src/dao/binding.dao.js +++ b/server/src/dao/binding.dao.js @@ -202,11 +202,18 @@ async function countActiveByUser(userId) { return rows[0].total } +async function closeExpiredPending() { + return query( + 'UPDATE bindings SET bind_status = 4 WHERE bind_status = 3 AND bind_expires < NOW()' + ) +} + module.exports = { findActiveByUser, findDeviceExists, cancelPending, createPending, + closeExpiredPending, confirmBind, mockBind, unbindByUser, diff --git a/server/src/dao/payment-order.dao.js b/server/src/dao/payment-order.dao.js index 1cd6580..6995bcb 100644 --- a/server/src/dao/payment-order.dao.js +++ b/server/src/dao/payment-order.dao.js @@ -84,4 +84,10 @@ async function countPendingByUser(userId) { return rows[0].cnt } -module.exports = { createOrder, findByOutTradeNo, markPrepay, markPaidAndActivateSubscription, markClosed, markFailed, countPendingByUser } +async function closeStaleOrders() { + return query( + "UPDATE payment_orders SET status = 'closed', trade_state = 'EXPIRED' WHERE status IN ('created', 'paying') AND created_at < DATE_SUB(NOW(), INTERVAL 24 HOUR)" + ) +} + +module.exports = { createOrder, findByOutTradeNo, markPrepay, markPaidAndActivateSubscription, markClosed, markFailed, countPendingByUser, closeStaleOrders }