2016-06-01 3 views
3

バッチで大量のレコードを処理する必要があります。そして、各バッチはそれ自身のトランザクションで処理されるべきです。トランザクションで各バッチをラップし、同時にすべてのレコードをバッチでロックする方法はありますか?Rails find_in_batches with locking

Model.scheduled_now.lock.find_in_batches do |batch| 
    model_ids = batch.map(&:id) 
    Model.update_all({status: 'delivering'}, {"id IN (?)" , model_ids}) 

    # creates and updates other DB records 
    # and triggers background job 
    perform_delivery_actions(batch) 
end 

この例のSELECT FOR UPDATEは、各バッチ後にトランザクションをコミットしますか? または、内部トランザクションブロックとロックレコードを手動で各バッチ内に配置する必要があります(つまり、もう1つのクエリを意味します)。

私が外部トランザクションブロックを置いて欲しくない理由は、一度に全部ではなく、別々にバッチをコミットしたいからです。

答えて

0

は、私は自分自身を実装することになったfind_in_batches_with_lock

def find_in_batches_with_lock(scope, user, batch_size: 1000) 
    last_processed_id = 0 
    records = [] 
    begin 
    user.transaction do 
     records = scope.where("id > ?", last_processed_id) 
        .order(:id).limit(batch_size).lock.all 
     next if records.empty? 
     yield records 
     last_processed_id = records.last.id 
    end 
    end while !records.empty? 
end