Tôi không biết chi tiết về quỳ và từ một tìm kiếm nhanh, hiện tại, quỳ không hỗ trợ sử dụng "giới hạn" trên các câu lệnh cập nhật, vì vậy chỉ là mô tả về phương pháp chung.
Trước tiên, hãy cập nhật hàng phù hợp với tiêu chí, sau đó chọn hàng đã cập nhật đó.
Vì vậy, trước tiên hãy thực hiện thao tác cập nhật chỉ định id người dùng hiện tại cho hàng chưa xử lý đầu tiên mà không có người dùng nào được chỉ định hoặc đã có cùng một người dùng được chỉ định:
update rows
set assignedTo = user.id
where assignedTo=0 or assignedTo=user.id
order by createdAt asc
limit 1
Tôi nghĩ rằng nó có thể hoạt động như thế này với quỳ bằng cách sử dụng một truy vấn thô nhưng chưa thử:
await knex.raw('update rows set assignedTo = :userid where assignedTo=0 or assignedTo= :userid order by createdAt asc limit 1', {userid: user.id})
Điều này sẽ tìm kiếm hàng đầu tiên (được tạo sớm nhất) chưa được chỉ định hoặc đã được chỉ định cho cùng một người dùng và sau đó chỉ định người dùng đó. Điều này xảy ra một lần.
Sau đó, bạn có thể tìm kiếm hàng được chỉ định cho người dùng:
const notProcessed = await knex('rows')
.select('*'')
.whereRaw(`status='Not-Processed' and assignedTo=${user.id}`)
.orderByRaw('createdAt asc')
.first();
Lưu ý rằng bây giờ chúng ta chỉ tìm kiếm một cách rõ ràng hàng đã được chỉ định cho người dùng như thế nào.
Kết hợp
await knex.raw('update rows set assignedTo = :userid where assignedTo=0 or assignedTo= :userid order by createdAt asc limit 1', {userid: user.id})
const notProcessed = await knex('rows')
.select('*'')
.whereRaw(`status='Not-Processed' and assignedTo=${user.id}`)
.orderByRaw('createdAt asc')
.first();
Rõ ràng là bạn không cần chọn nếu bạn không muốn làm việc với hàng ngay lập tức.
Vấn đề là khi nhiều yêu cầu được xử lý cùng một lúc, bạn phải tưởng tượng nhiều trường hợp mã chạy song song cùng một lúc. Vì vậy, với mã gốc của bạn, hai yêu cầu có thể thực hiện lựa chọn của bạn cùng một lúc trước khi bất kỳ yêu cầu nào trong số chúng thực hiện cập nhật. Vì vậy, cả hai sẽ có cùng một hàng được trả về.
Bằng cách cập nhật ngay hàng trong câu lệnh, ngay cả khi hai câu lệnh chạy song song, cơ sở dữ liệu sẽ đảm bảo rằng chúng không nhìn thấy cùng một hàng.
Một cách tiếp cận thay thế cho một giải pháp sẽ là sử dụng mutex (chẳng hạn như async-mutex ) xung quanh mã gốc của bạn để đảm bảo rằng thao tác chọn và cập nhật ban đầu của bạn là nguyên tử (xảy ra trong một lần), nhưng điều này rất có thể sẽ làm tăng thời gian phản hồi của ứng dụng của bạn vì trong một số trường hợp, một thao tác xử lý yêu cầu sẽ phải chờ một thao tác khác một để tiếp tục.