gae アプリ 開発メモ

Google App Engine アプリの開発メモ / 言語: python, javascript / ビギナー

memcacheでCriticalSectionを書いてみた

gaeアプリケーションでいくつものリクエストを受けた時、相互に排他制御できる仕組みが欲しい。
memcache.incr(), decr()はアトミック操作できる。
ということで、こいつを使って CriticalSection を書いてみた。

from google.appengine.api import memcache
import datetime
import time

class CriticalSection(object):
    def __init__(self, key, namespace = None, autolock = False):
        self.key = key
        self.namespace = namespace
        self.locked = False
        if autolock:
            self.lock()

    def __del__(self):
        self.unlock()

    def lock(self):
        assert not self.locked

        # 最大リトライ 250ms * 60times = 15sec
        for retry in range(60):
            # ここでロック
            count = memcache.incr(key = self.key, namespace = self.namespace, initial_value = 0)
            if count == 1:
                self.locked = True
                return True

            memcache.decr(key = self.key, namespace = self.namespace)

            # 250ms 待つ
            time.sleep(0.25)
        return False

    def unlock(self):
        if self.locked:
            self.locked = False
            # ここでアンロック
            memcache.decr(key = self.key, namespace = self.namespace)

def test():
  print 'start: ' + str(datetime.datetime.now())
  csection = CriticalSection('lock', autolock = True)

  print 'testing now...' + str(datetime.datetime.now())
  time.sleep(5.0)

  print 'done.' + str(datetime.datetime.now())

test()

今回はロックされていることを検出したら、250ms 毎にポーリングする仕組みを書いた。
ロックの解除をうまく検出できるといいんだけど、知識が足りなくていい知恵が思い浮かばん。