문제

나는 작은 딜레마를 쳤다! 나는 투표라는 핸들러가 있습니다. 그것이 호출되면, 그것은 그들이 선택한 모든 것에 대한 사용자의 투표를 설정합니다. 이전에 선택한 옵션을 기억하기 위해 현재 투표가 설정된 내용을 자세히 설명하는 유권자 옵션을 저장합니다.

물론, 그들이 처음 투표 할 때, 나는 물건을 만들고 그것을 저장해야합니다. 그러나 연속 투표는 기존 유권자의 가치 만 변경해야합니다. 그러나 그는 문제가 발생합니다. 어떤 상황에서는 두 개의 유권자가 만들어 질 수 있습니다. 드물지만 (지금까지 본 500 표에서 한 번만 발생했지만) 여전히 그렇게 할 때 여전히 나쁩니다.

이 문제는 두 개의 별도의 핸들러가 본질적으로 다음을 수행하기 때문에 발생합니다.

query = VoteRecord.all().filter('user =', session.user).filter('poll =', poll)

if query.count(1) > 0:
 vote = query[0]

 poll.votes[vote.option] -= 1
 poll.votes[option] += 1
 poll.put()

 vote.option = option
 vote.updated = datetime.now()
 vote.put()
else:
 vote = VoteRecord()
 vote.user = session.user
 vote.poll = poll
 vote.option = option
 vote.put()

 poll.votes[option] += 1
 poll.put()

 session.user.votes += 1
 session.user.xp += 3
 session.user.put()

 incr('votes')

내 질문은 : 요청이없고 요청이 없는지 확인하면서 이러한 요청을 처리하는 가장 효과적이고 빠른 방법은 무엇입니까?

도움이 되었습니까?

해결책

문제는이 부분입니다.

if vote.count(1) == 0:
    obj = VoteRecord()
    obj.user = user
    obj.option = option
    obj.put()

트랜잭션이 없으면 코드 가이 순서로 두 개의 통역사 인스턴스에서 실행될 수 있습니다.

if vote.count(1) == 0:
    obj = VoteRecord()
    obj.user = user


if vote.count(1) == 0:
    obj = VoteRecord()
    obj.user = user
    obj.option = option
    obj.put()


    obj.option = option
    obj.put()

또는 그 이상한 조합. 문제는 풋이 발생하기 전에 카운트 테스트가 다시 실행되므로 두 번째 스레드는 두 번째 대신 조건부의 첫 번째 부분을 통과합니다.

코드를 함수에 넣은 다음 사용 하여이 문제를 해결할 수 있습니다.

db.run_in_transaction()

기능을 실행합니다.

문제는 트랜잭션에 넣어야하는 의사 결정 논리에 대한 쿼리로 반환 된 객체 수에 의존하는 것 같습니다. Google I/O 대화를 읽거나 그룹을 보면 권장되지 않는다는 것을 알 수 있습니다. 쿼리를 거래 할 수 없기 때문입니다. 대신, 카운트를 어딘가에 엔티티 값으로 저장해야합니다. 밖의 트랜잭션 함수의 다음 해당 엔티티의 키를 트랜잭션 기능으로 전달하십시오.

다음은 엔티티 속성을 확인하는 트랜잭션 기능의 예입니다. 키를 매개 변수로 전달했습니다.

def checkAndLockPage(pageKey):
  page = db.get(pageKey)
  if page.locked:
    return False
  else:
    page.locked = True
    page.put()
    return True

한 번에 한 명의 사용자만이 엔티티를 잠글 수 있으며 중복 잠금 장치는 없습니다.

다른 팁

이 작업을 수행하는 가장 쉬운 방법은 투표 객체에 키 이름을 사용하고 Model.get_or_insert를 사용하는 것입니다. 먼저, 키 이름에 대한 명명 체계를 생각해냅니다. 여론 조사 후에 이름 지정이 좋은 아이디어입니다. 그런 다음 get_or_insert를 수행하여 관련 엔티티를 가져 오거나 만듭니다.

vote = VoteRecord.get_or_insert(pollname, parent=session.user, user=session.user, poll=poll, option=option)
if vote.option != option:
  # Record already existed; we need to update it
  vote.option = option
  vote.put()
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top