3

I'm studying Flask and tried to create small website on Heroku. I got timeout error with long task when deploy on Heroku and can by pass with timeout increasement. After investigate more, I found another solution is streamming. Here's article close with my solution: https://librenepal.com/article/flask-and-heroku-timeout/ But it's not work. Error still appears after 30 second Code from the article:

from flask import Flask, Response
import requests

app = Flask(__name__)

def some_long_calculation(number):
  '''
  here will be some long calculation using this number
  let's simulate that using sleep for now :)
  '''
  import time
  time.sleep(5)

  return number

@app.route('/')
def check():
    def generate():
      for i in range(10):
        yield "<br/>"   # notice that we are yielding something as soon as possible
        yield str(some_long_calculation(i))
    return Response(generate(), mimetype='text/html')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)

Do you have any idea about this problem?

3 Answers3

2

You can avoid heroku's 30 seconds limit by using streaming response, and I just confirmed it's working.

I'm using flask w/ gunicorn in heroku, and the thing that I need to do other than the link's example code is changing the gunicorn timeout settings: web: gunicorn "app.app:create_app()" --timeout 600 in my case. The default timeout was 30 seconds, which happens to be the same as heroku's timeout setup.

UGO
  • 353
  • 3
  • 13
0

EDIT: I originally answered this question in 2016 when the below information was true. Today, you can indeed surpass the 30-second timeout using streaming responses.

You cannot get around the 30 second timeout behavior on the request-response cycle on Heroku. This is enforced through the Heroku routing mesh.

If you need to make long-running requests like this, you have a few options:

  1. Put large data into a file on S3 or some other file storage service. When people make a request, send them the file URL, and let them download it there. (this is most optimal)
  2. Use websockets. Web sockets are, by definition, persistent TCP connections that never close between the browser and the server. This is really ideal for apps that require continuous back-and-fourth communication like what you're describing.
rdegges
  • 32,786
  • 20
  • 85
  • 109
  • thank rdegges for clear answer and stop me googling for non-existing answer – Nguyễn Tiến Lộc Jan 03 '17 at 10:41
  • I'm very late but this is not true. You can go around 30 seconds request timeout limit by streaming response. – UGO Sep 21 '19 at 11:16
  • Update, as of a while ago, my answer is outdated. This has changed since 2016 when I wrote this answer. I'm somehow unable to edit my answer, so leaving this comment here to help new readers. – rdegges Oct 10 '19 at 17:36
0

In case it helps you, this is my solution with the streaming support with Ruby and Rails. Even with that support I had to be careful with some response headers settings.

MegaTux
  • 1,591
  • 21
  • 26