次の例のように、取引内容に基づいてキーを作成することができます。
import datetime
import hashlib
>>> txn = {
'from_account': '100123',
'to_account': '200456',
'amount': 123456,
'timestamp': datetime.datetime(2017, 9, 23, 10, 11, 12, 123456)
}
# Combine the values into a string
>>> raw_key = u''.join([unicode(v) for k, v in sorted(txn.items())])
>>> print raw_key
12345610-09-23 10:11:12.123456200456
# hash the key so exposing it in logs etc. doesn't expose transaction data
>>> key = hashlib.sha256().hexdigest()
>>> print key
261c516faa580d6604850967c5804f3fce5f323aae90e36debdb84aa0b950dcb
をあなたがデータストアでハッシュされたキーを保存したり、持っていれば、それはあなたのトランザクションモデルの計算されたプロパティにすることができます新しいトランザクションを作成しようとする前にクエリを実行します。
class TransactionKeys(ndb.model):
pass
class TransactionHandler(webapp2.RequestHandler):
def post(self):
txn = {
'from_account': self.request.POST['from'],
'to_account': self.request.POST['to'],
'value': self.request.POST['value']
'timestamp': datetime.datetime.now()
}
raw_key = u''.join([unicode(v) for k, v in sorted(txn.items())])
txn_key = hashlib.sha256().hexdigest()
...
transfer(from_key, to_key, amount, txn_key)
@ndb.transactional(xg=True)
def transfer(from_key, to_key, amount, txn_key)
already_exists = TransactionKeys.get_by_id(txn_key)
if already_exists:
raise DuplicateTransactionError('Duplicate transaction!')
else:
transaction_key = TransactionKey(id=txn_key)
from = from_key.get()
to = to_key.get()
from.balance -= amount
to.balance += amount
ndb.put_multi([from, to, txn_key])
この方法は完璧ではありません - 二つの同一のトランザクションが例えば同じマイクロ秒で到着する場合、それは失敗します。 App EngineのインスタンスIDやリクエストIDなど、他のデータを追加してキーをより一意にすることができます。
最後に義務的な免責事項:私はセキュリティ専門家ではありません。実際のお金でこれを行う場合は、適切なレベルのデューデリジェンスを実施し、専門的補償/公的責任保険を検討する必要があります。
この古い記事を読んでください。 appengineには多くの新機能が登場する前に書かれていましたが、やっていることを実装するためのガイドとして見ておく価値があります。 http://blog.notdot.net/2009/9/Distributed-Transactions-on-App-Engine –