Ruby on rails rubyonrails中的竞争条件

Ruby on rails rubyonrails中的竞争条件,ruby-on-rails,ruby,postgresql,heroku,race-condition,Ruby On Rails,Ruby,Postgresql,Heroku,Race Condition,我在Heroku上遇到了一个奇怪的bug,我相信这可能是一个种族问题,我正在寻找解决它的任何建议 我的应用程序有一个模型,该模型在创建之后调用外部API(如果您好奇的话,可以是Twilio)。在这个调用中,它传递一个url,以便在第三方完成工作后回调。像这样: class TextMessage < ActiveRecord::Base after_create :send_sms def send_sms call.external.third.party.api

我在Heroku上遇到了一个奇怪的bug,我相信这可能是一个种族问题,我正在寻找解决它的任何建议

我的应用程序有一个模型,该模型在创建之后调用外部API(如果您好奇的话,可以是Twilio)。在这个调用中,它传递一个url,以便在第三方完成工作后回调。像这样:

class TextMessage < ActiveRecord::Base
   after_create :send_sms

   def send_sms
     call.external.third.party.api(
       :callback => sent_text_message_path(self)
     )
   end
end
我们检查过了,身份证是正确的。更疯狂的是,我们在创建模型时加入了一个
放入日志,这就是我们得到的:

2014-03-13T18:15:22.192733+00:00 app[web.1]: TextMessage created with ID 35.
2014-03-13T18:15:22.192791+00:00 app[web.1]: ActiveRecord::RecordNotFound (Couldn't find TextMessage with id=35)
注意时间戳。这些事情看起来相隔58毫秒,所以我认为这是一种竞赛条件。我们正在使用Heroku(至少用于登台),所以我认为可能是他们的虚拟Postgres数据库出了问题


以前有人有过这种问题吗?如果是,您是如何修复的?有什么建议吗?

您是否有主/从数据库,您总是向主数据库写入数据,但从从数据库读取数据?这听起来像是数据库复制延迟

我们通过在特定的控制器操作中强制从主数据库进行读取来解决这些问题


另一种方法是在复制完成后调用
send\u sms

在保存文本消息的数据库事务处理后。因此,命中另一个控制器的回调无法读取文本消息。在数据库事务中进行外部调用不是一个好主意,因为在缓慢的外部请求执行的整个过程中,事务都会阻塞部分数据库

simples解决方案是将保存后的
替换为提交后的
(请参阅:)

由于回调往往变得难以理解(并且在测试时可能会导致问题),因此我更愿意通过调用另一个方法来明确调用。也许是这样的:

# use instead of .save 
def save_and_sent_sms
  save and sent_sms
end

也许您希望在后台发送sms,这样不会减慢用户的web请求。搜索gems delayed_job或resque以获取更多信息。

这听起来完全正确,但我们使用的是Heroku,因此我们无法访问任何数据库设置。延迟短信是我们找到的一种解决方案,但我们也注意到,我们也可以在发送的回调中加入延迟。两个看起来都很丑。
2014-03-13T18:15:22.192733+00:00 app[web.1]: TextMessage created with ID 35.
2014-03-13T18:15:22.192791+00:00 app[web.1]: ActiveRecord::RecordNotFound (Couldn't find TextMessage with id=35)
# use instead of .save 
def save_and_sent_sms
  save and sent_sms
end