2 HTTP请求同时检查记录是否存在,如果不存在则创建它=重复记录

时间:2012-09-18 04:48:58

标签: mysql ruby-on-rails ruby

我有这个应用程序,在第一次启动时,在我的服务器后端调用2个不同的API端点(两者的用途非常不同)。但是,这两种方法都有before_filter,它使用HTTP_AUTH标头(设备标识符+ api密钥)中传递的信息对呼叫进行身份验证。

如果无法使用提供的标识符从我的设备表中找到一行,它会自动创建一个带有该标识符的新行。我的问题是,似乎有时2个调用是如此同步,以至于两个请求都找不到任何记录,因此它们都创建了一个新的设备行(结果是具有相同设备标识符的重复行)。

我的身份验证方法如下:

def current_user      
    authenticate_with_http_basic do |udid, secret|
        if secret == APP_SECRET
            @device = Device.find_by_udid(udid)

            if !@device
                @device = Device.new
                @device.udid = udid
                @device.created_on = DateTime.now.utc
            end

            // set a bunch of properties on @device
            @device.connected_at = DateTime.now.utc
            @device.save
        end
    end
end 

1 个答案:

答案 0 :(得分:8)

这就是发明独特索引的原因。在udid上放置一个唯一索引(这样每个udid只能存在一个设备)然后你的代码看起来像这样(伪代码):

def process
  device = Device.find

  unless device
    device = Device.create
  end

  # do your work with the device

rescue ActiveRecord::RecordNotUnique
  retry # this is an actual ruby keyword. It means "run this begin..end block 
        # again". In this case, there's an implicit begin..end block, which is 
        # the method body.
end

如果第二个工作人员尝试使用已存在的udid插入设备,则会出现错误,应该再次尝试搜索。