Django Channel 2 with Daphne on Heroku crash on starting - django

I created a django app using Channels 2 on heroku but it crash on starting with 503 error code.
2020-04-07T10:05:35.226253+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=www.mysite.com request_id=317bfbe6-9055-4957-9fbb-8190616c3964 fwd="" dyno= connect= service= status=503 bytes= protocol=https
Procfile :
release: python manage.py migrate
web : daphne myproject.asgi:application --port $PORT --bind 0.0.0.0 -v2
worker: python manage.py runworker channels -v2
settings.py
ASGI_APPLICATION = 'myproject.routing.application'
# Channels
CHANNEL_LAYERS = {
"default": {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
"CONFIG": {
"hosts": [os.environ.get('REDIS_URL', 'redis://localhost:6379')],
},
},
}
asgi.py
import os
import django
from channels.routing import get_default_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings")
django.setup()
application = get_default_application()

Have you created an instance of the process web in heroku?
You can do it in command line : heroku ps:scale worker=1
Give worker in Procfile as:
worker: python manage.py runworker channels --settings=<project-name>.settings -v2

Your Procfile should have this instead :
release: python3 manage.py makemigrations && python3 manage.py migrate
web: daphne domecode.asgi:application --port $PORT --bind 0.0.0.0 -v2
worker: python3 manage.py runworker channel_layer -v2
channel_layer instead of channels. Why? Well, look at your settings again, you've declared CHANNEL_LAYER there which you run locally on a Redis instance on Docker. However when deploying you can't run it on Docker ( I mean you technically can use Docker Swarms on Digital Ocean or AWS, I'm not sure how it works on Heroku ) so you need to change it to channel_layer.

Related

heroku run python manage.py makemigrations -a myapp takes forever

I have added this to my setting.py
DATABASE_URL = os.environ.get('DATABASE_URL')
db_from_env = dj_database_url.config(default=DATABASE_URL)
DATABASES['default'].update(db_from_env)
and yet when I run
heroku run python manage.py makemigrations -a myapp
it stucks in connecting process. Does anyone know how to solve this?

Flask webserver in Heroku returning 404 when serving CSS files

Website works for everything except CSS files. Static images works, static javascript works, favicon works, but CSS returns 404. I've tried different browsers and cache-reload on web browser.
Application logs:
2021-08-04T15:17:38.416574+00:00 heroku[router]: at=info method=GET
path="/static/css/index.css" host=redacted fwd="82.196.112.61"
dyno=web.1 connect=1ms service=7ms status=404 bytes=2332 protocol=https
2021-08-04T15:17:38.424598+00:00 heroku[router]: at=info method=GET
path="/static/js/bootstrap.bundle.js" host=redacted fwd="82.196.112.61"
dyno=web.1 connect=0ms service=27ms status=200 bytes=208248 protocol=https
This is my project structure. It works fully well locally, but as soon as I push it to Heroku the CSS fails to be served.
Project structure:
App.py:
from app import app
if __name__ == "__main__":
app.run(host='0.0.0.0',
port=33507,
use_reloader = True)
__init__.py:
from flask import Flask, send_from_directory
from whitenoise import WhiteNoise
app = Flask(__name__)
# Allows the app to identify the static folder
app.static_folder = 'static'
app.wsgi_app = WhiteNoise(
app.wsgi_app,
root='static/')
#app.route("/static/<path:path>")
def static_dir(path):
return send_from_directory("static", path)
#Configuration of application, see configuration.py, choose one and uncomment.
configuration = 'app.configuration.ProductionConfig'
#configuration = 'app.configuration.DevelopmentConfig'
app.config.from_object(configuration)
print('Running server on ' + app.config['ENV'] + '.')
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
print('Running database at', app.config['SQLALCHEMY_DATABASE_URI'])
from app import views, models
db.create_all()
SOLVED
The issue was rooted in heroku being case-sensitive while Github is not. Even though you change the case on a folder locally, it does not get commited and pushed to Github, and this then propagates to Heroku.
TL;DR: Check that your folders are persistent in it's letter case, locally, on Github, and in Heroku.
Github:
Code:

Flask web app crashes in Heroku, is fine in my computer server

It was find when it was a simple "Hello world" web, but I want to add this Dash-pivottable from plotly and it doen't work.
I get this error in the Heroku logs:
at=error code=H10 desc="App crashed" method=GET path="/" host=flasktabla.herokuapp.com request_id=** fwd="201.239.88.79" dyno=web.1 connect=5001ms service= status=503 bytes= protocol=https
app.py:
from flask import Flask
import dash
import dash_html_components as html
import dash_pivottable
server = Flask(__name__)
app = dash.Dash(__name__)
server = app.server
app.layout = html.Div(
dash_pivottable.PivotTable(
data=[
['Animal', 'Count', 'Location'],
['Zebra', 5, 'SF Zoo'],
['Tiger', 3, 'SF Zoo'],
['Zebra', 2, 'LA Zoo'],
['Tiger', 4, 'LA Zoo'],
],
cols=["Animal"],
rows=["Location"],
vals=["Count"]
)
)
if __name__ == "__main__":
app.run_server(debug=True)
#server.route("/")
def my_dash_app():
return app.index()
requirements.txt:
Click==7.1.2
Flask==1.1.2
gunicorn==20.1.0
itsdangerous==1.1.0
Jinja2==2.11.3
MarkupSafe==1.1.1
Werkzeug==1.0.1
dash-pivottable==0.0.2
Procfile:
web: gunicorn app:app
Thanks.
This is probably a error in your Procfile.
Change your Procfile to this:
web: gunicorn --bind 0.0.0.0:$PORT flaskapp:app

Django now working channels with ASGI + WSGI in Heroku

I am trying to setup a Django + Heroku app with Channels (V.2).
I tried to follow all the tutorial but most of them are not updated.
App must use WSGI for HTTP request and ASGI for websockets requests.
So far I found that it is almost working, the last missing piece is for the websockets endpoints to be visible for web app.
At this point whenever I try to create a new websocket:
Error during WebSocket handshake: Unexpected response code: 404
Here is the Settings:
ASGI_APPLICATION = 'app_xxx.routing.application'
ASGI_THREADS = 5
WSGI_APPLICATION = 'app_xxx.wsgi.application'
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
'hosts': [os.environ.get('REDIS_URL')],
},
},
}
Here is the Procfile:
web: gunicorn app_xxx.wsgi --log-file -
web2: daphne app_xxx.asgi:channel_layer --port $PORT --bind 0.0.0.0 -v2
worker: python manage.py runworker channel_layer -v2
Here is the asgi:
import os
from channels.layers import get_channel_layer
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app_xxx.settings")
channel_layer = get_channel_layer()
Here is the routing:
from channels.routing import ProtocolTypeRouter, URLRouter, ChannelNameRouter
from django.urls import path
from apps.booking.consumers import BookingConsumer
application = ProtocolTypeRouter({
"websocket": URLRouter([
path('ws/booking_review/<room_name>', BookingConsumer),
]),
})
You're supposed to run the ASGI application, not channel layer. Your ASGI_APPLICATION setting should point to routing.py or you can move its contents to asgi.py and point to it. With your current configuration, your Procfile should look like this:
web: gunicorn app_xxx.wsgi --log-file -
web2: daphne app_xxx.routing:application --port $PORT --bind 0.0.0.0 -v2
worker: python manage.py runworker channel_layer -v2
Check the docs deployment page for more details

code before app.run() can not be run in gunicorn+flask

#main.py
from flask import Flask
app = Flask(__name__)
if __name__ == '__main__':
print("before app run")
app.run() # , threaded=True host='0.0.0.0', debug=True, port=5000
Run gunicorn as follow:
gunicorn -b 0.0.0.0:8000 --preload main:app
the result will not print “before app unn”. How can i run the print code? if i don't want to place print outside of if __name__ == '__main__'
Gunicorn is not running the file, but importing it. That means that __name__ != "__main__" and your code never gets run.
Gunicorn then manually calls app.run() itself, after importing your file.
The solution is to make sure that your code is run at import time:
> cat main.py
from flask import Flask
app = Flask(__name__)
print "before main stanza"
if __name__ == "__main__":
print "in main stanza"
app.run()
And then running the app:
> gunicorn -b 0.0.0.0:8000 --preload main:app
before main stanza
[2017-06-07 08:33:15 +0100] [8865] [INFO] Starting gunicorn 19.7.1
[2017-06-07 08:33:15 +0100] [8865] [INFO] Listening at: http://0.0.0.0:8000 (8865)
...
Actually that will print before app run when you run this application with python main.py
It's not possible with Gunicorn though you can try before_first_request that will do the trick
#app.before_first_request
def execute_this():
print("before app run")