Comme vous le mentionnez, il n'existe actuellement aucun moyen propre de faire ce que vous voulez. La meilleure approche à l'heure actuelle pour des opérations comme celle dont vous avez besoin est la suivante :
- Le lecteur sélectionne X documents avec une limite et un tri appropriés
- Le lecteur marque les documents renvoyés par 1) avec son propre ID de lecteur unique (
e.g. update({_id:{$in:[<result set ids>]}, state:"available", $isolated:1}, {$set:{readerId:<your reader's ID>, state:"processing"}}, false, true)
) - Reader sélectionne tous les documents marqués comme en cours de traitement et avec son propre ID de lecteur. À ce stade, il est garanti que vous disposez d'un accès exclusif à l'ensemble de documents résultant.
- Offrez l'ensemble de résultats de 3) pour votre traitement.
Notez que cela fonctionne même dans des situations hautement simultanées car un lecteur ne peut jamais réserver des documents qui ne sont pas déjà réservés par un autre lecteur (notez que l'étape 2 ne peut réserver que les documents actuellement disponibles et que les écritures sont atomiques). J'ajouterais également un horodatage avec l'heure de réservation si vous souhaitez pouvoir expirer les réservations (par exemple pour les scénarios où les lecteurs pourraient planter/échouer).
EDIT :Plus de détails :
Toutes les opérations d'écriture peuvent parfois donner lieu à des opérations en attente si l'écriture prend un temps relativement long. Cela signifie que l'étape 2) peut ne pas voir tous les documents marqués par l'étape 1) à moins que vous ne suiviez les étapes suivantes :
- Utilisez une valeur « w » (écrire préoccupation) appropriée, c'est-à-dire 1 ou plus. Cela garantira que la connexion sur laquelle l'opération d'écriture est invoquée attendra qu'elle se termine, qu'elle aboutisse ou non.
- Assurez-vous d'effectuer la lecture à l'étape 2 sur la même connexion (uniquement pertinente pour les réplicas avec des lectures activées par slaveOk) ou thread afin qu'ils soient garantis séquentiels. Le premier peut être fait dans la plupart des pilotes avec les méthodes "requestStart" et "requestDone" ou similaires (documentation Java ici
).
- Ajoutez l'indicateur $isolated à vos mises à jour multiples pour vous assurer qu'il ne peut pas être entrelacé avec d'autres opérations d'écriture.
Voir également les commentaires pour la discussion concernant l'atomicité/l'isolement. J'ai supposé à tort que les mises à jour multiples étaient isolées. Ils ne le sont pas, ou du moins pas par défaut.