Procfile gunicorn custom module name - heroku

Context:
I am writing a medium sized flask application (10-15 views), and in the process, I am hoping to organize the code in a manner that will make it easily maintainable and extensible (not a monolithic file as most Flask applications are).
The structure of the application mimics the documentation as follows:
/AwesomeHackings
/ENV
/AwesomeHackings
/models
/static
/templates
/__init__.py
/awesome.py
/awesome.cfg
/Procfile
/README.MD
/requirements.txt
/run.py
Problem:
I am unable to get foreman to work with a flask application which is not named 'app'. I would love to have run.py be the entry point to my application.
I am using gunicorn + gevent, and my current Procfile contains:
web: gunicorn -w 2 -b 0.0.0.0:$PORT -k gevent app:run
I have been using run.py to test the application:
from AwesomeHackings import awesome
awesome.app.run(debug=True)
Thus I assumed I could simply substitute run for app in the Procfile, but when executing foreman start , gunicorn fails with meaningless verbiage about modules.

I found the solution in Django's documentation. The main parameter of gunicorn is module:
gunicorn [OPTIONS] APP_MODULE
Where APP_MODULE is of the pattern MODULE_NAME:VARIABLE_NAME
While it seemed logical for the syntax to be a keyword argument app:someIdentifier, as all of the tutorials use a module named app, it is in fact not the case. The correct argument for my situation was run:app.

Related

Mean.js - Dependancies Missing

I am using the MeanJS (https://github.com/meanjs/mean) framework, running on Heroku. When I try to run the application I get errors like:
Error: Cannot find module 'eslint-config-airbnb/legacy'
I am running in production mode (NODE_ENV=production).
The question I have is, it seems like gulpfile.js (when running the task prod) calls the task lint which calls the task eslint. But when I look at the packages.json file, I see that eslint-config-airbnb is only included in the devDependancies (and not dependancies). Now I tired to add it to dependancies, but I still get the same error about the missing module.
I'm new to MEAN.js, so I appreciate any help.

Using Heroku Scheduler add-on with Golang app

I can't figure out how to use the Heroku Scheduler add-on with Go.
I would like run a separate Go file periodically, but I can find the command to achieve that.
From Heroku's doc (https://devcenter.heroku.com/articles/scheduler), if the app is not a Rails app, I should use a ruby script. But I don't know how to run a Go file from there.
I ended up forking the same main function used by my web dyno:
func main () {
if len(os.Args) >= 2 && os.Args[1] == "my_job_param" {
// Execute job.
} else {
// Set up my web server with port, router, etc.
}
}
Then, in the Scheduler add-on, I just call: my-app-name "my_job_param". It's pretty hacky, but I wanted to find a solution using the Scheduler add-on.
The typical pattern is to do something like:
.
└── cmd
├── processX
│ └── main.go
└── web
└── main.go
And you set heroku.install to ["./cmd/..."] and Heroku compiles and installs both commands into bin, so you get a bin/web and a bin/processX (processX is just a placeholder, whatever the name of the directory that contains a main package is the name of the resulting executable). In the above case your Procfile would say web: web, the first web being the process type, the second being the name of the executable. And the job you would tell scheduler to run would be processX.
That cleanly separates responsibilities
The Heroku scheduler will run any terminal command basically. So, if you compile your script into an executable called myscript, for example, you could simply put:
myscript
In the scheduler and it will execute that command, thereby running your script =) No ruby is required.

How do you translate a rackup invocation to a self-contained script?

I'm trying to make a gem out of an app that did:
spawn("rackup", "--port", PORT.to_s, "--server", "thin", "-E", "development", File.expand_path("../server.ru", __FILE__))
If I use this in the gem I get a LoadError for thin (after packaging it and installing it) (thin is in my gemspec but I guess the error has to do with the spawning of the rackup executable, which is not part of the gem's bundle).
Replacing:
run app
with
Rack::Handler::Thin.run app
in the server.ru file will start the server, but I need to set the parameters too.
I tentatively tried:
ENV['RACK_ENV']='development'
Rack::Handler::Thin.run app, host: 'localhost', port: PORT.to_s
to no avail. What is the recipe for translating parameterized rackup invocations to executable *.ru files with explicit handlers?
Rack::Handler::Thin had a valid_options method.
None of those keys worked, nor did various combinations.
The SERVER_PORT and SERVER_HOST env variables didn't work either.
I endend up running the thin executable with the *.ru file as an argument and that did it.
It may well be that the things I've tried would've worked with some handler other than Thin (i.e., thin might be a crappy rack citizen). I don't know or care. Just needed to get this working. I will, of course, appreciate (upvote/accept) answers that shed more light on this

gevent-socketio + Flask + Gunicorn

Can I use gevent-socketio with Flask, running under Gunicorn, and still enjoy the nice exception printing, debugger, and reload capability that Flask offers? How would my gunicorn worker and WSGI app class look like?
I've got the exact same problem so I solved it by using watchdog.
pip install watchdog
together with this command:
watchmedo shell-command --patterns="*.py*;;*.less;*.css;*.js;*.txt;*.html" --recursive --command='kill -HUP `cat /tmp/gunicorn.pid` && echo "Reloading code" >> /tmp/gunicorn.log' ~/projectfolder
It requires (well, not really, but I point "Reloading code" into the same logfile so It's a nice thing to have) that you daemonize the gunicorn process, which I do like this:
gunicorn_config.py
workers = 2
worker_class = 'socketio.sgunicorn.GeventSocketIOWorker'
bind = '0.0.0.0:5000'
pidfile = '/tmp/gunicorn.pid'
debug = True
loglevel = 'debug'
errorlog = '/tmp/gunicorn.log'
daemon = True
Start the application:
gunicorn run:app -c gunicorn-config.py
View the log:
tail -f /tmp/gunicorn.log
From this point everything should be reloaded with each change in your project.
It's a bit complicated but since gunicorn with a worker (or the built in socketio-server) doesn't have any reloading capabilities I had to do it like this.
It's a different approach compared to the decorator solution in the other answer but I like to keep the actual code clean from development specific solutions. Both accomplish the same thing so I guess you'll just have to pick the solution you like. :)
Oh, as an added bonus you get to use the production server in development which means both environments match each other.
I've been looking into this subject lately. I don't think you can easily use autoreload feature with Flask + gevent-socket.io + Gunicorn. Gunicorn is a production server that does not allow such features natively.
However, I found a nice solution for my development server : user SocketIOServer provided with the library and a Flask snippet for autoreload. Here is the startup script (runserver.py) :
from myapp import app
from gevent import monkey
from socketio.server import SocketIOServer
import werkzeug.serving
# necessary for autoreload (at least)
monkey.patch_all()
PORT = 5000
#werkzeug.serving.run_with_reloader
def runServer():
print 'Listening on %s...' % PORT
ws = SocketIOServer(('0.0.0.0', PORT), app, resource="socket.io", policy_server=False)
ws.serve_forever()
runServer()
This solution is inspired from : http://flask.pocoo.org/snippets/34/
I've made some tweaks to Werkzeug debugger so it now works with socket.io namespaces, see below and enjoy :)
https://github.com/aldanor/SocketIO-Flask-Debug

Passing options to rackup via a Sinatra application

I'm new to ruby, learning Sinatra. While creating a Sinatra site by requiring 'sinatra' and setting up the routes directly under is pretty easy and rather well documented, creating an application by requiring 'sinatra/base' and writing a class that inherits from 'Sinatra::Base', while still relatively easy, is very poorly documented (maybe because it's a pretty recent feature of Sinatra).
And that's exactly what I am doing. I am not having too much trouble on the Sinatra part, however I am having a bit of trouble on the rackup/thin/server part. Apparently there are two ways to deploy the application: using Sinatra itself (using the run! method) and using a rackup file (typically config.ru).
Using Sinatra's run! method is extremely intuitive and works like a charm, but apparently it doesn't work if I want to deploy my app on heroku. As a matter of fact, almost all the Sinatra apps that I have encountered on GitHub use a config.ru file.
Using a rackup file might be equally intuitive, but I can't manage to understand how to pass options from the Sinatra app to the server (ir: the port). I tried to merge options to rackup's default options array:
MyApp::App.default_options.merge!(
:run => false,
:env => :production,
:port => 4567
)
run MyApp::App
by adding options directly to the app:
MyApp::App.set :port, 4567
MyApp::App.set :run, false
MyApp::App.set :env, :production
run MyApp::App
by setting options from within the application class:
module MyApp
class App < Sinatra::Base
set :port, 4567
set :run, false
set :env, :production
# ...
# config.ru
require 'app'
run MyApp::App
All the methods above failed, either by showing error messages or by just not taking any of the options into consideration. So is there any way to pass options to rackup/thin/the sever via a Sinatra app when using a rackup file? Or the options in questions should be passed directly to rackup/thin/the sever via command-line options?
As a reference to the problem, here is the little Sinatra application I am building: https://github.com/AzizLight/Wiki/
You're actully going to pass options to thin on the command line directly or via a configuration file. See all options:
$ thin -h
For production, use a configuration file:
$ thin -C thin-production.yml -R config.ru start
Here is an example thin-production.yml file:
---
address: localhost
port: 3020
servers: 4
max_conns: 1024
max_persistent_conns: 512
timeout: 30
environment: production
pid: tmp/pids/thin-production.pid
log: log/thin-production.log
daemonize: true
I know I'm resurrecting an ancient question here, but I came across another useful solution not yet mentioned. As stated in this rack wiki tutorial:
the first line starting with #\ is treated as if it was options, allowing rackup arguments to be specified in the config file.
So if you wanted to set your host to 0.0.0.0 and port to 5656, you would add the following line to the beginning of your config.ru file:
#\ -o 0.0.0.0 -p 5656

Resources