App Engineã§ã®ãã©ã³ã¶ã¯ã·ã§ã³ã®åé¢
http://code.google.com/appengine/articles/transaction_isolation.html
ã¯ããã«
Wikipediaã«ããã¨ãã¼ã¿ãã¼ã¹ç®¡çã·ã¹ãã ã®ãã©ã³ã¶ã¯ã·ã§ã³ã®åé¢ã¬ãã«ã¯ãããæä½ã«ããå¤æ´ã並åã«å®è¡ãããä»ã®æä½ããè¦ããããã«ãªãã¿ã¤ãã³ã°ã¨ãã®æ段ã«ãã£ã¦å®ç¾©ããããããã ããã®è¨äºã§ã¯Google App Engineãã¼ã¿ã¹ãã¢ã§ã®ãã©ã³ã¶ã¯ã·ã§ã³ã®åé¢ã«ã¤ãã¦èª¬æããããè¨äºãèªãã°ä¸¦åãªèªã¿æ¸ããã©ã®ããã«å®è¡ããããããæ·±ãç解ãå¾ãããã ããã
Read Committed
ãã¼ã¿ãã¼ã¹ã«ãã£ã¦ãµãã¼ããããåé¢ã¬ãã«ã¯4ã¤(Serializable, Repeatable Read, Read Committed, Read Uncommitted)ã ãããã¼ã¿ã¹ãã¢ã®åé¢ã¬ãã«ã¯ãã®ãã¡ã®Read Committedã¨ã»ã¨ãã©åãã ããã¼ã¿ã¹ãã¢ããã¯ã¨ãªã¾ãã¯get()ã§èªã¿è¾¼ã¾ããã¨ã³ãã£ãã£ã¯ã³ãããããããã¼ã¿ã®ã¿ãããªããèªã¿è¾¼ã¾ãããã¼ã¿ãé¨åçã«ã³ãããããããã¼ã¿ãã¤ã¾ãããã¤ãã®ãã¼ã¿ãã³ãããåã®ãã¼ã¿ã§ãã以å¤ãã³ãããå¾ãã¨ãããã¨ã¯ããããªãããã ããã¯ã¨ãªã¨ãã©ã³ã¶ã¯ã·ã§ã³ã®ããã¨ãã¯ããå°ãåããã«ããããããç解ããã«ã¯commit()ã®ããã»ã¹ã«ã¤ãã¦ç´°ããè¦ãå¿ è¦ãããã ããã
commit()ããã»ã¹
commit()ã«ã¯ãã¤ã«ã¹ãã¼ã³ãäºã¤ãããã¨ã³ãã£ãã£ã®å¤æ´ãé©ç¨ãããã¨ãã¨ãã¨ã³ãã£ãã£ã®ã¤ã³ããã¯ã¹ã®å¤æ´ãé©ç¨ãããã¨ãã ãæåã®ãã¤ã³ãããã¤ã«ã¹ãã¼ã³Aã次ã®ãã¤ã³ããcommit()ãçµäºããã¨ããããã¤ã«ã¹ãã¼ã³Bã¨å¼ã¼ãããã¤ã«ã¹ãã¼ã³Aã«å°éããã¨ãã«ã¯ã¨ã³ãã£ãã£ã«ã¯å ¨ã¦ã®å¤æ´ãé©ç¨ããã¦ããããã¤ã«ã¹ãã¼ã³Bã«å°éããã¨ã¨ã³ãã£ãã£ã®ã¤ã³ããã¯ã¹ã®å¤æ´ãé©ç¨ããã¦ããã
ãã¤ã«ã¹ãã¼ã³Aã®ãã¨ã§æ´æ°ãããã¨ã³ãã£ãã£ããã¼ã使ã£ã¦æ¤ç´¢ããã¨ãã¨ã³ãã£ãã£ã®ææ°ãã¼ã¸ã§ã³ãå¾ããããã¨ã¯ä¿è¨¼ããã¦ããããã ããããåæã«å±ãããªã¯ã¨ã¹ããå®è¡ããã¯ã¨ãªã®è¿°èª(SQL/GQLçã«è¨ãã°`WHEREå¥')ãæ´æ°åã®ã¨ã³ãã£ãã£ã«åè´ãããæ´æ°å¾ã®ã¨ã³ãã£ãã£ã«åè´ãããªãããã¤ã«ã¹ãã¼ã³Bã«å°éããcommit()æä½ã®å¾ã ã£ãå ´åã ããã®ã¨ã³ããªã¯ãªã¶ã«ãã»ããã«å«ã¾ãããã¤ã¾ãã ãã³ã®çãéãããä¸åº¦ãã¼ã使ã£ã¦æ¤ç´¢ãã¦ãã¯ã¨ãªã®æ¡ä»¶ãæºãããªãã¨ã³ãã£ãã£ããªã¶ã«ãã»ããã«å«ã¾ãããã¨ããããã¯ã¨ãªãã©ã®ã¨ã³ãã£ãã£ãè¿ãã決å®ããéã«ã¯ãã¤ã«ã¹ãã¼ã³Aã¨ãã¤ã«ã¹ãã¼ã³Bã®éã«ããã¢ã«ã¦ã³ãã®å¤æ´ã¯è¦ããªãããã¯ã¨ãªãç¹å®ã®ã¨ã³ãã£ãã£ãè¿ããã¨ã決å®ãããã¨ã¯å¸¸ã«ãã¤ã«ã¹ãã¼ã³Aãã¼ã¸ã§ã³ã®ã¨ã³ãã£ãã£ãæ»ãããã¨è¨ããã¨ã«æ³¨æãããã
ä¾
並åãªæ´æ°ã¨ã¯ã¨ãªãã©ã®ããã«ç¸äºä½ç¨ãããä¸è¬çãªèª¬æããã¦ãããã©ãç§ãªãå ·ä½çãªä¾ãä¸éãçºããæ¹ããã®ã³ã³ã»ãããç°¡åã«ç解ã§ããã¨æããã¡ãã£ã¨è¦ã¦ã¿ãããåç´ãªã±ã¼ã¹ããåãã¦ãæçµçã«ããèå³æ·±ãä¾ãæä¾ãããã
Personã¨ã³ãã£ãã£ãæã¤ã¢ããªã±ã¼ã·ã§ã³ãèããããPersonã«ã¯æ¬¡ã®ãããªå±æ§ããã:
- åå
- 身é·
ã¾ããã¢ããªã±ã¼ã·ã§ã³ã¯æ¬¡ã®ãããªæä½ãã§ãã:
- updatePerson()
- getTallPeople(), 72ã¤ã³ããããèã®é«ã人ãå ¨ã¦è¿ã
ãã¼ã¿ã¹ãã¢ã«ã¯2ã¤ã®Personã¨ã³ãã£ãã£ãåå¨ãã:
- ã¢ãã , 身é·68ã¤ã³ã
- ãã, 身é·73ã¤ã³ã
ä¾1 â ã¢ãã ã大ãããã
ã¢ããªã±ã¼ã·ã§ã³ãå ¨ãåãã¿ã¤ãã³ã°ã§ãªã¯ã¨ã¹ããäºã¤åãåã£ãã¨ããããæåã®ãªã¯ã¨ã¹ãã§ã¯ã¢ãã ã®èº«é·ã68ã¤ã³ããã74ã¤ã³ãã«ãããççºçãªæé·ï¼ã§ãäºã¤ç®ã®ãªã¯ã¨ã¹ãã¯getTallPeople()ãå¼ã³åºãããã¦getTallPeople()ãè¿ãå¤ã¯ã©ããªãï¼
ãã®åçã¯ãªã¯ã¨ã¹ã1ã«ãã£ã¦èµ·åãããäºã¤ã®commit()ãã¤ã«ã¹ãã¼ã³ã¨ããªã¯ã¨ã¹ã2ã«ãã£ã¦å®è¡ãããgetTallPeople()ã¯ã¨ãªã®é¢ä¿ã«ããã次ã®ããã ã¨ããã¨:
- ãªã¯ã¨ã¹ã1ã put()
- ãªã¯ã¨ã¹ã2ã getTallPeople()
- ãªã¯ã¨ã¹ã1ã put()-->commit()
- ãªã¯ã¨ã¹ã1ã put()-->commit()-->ãã¤ã«ã¹ãã¼ã³A
- ãªã¯ã¨ã¹ã1ã put()-->commit()-->ãã¤ã«ã¹ãã¼ã³B
ãã®ã·ããªãªã ã¨getTallPeople()ã¯ããã ããè¿ãããªããã£ã¦ï¼ããã¯ã¢ãã ã®èº«é·ãé«ãããããã®å¤æ´ãã¾ã ã³ãããããã¦ããªãã¦ããªã¯ã¨ã¹ã2ãçºè¡ããã¯ã¨ãªããã¯ã¾ã è¦ããªãããã ã
次ã«ãã®ãããªãã®ãèãã¦ã¿ã:
- ãªã¯ã¨ã¹ã1ã put()
- ãªã¯ã¨ã¹ã1ã put()-->commit()
- ãªã¯ã¨ã¹ã1ã put()-->commit()-->ãã¤ã«ã¹ãã¼ã³A
- ãªã¯ã¨ã¹ã2ã getTallPeople()
- ãªã¯ã¨ã¹ã1ã put()-->commit()-->ãã¤ã«ã¹ãã¼ã³B
ãã®ã·ããªãªã§ã¯ãªã¯ã¨ã¹ã1ããã¤ã«ã¹ãã¼ã³Bã«å±ãåã«ã¯ã¨ãªãå®è¡ããã¦ãããã¤ã¾ãPersonã®ã¤ã³ããã¯ã¹ã¸ã®å¤æ´ã¯ã¾ã é©ç¨ããã¦ããªãããã®ããçµå±getTallPeople()ã¯ããã ããè¿ããã¨ã«ãªãããããã¯ã¨ãªã®æ¡ä»¶ãæºããããããã£ãæã¤ã¨ã³ãã£ãã£ããªã¶ã«ãã»ããã«å«ã¾ããªãå ´åã®ä¾ã ã
ä¾2 â ãããå°ããããï¼ããããããï¼
ãã¡ãã®ä¾ã§ã¯ãªã¯ã¨ã¹ã1ãã¡ãã£ã¨éããã¢ãã ã®èº«é·ã68ã¤ã³ããã74ã¤ã³ãã«å¢ããã®ã§ã¯ãªãããã®èº«é·ã73ã¤ã³ããã65ã¤ã³ãã«æ¸ããããã®å ´åãgetTallPeople()ã¯ã©ããªãã ãã
- ãªã¯ã¨ã¹ã1ã put()
- ãªã¯ã¨ã¹ã2ã getTallPeople()
- ãªã¯ã¨ã¹ã1ã put()-->commit()
- ãªã¯ã¨ã¹ã1ã put()-->commit()-->ãã¤ã«ã¹ãã¼ã³A
- ãªã¯ã¨ã¹ã1ã put()-->commit()-->ãã¤ã«ã¹ãã¼ã³B
ãã®ã·ããªãªã§ã¯getTallPeople()ã¯ãããè¿ãããªããï¼ããã®èº«é·ãæ¸ããæ´æ°ãã¾ã ã³ãããããã¦ããªãã®ã§ããªã¯ã¨ã¹ã2ã«çºè¡ãããã¯ã¨ãªã«ã¯ã¾ã å¤æ´ãè¦ããªãããã ã
次ã«ãã®ãããªä¾ãèããã:
- ãªã¯ã¨ã¹ã1ã put()
- ãªã¯ã¨ã¹ã1ã put()-->commit()
- ãªã¯ã¨ã¹ã1ã put()-->commit()-->ãã¤ã«ã¹ãã¼ã³A
- ãªã¯ã¨ã¹ã1ã put()-->commit()-->ãã¤ã«ã¹ãã¼ã³B
- ãªã¯ã¨ã¹ã2ã getTallPeople()
ãã®ã·ããªãªã ã¨getTallPeople()ã¯èª°ãè¿ããªããããã®èº«é·ãæ¸ããå¤æ´ã¯ãªã¯ã¨ã¹ã2ã®ã¯ã¨ãªãçºè¡ãããæç¹ã§ã³ãããããã¦ããããã ã
次ã«ãã®ãããªä¾ãèããã:
- ãªã¯ã¨ã¹ã1ã put()
- ãªã¯ã¨ã¹ã1ã put()-->commit()
- ãªã¯ã¨ã¹ã1ã put()-->commit()-->ãã¤ã«ã¹ãã¼ã³A
- ãªã¯ã¨ã¹ã2ã getTallPeople()
- ãªã¯ã¨ã¹ã1ã put()-->commit()-->ãã¤ã«ã¹ãã¼ã³B
ãã®ã·ããªãªã§ã¯ãã¤ã«ã¹ãã¼ã³Bã®åã«ã¯ã¨ãªãå®è¡ãããã®ã§ãPersonã®ã¤ã³ããã¯ã¹ã®å¤æ´ã¯ã¾ã é©ç¨ããã¦ããªãããã®ããgetTallPeople()ã¯ã¾ã ãããè¿ãããPersonã®heightããããã£ã¯æ´æ°ãããå¤ã65ãè¿ãããããããããã£ãã¯ã¨ãªã®æ¡ä»¶ãæºãããªãã¨ã³ãã£ãã£ããªã¶ã«ãã»ããã«å«ã¾ããå ´åã®ä¾ã ã
ã¾ã¨ã
ä¸è¨ã®ä¾ããåããããã«ãGoogle App Engineãã¼ã¿ã¹ãã¢ã®ãã©ã³ã¶ã¯ã·ã§ã³åé¢ã¬ãã«ã¯Read Committedã¨æ¥µãã¦è¿ãããã¡ããéè¦ãªéããããããã§ã«åã¯ãã®éãã¨çç±ãç解ããã ããããã£ã¨åã®ã¢ããªã±ã¼ã·ã§ã³ã«ã¤ãã¦ããè³¢æã§ãã¼ã¿ã¹ãã¢ã«é©ãã決å®ãä¸ããããã«ãªã£ãã¯ãã ã
Pythonã®ãã³ã¬ã¼ã¿ãé¢ç½ãã®ã§Rubyã§å®è£ ãã¦ã¿ã
ã»ã»ã»ãã©ãã¾ãã¡ã ã£ãorz
ä¸å¿èª¬æããã¨ããã³ã¬ã¼ã¿ã£ã¦è¨ãã®ã¯Pythonã«ããã¢ããã¼ã·ã§ã³ã§ã¡ã½ãããæ¡å¼µã§ããæ©è½ã»ã»ã»ãããã
ä»åã®ç®æ¨ã¯ãããåãããã¨ã(@declareArgs(float, float)ããã³ã¬ã¼ã¿)
http://www.itmedia.co.jp/enterprise/articles/0501/24/news034_3.html
# http://www.itmedia.co.jp/enterprise/articles/0501/24/news034_3.html import math def declareArgs(*argTypes): def checkArguments(func): assert func.func_code.co_argcount == len(argTypes) def wrapper(*args, **kwargs): pos = 1 for (arg, argType) in zip(args, argTypes): assert isinstance(arg, argType), \ "Value %r dose not match %s at %d" % (arg, argType, pos) pos += 1 return func(*args, **kwargs) wrapper.func_name = func.func_name return wrapper return checkArguments @declareArgs(float, float) def calcDistance(x, y): return math.sqrt(x * x + y * y) print calcDistance(3.14, 1.592) print calcDistance(2.0, 4)
å®è¡çµæã
# http://www.itmedia.co.jp/enterprise/articles/0501/24/news034_3.html $ /opt/Python-2.4/bin/python DecoratorTest.py 3.52052041607 Traceback (most recent call last): File "DecoratorTest.py", line 27, in ? print calcDistance(2.0, 4) File "DecoratorTest.py", line 11, in wrapper assert isinstance(arg, argType), \ AssertionError: Value 4 dose not match at 2
ã¦ãããããªãã§ITmediaã¯ãã³ã¬ã¼ã¿ã®èª¬æãªã®ã«ãããããªãã¬ã¯ã·ã§ã³ä½¿ãã¾ãã£ãä¾ã«ãããã ããã移æ¤ãããã©ããã»ã»ã»ã
ã¨ãããããã³ã¬ã¼ã¿ã¯ãããªæãã®å®è£ ã«ãã¦ã¿ãã
# decorator.rb module Kernel def decorate(decorator, target) decorator = method(decorator) if decorator.is_a? Symbol method_name, method_body = case target when Method [target.to_s.sub(/#<Method: (\w+)#(\w+)>/, '\2'), target] else [target, nil] end if self.is_a? Class method_body ||= instance_method(target).bind(self.new) define_method method_name, &decorator.call(method_body) else method_body ||= method(target) self.class.instance_eval{define_method method_name, &decorator.call(method_body)} end end end
使ã£ã¦ã¿ãã¨ããã¯ããã
require 'decorator' def declare_args(*arg_types) lambda do |func| raise <<-eos.strip unless func.arity == arg_types.size The number of arguments, #{func.arity}, should be #{arg_types.size}. eos lambda do |*args| args.size.times do |pos| arg, arg_type = args[pos], arg_types[pos] raise <<-eos.strip unless arg.instance_of? arg_type Value #{arg} does not match #{arg_type} at #{pos}. eos end func.call(*args) end end end def calc_distance(x, y) Math.sqrt(x * x + y * y) end decorate declare_args(Float, Float), :calc_distance puts calc_distance(3.14, 1.592) puts calc_distance(2.0, 4)
å®è¡çµæ
% ruby dec1.rb 3.52052041607487 dec1.rb:12:in `calc_distance': Value 4 does not match Float at 1. (RuntimeError) from dec1.rb:10:in `times' from dec1.rb:10:in `calc_distance' from dec1.rb:27
ãã¼ãã¾ãä¸å¿åãã¦ããã ãã©ãã¢ããã¼ãã¿ããã«ã¡ã½ããå®ç¾©ã®åã«ä»ããããªãã®ããªãã»ã»ã»ããã¨ãã³ã¬ã¼ã¿ã®å®è£ è¦ãã°åãããã©ãinstance_method(target).bind(self.new) âããã§æ°ããnewãããªãã¸ã§ã¯ãããã¤ã³ããã¦ãã®ãææªããªãã¨ããã¾ãå®è¡æã®ã¤ã³ã¹ã¿ã³ã¹å¼ã£å¼µã£ã¦æ¥ããªããããã
ã¾ãçµå±ãããããã®ã¯ActiveSupportã®alias_method_chainã使ã£ãã»ããããã¨æã£ãã