We are using RabbitMQ as our message queue system, ruby client is workling. This week we encountered a strange issue, we create a notification, and define an after_create callback to ask workling to find that notification and then push the notification to twitter or facebook, it works fine except that sometimes it will raise an error said "can't find the notification with the specified ID"
class Notification < ActiveRecord::Base
after_create :asyns_send_notification
......
def async_send_notification
NotificationWorker.async_send_notification({:notification_id => id})
end
end
class NotificationWorker < Workling::Base
def send_notification(params)
notification = Notification.find(params[:notification_id])
......
end
end
It's wierd the notification_id is passed to NotificationWorker, that means the notification is already created, the notification is supposed to be existed.
After talking with MySQL DBA, we find the problem is the find sql is executed before insert transaction is committed.
Let me describe it step by step.
- Notification sends "Transaction Begin" command
- Notification sends "INSERT" command
- Notification gets "next sequence value" as new object id
- Notification sends "new object id" to NotificationWorker
- NotificationWorker sends "SELECT" command to find notification object
- Notification sends "Transaction Commit" command
As you seen, at step 5, the new notification is not existed in the mysql database yet, so the error "Not found" will be raised.
To solve this issue, we can use after_commit callback.
In rails 2.x, we should install after_commit gem, in rails 3.x, after_commit callback is supported by default.
class Notification < ActiveRecord::Base
after_commit_on_create :asyns_send_notification
......
def async_send_notification
NotificationWorker.async_send_notification({:notification_id => id})
end
end
So Notification asks NotificationWorker to run only after the transaction is committed.
本文详细介绍了在使用RabbitMQ作为消息队列系统时,遇到的一个奇怪问题:在创建通知后,定义了after_create回调来请求工作进程查找并推送通知到Twitter或Facebook,但在某些情况下会抛出找不到指定ID的通知的错误。文章通过逐步分析,揭示了问题根源在于find SQL执行在插入事务未提交之前,并提供了使用after_commit回调解决此问题的方法。
50

被折叠的 条评论
为什么被折叠?



