How to run a background task in Heroku?

自闭症网瘾萝莉.ら 提交于 2021-02-11 12:46:19

问题


I have already build a a python app and deployed it using Flask and Python. Here is my Skelton of my code.

#app.py
@app.route('/', methods=['GET'])
def login():
    '''login process'''

@app.route('/reset-password', methods=['GET'])
def reset_password():
    '''reset password process'''

@app.route('/add-psa', methods=['GET'])
def add_user():
    '''add user process'''

if __name__ == '__main__':
    app.debug = True
    app.run(use_reloader=False, threaded=True)

Deployed app work fine in the Heroku. But sometime it takes more than 30 seconds to response which means H12 error according to Heroku doc. So I followed this tutorial to run background job. Here is what I've done so far

#worker.py
import os

import redis
from rq import Worker, Queue, Connection

listen = ['high', 'default', 'low']

redis_url = os.getenv('REDISTOGO_URL', 'redis://localhost:6379')

conn = redis.from_url(redis_url)

if __name__ == '__main__':
    with Connection(conn):
        worker = Worker(map(Queue, listen))
        worker.work()

Next...

#utils.py
import requests

def count_words_at_url(url):
    resp = requests.get(url)
    return len(resp.text.split())

I also made change in the Procfile and requirements.txt

I want to run my reset_password() in background since its taking more than 30seconds. Any one who can help me on this?


回答1:


A solution is to spawn a thread from the web request: in this case the response can be returned (almost) immediately while a background thread starts and performs the necessary task (without the constraint of the HTTP timeout)

# my background thread
class MyWorker():

  def __init__(self, message):
    self.message = message

    thread = threading.Thread(target=self.run, args=())
    thread.daemon = True
    thread.start()

  def run(self):
    logging.info(f'run MyWorker with parameter {self.message}')

    # do something

The web request creates an instance of the thread and could inform the caller something is in progress (or apply a different workflow/message)

#app.py
@app.route('/reset-password', methods=['GET'])
def reset_password():
'''reset password process'''
   MyWorker('param_value')
   return "In progress... You will receive an email"


来源:https://stackoverflow.com/questions/64474892/how-to-run-a-background-task-in-heroku

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!