0

App Engine のタスク キューについて学んでいます。私のアプリケーションには、ドキュメントを処理するタスクがあります。各タスクの完了には約 5 ~ 10 分かかります。私の目的は、Web ページを介して各タスクの進行状況を監視することです。

テストとして、プッシュ キューのチュートリアル コードを単純なループに適合させました (以下を参照)。「アナライザー ページ」フォームが送信されると、新しい「トランザクション ループ」タスクが開始されます。

非同期の「トランザクション ループ」により、タスクが完了するまで「アナライザー ページ」が更新されないことに驚きました。

2 つの質問があります。

  1. 非同期タスクがページの更新を停止するのはなぜですか?

    タスクの背後にある実装についての私の素朴な見方は、各タスクがスケジュールされたスレッドまたはプロセスであり、「トランザクション ループ」スレッドがデータストア io 中にブロックされ、「アナライザー ページ」スレッドが更新されるというものです。(最終的なコードはこのテストとは大きく異なるため、これは重要ではありません)

  2. データストア/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)
4

1 に答える 1

2

dev appserverはシングルスレッドであるため、タスクが完了するまで更新ページがブロックされます。

于 2012-06-20T22:46:52.330 に答える