2013-04-09 3 views
4

Tornado으로 구축 된 작은 웹 응용 프로그램을 가지고 있는데 일부 데이터 저장소에 ZODB을 사용하고 싶습니다. ZODB 문서 (multi-threaded programs are supported, but they should start up a new connection per thread)에 따르면 나는 새로운 연결을 할 쓰기 모든 DB-상호 작용 핸들러하거나 사람을 위해 여전히 필요하다, 즉 내가 먼저ZODB with Tornado

### On startup 
dbFilename = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Data.fs") 
db = DB(FileStorage(dbFilename)) 

### Example handler 
class Example(tornado.web.RequestHandler): 
    def get(self): 
     try: 
      conn = db.open() 
      root = conn.root() 
      ### do stuff with root here 
      root._p_changed = 1 ## Include these lines for writes 
      transaction.commit() ## on sub-elements 
     finally: 
      conn.close() 

같은 것을 할 필요가 있음을 의미한다고 생각? 시작시 하나의 연결을 시작하여 모든 읽기에 사용하는 것이 합리적일까요? 그리고 위의 연결은 내가 뭔가를 쓸 필요가있을 때만 노래와 춤을 할 수 있습니까?

둘째, 패턴을 파이썬에서 추상화하는 관용적 인 방법은 무엇입니까?

def withDB(fn): 
    try: 
     conn = db.open() 
     root = conn.root() 
     res = fn(root) 
     root._p_changed = 1 
     transaction.commit() 
     return res 
    finally: 
     conn.close() 

def delete(formName): 
    def local(root): 
     ### do stuff with root here 
    return withDB(local) 

을 염두에 두었습니다. 그러나 그것은 아마도 Lisp의 내 모습입니다.

접근 방식에 대한 일반적인 점검도 환영합니다.

답변

4

스레드마다 새 연결을 만들어야합니다. ZODB는 각 연결에 일관된 트랜잭션 별보기 (MVCC, 다중 뷰 동시성 제어)를 제공하므로 읽기에도 별도의 연결이 필요합니다. 하나의 스레드에서 순차 요청에 대해 연결을 다시 사용할 수 있습니다.

따라서 연결 당 ZODB.DB에 의해 제공된 스레드 당 풀을 사용합니다 (아마도 pyramid_zodbconn과 같이 요청 당 연결 캐싱). 컨텍스트 매니저가 트랜잭션이 입력에 시작하고, 예외없이 종료에 최선을 다하고 있습니다 보장으로 transaction.manager 객체를 사용

class Example(tornado.web.RequestHandler): 
    def get(self): 
     connection = some_connection_pool.get_connection() 
     with transaction.manager: 
      root = conn.root() 
      res = fn(root) 
      root._p_changed = 1 

: 귀하의 요청 핸들러 내에서

, 당신은 컨텍스트 관리자로 트랜잭션 관리자를 사용할 수 있습니다 , 예외가 발생하면 종료 될 때 중단됩니다.

당신은뿐만 아니라 ZODB 연결을 처리하기 위해 컨텍스트 관리자를 만들 수 있습니다

class Example(tornado.web.RequestHandler): 
    def get(self): 
     with zodbconn(db) as root, transaction.manager: 
      res = fn(root) 
      root._p_changed = 1 

이 컨텍스트는 관리자가 소요 :

from contextlib import contextmanager 

@contextmanager 
def zodbconn(db): 
    conn = db.open() 
    yield conn.root() 
    conn.close() 

후 함께 트랜잭션 관리자와 컨텍스트 매니저 것을 사용 데이터베이스 객체를 반환하고 루트 객체를 반환하여 컨텍스트가 다시 종료 될 때 자동으로 연결을 닫습니다.

+0

흠. [this] (http://zodb.readthedocs.org/en/latest/api.html#connection-pool)에 따르면,'ZODB.DB'는 이미'open()'을 통해 풀링 연결을합니다. 이것은'transaction.manager와 m : db.open (transaction_manager = m) ... '같은 것을 할 수 있다는 것을 의미합니까? – Inaimathi

+0

아 물론, 그렇습니다. 나는 나를 위해 자동으로 연결과 트랜잭션을 처리하는 시스템에 버릇이있다. :-) –