id:kazunori_279さんのMemcacheでスピンロックを実装してTask Queue処理結果を集約してみるテストに感動したのでpythonで書いてみました。
pythonの練習用にデコレーターにしてみました。*1
ただこれで上の記事の内容をちゃんと実装できているかはちょっと自信がありません。。
#! /usr/bin/python # -*- encoding: utf-8 -*- from google.appengine.api import memcache from functools import wraps import time # 例外 class MemcacheSpinLockError(Exception): def __init__(self,value): self.value = value def __str__(self): return self.value # MemcacheのLock取得 def _acquireLock(key): data = memcache.incr(key) if data is None: memcache.add(key,0) return False else: if data == 1: return True else: memcache.decr(key) return False # MemcacheのLock解除 def _releaseLock(key): memcache.decr(key,1) # MemcacheのLock取得し、関数実行後、Lock解除するデコレータ def runSynchronized(key): def inner(func): def wrapper(*args, **kwargs): n = 0 # 10回Lockを取得しようとして失敗した場合は例外を返す while n < 10: locked = _acquireLock(key) if locked == True: break else: if n <9: n += 1 time.sleep(0.5) else: raise MemcacheSpinLockError(key) try: func(*args,**kwargs) finally: _releaseLock(key) return wraps(func)(wrapper) return inner
使い方
from memcachespinlock import runSynchronized,MemcacheSpinLockError KEY_NAME = "count_up" @runSynchronized("count_up_lock") def count_up(): data = memcache.get(KEY_NAME) if data is not None: data += 1 memcache.set(KEY_NAME,data) else: memcache.add(KEY_NAME,1)
ソースは以下にあります。
http://bitbucket.org/ehren/gae_memcachespinlock/