App Engine のタスク キューについて学んでいます。私のアプリケーションには、ドキュメントを処理するタスクがあります。各タスクの完了には約 5 ~ 10 分かかります。私の目的は、Web ページを介して各タスクの進行状況を監視することです。
テストとして、プッシュ キューのチュートリアル コードを単純なループに適合させました (以下を参照)。「アナライザー ページ」フォームが送信されると、新しい「トランザクション ループ」タスクが開始されます。
非同期の「トランザクション ループ」により、タスクが完了するまで「アナライザー ページ」が更新されないことに驚きました。
2 つの質問があります。
非同期タスクがページの更新を停止するのはなぜですか?
タスクの背後にある実装についての私の素朴な見方は、各タスクがスケジュールされたスレッドまたはプロセスであり、「トランザクション ループ」スレッドがデータストア io 中にブロックされ、「アナライザー ページ」スレッドが更新されるというものです。(最終的なコードはこのテストとは大きく異なるため、これは重要ではありません)
データストア/memcache を使用してタスクの進行状況を記録することは、特に書き込みクォータに関してはかなり重いようです。これを行うためのより良い方法はありますか?
ありがとう、
ブライアン
開発サーバー 1.6 でテスト済み:
from google.appengine.api import taskqueue
from google.appengine.ext import db
from google.appengine.ext import webapp
class Counter(db.Model):
count = db.IntegerProperty(indexed=False)
class Analyser(webapp.RequestHandler):
# Analyser Page -- Page refresh (get) only completes after task is called
def get(self):
self.response.write("<html> <body>")
# My first guess was that calling counter.put() blocked the Counter.all()
# call to the datastore.
# However commenting the following code had the same effect.
# self.response.write("Counters:<br>")
# counters = Counter.all()
# for counter in counters:
# self.response.write(str(counter.count) + "<br>")
self.response.write("<form action=\"/api/analyse\" method=\"post\"> \
Key: <input type=\"text\" name=\"key\" /><br /> \
<input type=\"submit\" value=\"Submit\" /> \
</form>")
self.response.write("</body> </html>")
def post(self):
key = self.request.get('key')
# Add the task to the default queue.
taskqueue.add(url='/analyse_worker', params={'key': key})
self.response.write("Added task with key:" + key)
class AnalyserWorker(webapp.RequestHandler):
def post(self): # should run at most 1/s
key = self.request.get('key')
def txn():
counter = Counter.get_by_key_name(key)
if counter is None:
counter = Counter(key_name=key, count=1)
else:
counter.count += 1
counter.put()
# Transaction loop
for i in range(0,200):
db.run_in_transaction(txn)