sql >> データベース >  >> NoSQL >> Redis

Redisバックグラウンドジョブが完了した後、flaskのrender_templateを返すにはどうすればよいですか?

    基本的で実行可能なソリューション(要点):

    これを行うには、ジョブをエンキューするルートからリダイレクトし、メタタグでそのページを定期的に更新します。まず、必要なライブラリをインポートします:

    from flask import Flask, redirect, url_for, render_template_string
    app = Flask(__name__)
    
    from time import sleep
    
    from rq import Queue
    from rq.job import Job
    from redis import Redis
    

    rq関連の接続を設定し、実行する関数を定義します。

    r = Redis(host='redisserver')
    q = Queue(connection=r)
    
    def slow_func(data):
        sleep(5)
        return 'Processed %s' % (data,)
    

    次に、5秒ごとにページを更新できるテンプレートを定義します。

    template_str='''<html>
        <head>
          {% if refresh %}
            <meta http-equiv="refresh" content="5">
          {% endif %}
        </head>
        <body>{{result}}</body>
        </html>'''
    

    また、flask render_template_stringを使用して、変数が挿入されたテンプレートを返すヘルパー関数を作成します。 。提供されていない場合、更新はデフォルトでFalseになっていることに注意してください:

    def get_template(data, refresh=False):
        return render_template_string(template_str, result=data, refresh=refresh)
    

    次に、関数をエンキューするルートを作成し、そのrq job-idを取得してから、resultへのリダイレクトを返します。 そのidで表示 。これはURL文字列に入力するだけですが、どこからでも取得できます:

    @app.route('/process/<string:data>')
    def process(data):
        job = q.enqueue(slow_func, data)
        return redirect(url_for('result', id=job.id))
    

    次に、rq.Jobを使用して、実際の結果を処理しましょう。 物体。 "finished"を除くすべての値でページが更新されるため、ここでのロジックを微調整することができます。 :

    @app.route('/result/<string:id>')
    def result(id):
        job = Job.fetch(id, connection=r)
        status = job.get_status()
        if status in ['queued', 'started', 'deferred', 'failed']:
            return get_template(status, refresh=True)
        elif status == 'finished':
            result = job.result 
            # If this is a string, we can simply return it:
            return get_template(result)
    

    ステータスが"finished"の場合 次にjob.result slow_funcの戻り値が含まれます 、ページにこれをレンダリングします。

    この方法には、ジョブの完了を待機している間にサーバーに複数の要求を発生させるという欠点があります。メタリフレッシュタグは少し型破りかもしれません。 Javascriptから更新のリクエストを送信する場合、AJAXリクエストを間隔を置いて送信できるソリューションがありますが、これには同じ複数のリクエストの問題があります。

    別の方法は、WebSocketまたはSSEを使用して、完了したジョブの結果を完了したらすぐにフロントエンドにストリーミングすることです。

    更新:2021年2月27日

    フロントエンドをジョブステータスで更新するSSEメソッドを試してみることにしました。 rq metaの更新をネイティブでサポートしています rq.get_current_jobをインポートすることにより、ジョブ内の属性 ジョブの内部。ジョブの更新後に外部からアクセスできます。

    次のデモコードを参照してください:

    プログレスバー(要点)を使用した基本的な例:




    1. Mongoでnullではないことをどのようにクエリしますか?

    2. 配列に格納されている_idを使用してgolangからmongodbをクエリする

    3. MongoDB $ and Aggregation Pipeline Operator

    4. cronジョブを介してredisにデータを保存する