2012-04-25 2 views
3

누군가가 도움을 주면 내가 문제를보고 있는지 또는 mongodb tailable 커서 동작을 이해할 수 없는지 이해할 수 있습니다. 나는 mongodb 2.0.4와 pymongo 2.1.1을 돌리고있다.pymongo tailable 커서를 사용하면 빈 컬렉션에서 사망합니다

다음은 문제를 나타내는 스크립트입니다.

#!/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가 실제로 무언가를 할 것이라고 생각했지만, 연결을 기다리지 않고 두 번째 또는 두 번 기다리는 것만으로 보입니다.

net의 예제 대부분은 cursor.alive 루프 주위에 두 번째 While True 루프를 표시하지만 스크립트가 빈 컬렉션을 꼬리면 루프가 회전하여 아무 것도없는 CPU 시간을 낭비합니다. 난 정말 응용 프로그램 시작 시이 문제를 피하기 위해 하나의 가짜 레코드에 넣어 싶지 않아요.

+0

무언가를 무한히 차단하면 결코 좋은 생각이 아닙니다. – mensi

+0

gobject.MainLoop(). run();)에게 알리십시오. – DaGoodBoy

답변

1

이것은 알려진 동작이며이 경우를 해결하기 위해 "해결 방법"두 개의 루프가 허용됩니다. 콜렉션이 비어있는 경우 즉시 다시 시도하고 제안 된 것처럼 단단한 루프를 입력하는 것이 아니라 잠시 동안 잠을 잘 수 있습니다 (특히 곧 꼬리에 데이터가있을 것으로 예상되는 경우).

+3

으악. 나는 그것을했지만, 더러운 느낌이 들게했다. – DaGoodBoy

관련 문제