2010-02-13 3 views
2

코드 모듈화 및 디커플링을 유지하면서 트랜잭션을 두 번 입력하지 않는 가장 좋은 방법은 무엇입니까?엔티티 데이터를 트랜잭션 방식으로 수정 (필요에 따라)

엔티티에는 종종 데이터를로드, 수정 및 저장하는 클래스 메소드가 있습니다. 종종 이것은 아동/형제/사촌 실체와 일치하기 위해 트랜잭션이어야합니다. 다음은 패턴입니다.

class MyEntity(db.Model): 
    # ... some properties 

    @classmethod 
    def update_count(cls, my_key): 
    def txn(): 
     me = db.get(my_key) 
     me.count += 23 
     me.put() 
     OtherEntity.update_descendants(ancestor=me) 
    return db.run_in_transaction(txn) 

일반적으로 엔티티를 가져 와서 수정하고 한 번에 저장해야합니다. 그 기술 더 performant이다; 때로는 모듈성 및 유지 관리보다 성능이 중요하지 않은 경우도 있습니다. 두 업데이트는 분리되어야합니다. (아마도 update_descendants는 분리 종종라고하며 데이터를 저장하기위한 책임이 있습니다.)

을하지만, 다음 코드는 버그 :

>>> MyEntity.update_count(my_key=some_key_i_have) 
Traceback (most recent call last): 
    ... 
BadRequestError: Nested transactions are not supported. 

: 예외가 발생

class OtherEntity(db.Model): 
    # ... some properties 

    @classmethod 
    def update_descendants(cls, ancestor): 
    def txn(): # XXX Bug! 
     descendants = cls.all().ancestor(ancestor).fetch(10) 
     for descendant in descendants: 
     descendant.update_yourself(ancestor.count) 
     db.put(descendants) 
    return db.run_in_transaction(txn) 

그렇다면 어떻게 모듈성과 정확성의 두 가지 장점을 모두 얻을 수 있습니까?

답변

2

내가 사용하는 패턴은 트랜잭션 동작이 필요한지 여부를 나타내는 매개 변수를 갖는 것입니다.

class OtherEntity(db.Model): 
# ... some properties 

@classmethod 
def update_descendants(cls, ancestor, with_transaction=True): 
    if with_transaction: 
    return db.run_in_transaction(cls.update_descendants, ancestor, 
           with_transaction=False) 

    # Now I can assume I am in a transaction one way or another... 
    descendants = cls.all().ancestor(ancestor).fetch(10) 
    for descendant in descendants: 
    descendant.update_yourself(ancestor.count) 
    return db.put(descendants) 

같은 원칙

put에 대한 책임을, 또는 발신자에게 맡겨 여부를 나타 내기 위해 확장 될 수있다.

+1

기록을 위해, 나는 Erlang ("country")을 너무 많이 사용하고 Rails ("rock and roll")를 너무 많이 사용하여 내 작업에서이 작업을 시작했습니다. – JasonSmith

1

트랜잭션 기능을 최상위 클래스 메소드로 만드는 것이 좋습니다. 그런 다음 직접 또는 db.run_in_transaction으로 전화 할 수 있습니다.

+0

고마워, 닉. 내가 제시 한 답변의 논리를 바꾸면 (기본적으로 거래가 사용 중지됨) 기본적으로 귀하의 제안이됩니다. – JasonSmith

+0

나는 개인적으로 당신이 기술하는 기술을 사용하지 않는다고 말해야 만합니다. 나는 트랜잭션이 필요한지를 지정하거나 계산하는 것을 선호하며, 그 정보를보다 기능적인 스타일로 콜 체인에 전달하는 것을 선호한다. 개인적인 취향의 문제라고 생각합니다. – JasonSmith

관련 문제