MySQL 触发多条更新时,中间件的延时处理策略

背景

前文中有写道,在 MySQL 上加行级触发器,反向调用 Web 服务器,以达到 Web 服务器被动感知数据库变更的需求。

问题

有个问题就是,MySQL 的触发器只能建在行上,所以有多少行发生变更,就会触发多少次这个网络请求,有时这个开销是不必要的。

解决方案

Web 服务器上作一个定时,在一个时间周期内缓存收到的变更请求,如果在延时周期内收到新的请求,则顺延周期时间。

Code

const express = require('express');
const router = express.Router(null);
const schemas = require('../../models/schemas');
const poolCluster = require('../../conf/mysql.conf').poolCluster;
const roleUpdateCache = new Set();
let setTimeOuter = null;
const timeOutHandler = () => {
    const userPrivilegeModel = schemas.UserPrivilegeModel;
    console.log(1);
    userPrivilegeModel.remove(() => {
        console.log(2);
        poolCluster.getConnection((err, connection) => {
            console.log(err);
            console.log(3);
            connection.query('CALL proc_ht_getInitialPriv();', [], (err, rows) => {
                console.log('result');
                if (err) {
                    throw err;
                }
                const result = {};
                for (let index = 0, len = rows[0].length; index < len; index++) {
                    const element = rows[0][index];
                    if (!result[element.roleId]) {
                        result[element.roleId] = new userPrivilegeModel();
                        result[element.roleId].roleId = element.roleId;
                    }
                    result[element.roleId].privilegeInfo.privilegeCode.push(element.privilegeCode);
                    result[element.roleId].privilegeInfo.privilegeLevel.push(element.privilegeLevel);
                    result[element.roleId].privilegeInfo.privilegeScope.push(element.privilegeScope);
                    result[element.roleId].privilegeInfo.privilegeRoute.push(element.privilegeRoute);
                }
                userPrivilegeModel.insertMany(Object.values(result)).then(() => {
                    schemas.SessionModel.find({
                        'session.roleId': {$in: Array.from(roleUpdateCache)}
                    }, 'session.uid', (err, result) => {
                        console.log('Old roleId and New roleId:');
                        console.log(roleUpdateCache);
                        roleUpdateCache.clear();
                        // TODO: Exception handler.
                        console.log(result);
                        if (result.length !== 0) {
                            const uid = result[0]['session']['uid'];
                            const wsMap = require('../../models/entities');
                            const wsInstance = wsMap.get(uid);
                            wsInstance ? wsInstance.send('Test Message.') : console.log('Can not find this user\'s ws handle in wsMap!\n Maybe you should reboot your app.');
                        }
                    })
                });
            });
        });
    });
};
router.get('/role-privilege-update', (req, res) => {
    const params = req.query;
    const oldRoleId = params['old_roleid'];
    const newRoleId = params['new_roleid'];
    res.end();
    roleUpdateCache.add(+oldRoleId);
    roleUpdateCache.add(+newRoleId);
    console.log(roleUpdateCache);
    if (setTimeOuter) {
        clearTimeout(setTimeOuter);
    }
    setTimeOuter = setTimeout(() => {
        console.log(123);
        console.log(roleUpdateCache);
        timeOutHandler();
    }, 2000);
});
router.get('/role-privilege-delete-or-insert', (req, res) => {
    const params = req.query;
    const roleIdConcerned = params['roleid_concerned'];
    res.end();
    roleUpdateCache.add(+roleIdConcerned);
    if (setTimeOuter) {
        clearTimeout(setTimeOuter);
    }
    setTimeOuter = setTimeout(() => {
        timeOutHandler();
    }, 2000);
});
module.exports = router;

你可能感兴趣的:(MySQL 触发多条更新时,中间件的延时处理策略)