Jak wspomniałeś, obecnie nie ma czystego sposobu na robienie tego, co chcesz. Obecnie najlepszym podejściem do operacji takich jak ta, której potrzebujesz, jest :
- Czytnik wybiera X dokumentów z odpowiednim limitem i sortowaniem
- Czytnik oznacza dokumenty zwrócone przez 1) swoim własnym unikalnym identyfikatorem czytnika (
e.g. update({_id:{$in:[<result set ids>]}, state:"available", $isolated:1}, {$set:{readerId:<your reader's ID>, state:"processing"}}, false, true)
) - Czytnik wybiera wszystkie dokumenty oznaczone jako przetwarzane i posiadające własny identyfikator czytnika. W tym momencie masz gwarancję, że masz wyłączny dostęp do powstałego zestawu dokumentów.
- Zaoferuj zestaw wyników z 3) do przetworzenia.
Zauważ, że działa to nawet w wysoce współbieżnych sytuacjach, ponieważ czytelnik nigdy nie może zarezerwować dokumentów, które nie zostały jeszcze zarezerwowane przez innego czytelnika (zwróć uwagę, że krok 2 może zarezerwować tylko aktualnie dostępne dokumenty, a zapisy są niepodzielne). Dodałbym również znacznik czasu z czasem rezerwacji, jeśli chcesz mieć możliwość przekroczenia limitu czasu rezerwacji (na przykład w scenariuszach, w których czytelnicy mogą się zawiesić / nie powieść).
EDYCJA:Więcej szczegółów :
Wszystkie operacje zapisu mogą czasami przynosić rezultaty dla operacji oczekujących, jeśli zapis zajmuje stosunkowo dużo czasu. Oznacza to, że krok 2) może nie zobaczyć wszystkich dokumentów oznaczonych w kroku 1), chyba że wykonasz następujące kroki :
- Użyj odpowiedniej wartości „w” (problem z zapisem), co oznacza 1 lub więcej. Zapewni to, że połączenie, na którym wywoływana jest operacja zapisu, będzie czekało na jej zakończenie, niezależnie od tego, czy przyniesie.
- Upewnij się, że wykonujesz odczyt w kroku 2 na tym samym połączeniu (dotyczy tylko zestawów replik z włączonymi odczytami slaveOk) lub wątku, aby zagwarantować, że będą one sekwencyjne. To pierwsze można wykonać w większości sterowników za pomocą metod „requestStart” i „requestDone” lub podobnych (dokumentacja Java tutaj
).
- Dodaj flagę $isolated do wielu aktualizacji, aby upewnić się, że nie można jej przeplatać z innymi operacjami zapisu.
Zobacz także komentarze do dyskusji dotyczącej atomowości/izolacji. Błędnie założyłem, że wielokrotne aktualizacje są izolowane. Nie są, a przynajmniej nie są domyślnie.