Надявам се, че някой може да ми помогне да разбера дали виждам проблем или просто не разбирам поведението на tailable курсора на mongodb. Работя с mongodb 2.0.4 и pymongo 2.1.1.
Ето един скрипт, който демонстрира проблема.
#!/usr/bin/python
import sys
import time
import pymongo
MONGO_SERVER = "127.0.0.1"
MONGO_DATABASE = "mdatabase"
MONGO_COLLECTION = "mcollection"
mongodb = pymongo.Connection(MONGO_SERVER, 27017)
database = mongodb[MONGO_DATABASE]
if MONGO_COLLECTION in database.collection_names():
database[MONGO_COLLECTION].drop()
print "creating capped collection"
database.create_collection(
MONGO_COLLECTION,
size=100000,
max=100,
capped=True
)
collection = database[MONGO_COLLECTION]
# Run this script with any parameter to add one record
# to the empty collection and see the code below
# loop correctly
#
if len(sys.argv[1:]):
collection.insert(
{
"key" : "value",
}
)
# Get a tailable cursor for our looping fun
cursor = collection.find( {},
await_data=True,
tailable=True )
# This will catch ctrl-c and the error thrown if
# the collection is deleted while this script is
# running.
try:
# The cursor should remain alive, but if there
# is nothing in the collection, it dies after the
# first loop. Adding a single record will
# keep the cursor alive forever as I expected.
while cursor.alive:
print "Top of the loop"
try:
message = cursor.next()
print message
except StopIteration:
print "MongoDB, why you no block on read?!"
time.sleep(1)
except pymongo.errors.OperationFailure:
print "Delete the collection while running to see this."
except KeyboardInterrupt:
print "trl-C Ya!"
sys.exit(0)
print "and we're out"
# End
Така че, ако погледнете кода, е доста лесно да демонстрирам проблема, който имам. Когато стартирам кода срещу празна колекция (правилно ограничена и готова за проследяване), курсорът умира и кодът ми излиза след един цикъл. Добавянето на първи запис в колекцията го кара да се държи по начина, по който бих очаквал да се държи задният курсор.
Освен това каква е сделката с изключението StopIteration, което убива cursor.next() в очакване на данни? Защо бекендът не може просто да блокира, докато данните станат налични? Предположих, че await_data наистина ще направи нещо, но изглежда само че поддържа връзката да чака секунда или две по-дълго, отколкото без него.
Повечето примери в мрежата показват поставяне на втори цикъл While True около цикъла cursor.alive, но след това, когато скриптът следи празна колекция, цикълът просто се върти и върти, губейки време на процесора за нищо. Наистина не искам да поставям нито един фалшив запис, само за да избегна този проблем при стартиране на приложението.