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

sam*_*tte 3 ruby mysql ruby-on-rails

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

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

我的auth方法如下所示:

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 
Run Code Online (Sandbox Code Playgroud)

Ser*_*sev 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
Run Code Online (Sandbox Code Playgroud)

如果第二个工作程序尝试插入已存在的udid设备,则会出现错误并应再次尝试搜索.