Bị request nhiều lần lên server



  • Chào các bác. Em đang rất đau đầu về vấn đề này.
    Em có viết 1 api. Api này cho người dùng lấy thẻ 1 lần/ngày/người. Nhưng em thấy có trường hợp db lưu 2 bản ghi thậm chí là 3, 4 bản ghi.
    Em có test thử lại thì vẫn bình thường, nhưng có 1 lần mạng em yếu thế là nó tự động request 2 phát :(

    Bác nào có kinh nghiệm cho em lời khuyên ạ :)

    Dưới đây là code của em ạ

    async.waterfall([
    	function(callback)
    	{
    		Setting.find({name: {$in: ['allow_charging', 'max_cashout']}}, function(err, data)
    		{
    			var objSetting = {};
    			for(var i in data)
    			{
    				objSetting[data[i]._doc.name] = parseInt(data[i]._doc.value);
    			}
    			return callback(null, objSetting);
    		})
    	},
    	function(setting, callback)
    	{
    		Cashout.aggregate([
    			{
    				$match: {
    					'user.facebook_id': user_info.facebook_id,
    					created_at: {
    						$gt: new Date(_start), 
    						$lt: new Date(_end)
    					}
    				}
    			},
    			{
    				$group: {
    					_id: '',
    					total: {$sum: "$card_value"}
    				}
    			}
    		], function(err, data)
    		{
    			var charging = 0;
    			if(!data || data.length == 0)
    			{
    				charging = 0
    			}
    			else
    			{
    				charging = data[0].total;
    			}
    			//Tong so tien da doi
    			var remaning = parseInt(setting.max_cashout) - charging;
    			//Neu tong so tien da doi ma nho hon so tien duoc config thi 
    			var dataCallback = {max_cashout: setting.max_cashout};
    			if(remaning >= parseInt(setting.max_cashout))
    			{
    				dataCallback.status = true;
    				return callback(0, dataCallback);//false khong cho lay the nua
    			}
    			dataCallback.status = false;
    			return callback(0, dataCallback)//Cho phep lay the nhung phai check so tien doi
    		})
    	},
    	function(infoCharging, callback)
    	{
    		if(infoCharging.status == false || card_value > infoCharging.max_cashout)
    		{
    			return callback(50);
    		}
    		User.findOne({_id: user_info._id}, function(err, user)
    		{
    			if(err || !user)
    			{
    				return callback(11);
    			}
    			
    			//Kiem tra nguoi dung da xac nhan sdt chua
    			if(user.phone_number == '0')
    			{
    				return callback(52);
    			}
    			
    			//... Lay thong tin the
    		})
    	}
    
    ], function(err, results)
    {
    	if(err)
    	{
    		return res.json({
    			errorCode: err,
    			data: null
    		})
    	}
    	return res.json(results)
    }) 
    


  • Đại khái flow ứng dụng của bạn là :

    • Lấy setting -> check info người dùng -> logic trả thẻ -> cập nhật lại

    Như vậy trong tính huống nào đó sẽ có các request tới mà vẫn chưa có cập nhật lại => nhiều hơn 1 bản ghi.
    Cách dễ nhất là chuyển qua dùng Postgres hoặc MySQL , SQL có hỗ trợ transactions nó xử lý concurrency đơn giản. Mongo nó chỉ hỗ trợ transaction-like (Cái này mình chưa dùng bao giờ :D).

    Một giải pháp khác là xây dựng hệ thống dưới dạng event sourcing: Bạn sẽ không lưu dưới dạng trạng thái đã lấy hay chưa nữa ( State) mà lưu các action của người dùng. Mỗi lần lấy rồi thì 1 bản ghi và dựa vào các bản ghi này để lấy ra trạng thái.


Log in to reply