Restart my heroku application automatically - ruby-on-rails

This terminal command restarts my heroku application:
heroku restart
Is there a way to run a script that will run this command and restart my application every hour?

I actually just had to solve this problem for my apps and wrote a post on it with more details. Basically, you need the heroku-api gem now since the heroku gem is replaced by the CLI. Then you need a rake task, a couple of config variables and the heroku scheduler plugin (free except for minimal dyno time).
The rake task looks like this:
namespace :heroku do
desc 'restarts all the heroku dynos so we can control when they restart'
task :restart do
Heroku::API.
new(username: ENV['HEROKU_USERNAME'], password: ENV['HEROKU_PASSWORD']).
post_ps_restart(ENV['HEROKU_APP_NAME'])
end
end
You can also set it up to use your API token instead of putting your username and password into the config. This only matters if you don't want your co-contributors/coworkers knowing your password or the password to your main account on Heroku.
heroku config:set HEROKU_USERNAME=[username] HEROKU_PASSWORD=[password] HEROKU_APP_NAME=[app_name] -a [app_name]
Now, go ahead and deploy and test:
git push [heroku_remote_name] [feature_branch]:master
heroku run rake heroku:restart -a [app_name]
Lastly, we’ll need to set up the task to run this on schedule. I’ve chosen to go with the free Heroku cron add-on:
heroku addons:add scheduler:standard -a [app_name]
heroku addons:open scheduler -a [app_name]
This will open up the scheduler UI in your browser and you can create a scheduled worker to run the rake task whenever you’d like. We only need it once per day and we’re choosing to run it before our first scheduled job of the day.
My original post with frigged up CSS (see update2 below):
https://web.archive.org/web/20150612091315/http://engineering.korrelate.com/2013/08/21/restart-heroku-dynos-on-your-terms/
UPDATE
I changed the name of the task from "implode" to "restart" to be way more clear as to what is happening. Implode is a fun name but pretty much useless otherwise.
UPDATE2
Apparently my company removed the blog post. I'm adding more of the code here and I've updated the link, but the CSS looks like a dog threw it up. My apologies.

You could create a heroku cron job that uses the Heroku api on your application to restart itself...
One question though - why?

We solved this by using a buildpack to get the heroku command available to the dyno itself, then using Heroku Scheduler.
We added the https://github.com/gregburek/heroku-buildpack-toolbelt buildpack per its instructions:
heroku buildpacks:add https://github.com/gregburek/heroku-buildpack-toolbelt.git
heroku config:add HEROKU_TOOLBELT_API_EMAIL=`heroku whoami`
heroku config:add HEROKU_TOOLBELT_API_PASSWORD=`heroku auth:token`
Then made sure the app slug was rebuilt per the instructions:
git push heroku master
In Heroku Scheduler, we added this as a hourly job:
vendor/heroku-toolbelt/bin/heroku ps:restart -a $HEROKU_APP_NAME
You can determine if it's working by looking for Scheduler output in the Heroku logs, and of course by the memory graph of the app in the Heroku dashboard (if you're restarting to work around a memory leak).

A script isn't necessary, just "crash" your application and Heroku will restart it.
Just don't do this more frequently than once every ten minutes or Heroku will subject you to a 10 minute timeout.
In node.js you do this with process.exit(0).
From Chris at Heroku Support:
A crashed dyno will be restarted immediately. If the dyno moves from a
crashed state into an "up" state (meaning that the dyno bound to
$PORT) then it's subject to being a normal running dyno. If it crashes
again during the boot or "starting" sequence then it won't be
restarted again until after the TIMEOUT period. The TIMEOUT period is
currently 10 minutes but that is subject to change. This prevents
dynos that are continually crashing from putting extraneous load on
the platform.
However, as good as that sounds, it doesn't work in practice. You will hit the timeout every time you exit because the dyno manager expects your app to be up:
For your worker process management you're exiting the process cleanly
but the platform is expecting the dyno to be up. It sounds like you're
essentially crashing the dyno as a result.
So again, if you need to restart periodically -- and that period can be set to > 10 minutes -- this is a easy and simple way to manage memory clearing. If you need to reboot dynamically (for example, when idle is detected) or frequently you will need to explore other options.
You can access the name of the dyno (ex. "worker.3", "web.1") through the environment variable "PS" and issue a heroku API restart command programmatically.

Inspired by https://www.stormconsultancy.co.uk/blog/development/ruby-on-rails/automatically-restart-struggling-heroku-dynos-using-logentries/
# Setup
heroku plugins:install https://github.com/heroku/heroku-oauth
heroku authorizations:create -s write
heroku config:add RESTART_API_KEY=<API KEY>
heroku config:add APP_NAME=<App Name>
heroku addons:add scheduler:standard -a <App Name>
heroku addons:open scheduler -a <App Name>
add `rake restart`
# Gemfile
gem 'platform-api', require: false
# Rakefile
task :restart do
require 'platform-api'
app_name = ENV.fetch('APP_NAME')
key = ENV.fetch('RESTART_API_KEY')
connection = PlatformAPI.connect_oauth(key)
connection.dyno.list(app_name).map do |info|
if info['type'] == 'web' && info['state'] == 'up'
puts "Restarting #{info.inspect}"
connection.dyno.restart(app_name, info['name'])
else
puts "Skipping #{info.inspect}"
end
end
end

I solved this with a very simple curl command script within the repo that is triggered using the free Heroku scheduler.
#!/bin/sh
curl -X DELETE "https://api.heroku.com/apps/${HEROKU_APP_NAME}/dynos" \
--user "${HEROKU_CLI_USER}:${HEROKU_CLI_TOKEN}" \
-H "Content-Type: application/json" \
-H "Accept: application/vnd.heroku+json; version=3"
See https://gist.github.com/mattheworiordan/f052b7693aacd025f025537418fa5708.

We've given our app a long-running token to use to authenticate with the Heroku API, and simply included a curl request in our code to restart the app.
Create a long-running API token:
$ heroku authorizations:create --description="Long-lived token for app restarts"
Creating OAuth Authorization... done
Client: <none>
ID: abcdabcd-abcd-4bcd-abcd-abcdabcdabcd
Description: Long-lived token for app restarts
Scope: global
Token: 12341234-1234-4234-1234-123412341234
Updated at: Tue May 11 2021 09:16:38 GMT-0400 (Eastern Daylight Time) (less than a minute ago)
Note the Token. We've stored it in the ENV via heroku config, along with the app name:
$ heroku config:set HEROKU_API_TOKEN=12341234-1234-4234-1234-123412341234 HEROKU_APP_NAME=not-really-an-app
In our code we have the following method to restart the app via Heroku's API, using this API call:
def restart!
# Using puts to log output, replace with your logging system if needed
puts `curl -v -s -n -X DELETE https://api.heroku.com/apps/#{ENV["HEROKU_APP_NAME"]}/dynos -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Authorization: Bearer #{ENV["HEROKU_API_TOKEN"]}"`
end
Finally, as you're interested in automatic restarts every hour, the restart! method above can be scheduled using Heroku's Scheduler, rufus-scheduler, as a Sidekiq job, or otherwise.
Note: Heroku has some limits/timing logic around app restarts, mostly centered around dyno crashes. Reading the docs may help inform your app restart strategy.

As far as I can tell, simply running heroku ps:restart --app APPNAME in the Heroku Scheduler add-on works fine. It's unclear to me why the additional steps in other answers are necessary.

Related

Heroku: Cannot run more than 1 Free size dynos

I was trying to run
heroku run rake db:migrate
And was getting the error
Cannot run more than 1 Free size dynos.
See below for how to fix...
Most Efective
in console run:
heroku ps
the result is some like this:
run.4859 (Free): up 2016/01/12 21:28:41 (~ 7m ago): rails c
So the numbers 4859 represent the session that is open and needs to be closed. To fix the error you need to run(Obviusly, replace the number 4859 by the number obtained):
heroku ps:stop run.4859
It is a very simple solution.
The answer is to look for any open heroku sessions (you can use 'heroku ps' as john points out above), in my case I already had a started a heroku console session 30mins earlier and just forgot about it. So if you see the "Cannot run more than 1 Free size dynos" error just close any existing console or other heroku sessions you have open.
Hopefully this saves someone the ten minutes it took me to come to my senses.
Had the exact same issue and came to this page. After reading realized what was going on but want to add following.
just run
heroku kill DYNO --app your_app_name
After this close all open consoles.
Then run db migrate command, it will work.
In my case, I ran heroku ps:restart to restart all dynos and the heroku run * command worked again.
Examples
If you just have one Git remote for Heroku, use this:
heroku ps:restart && heroku run *
If you have multiple Git remotes for Heroku, use this:
heroku ps:restart --remote your-remote-name && heroku run * --remote your-remote-name
OR
heroku ps:restart --app your-heroku-app-name && heroku run * --app your-heroku-app-name
Replace * with your command e.g. console for Rails console.
What I meant by your-heroku-app-name here is the sub-domain for your Heroku app. For example, if your app URL is https://cute-cat.herokuapp.com, that means your-heroku-app-name is cute-cat.
If you are not sure/forgot what's your Git remote name for Heroku, git remote -v can help you with that.
Example:
$ git remote -v
this-is-the-remote-name https://git.heroku.com/xxx.git (fetch)
this-is-the-remote-name https://git.heroku.com/xxx.git (push)
this-is-another-remote-name https://git.heroku.com/yyy.git (fetch)
this-is-another-remote-name https://git.heroku.com/yyy.git (push)
Just restart all dynos.
heroku restart
For me there was one command running on the web run console, I just ended its session there and it was resolved.
Heads up: Heroku free tier is going away soon
"What happens if I take no action on my free apps or databases or do not upgrade to a paid plan?
free dynos will be scaled down to 0 and hobby-dev databases will be deleted starting November 28, 2022."
"Starting November 28, 2022, free Heroku Dynos, free Heroku Postgres, and free Heroku Data for Redis® plans will no longer be available. If you have apps using any of these resources, you must upgrade to paid plans by this date to ensure your apps continue to run and retain your data. See our blog and FAQ for more info."
REF:
https://blog.heroku.com/next-chapter
https://devcenter.heroku.com/articles/free-dyno-hours
https://help.heroku.com/RSBRUH58/removal-of-heroku-free-product-plans-faq

Heroku db:pull 'db:pull is not a heroku command'

I'm getting this message even though I've used heroku db:pull a million times. For some reason it's no longer working even though I haven't even touched my code. Any ideas?
The full error message is
db:pull is not a heroku command.
Perhaps you meant pg:pull
See heroku help for a list of available commands.
For now, we can still use heroku-legacy-taps until the taps gods decide to deprovision the taps servers.
Run: heroku plugins:install https://github.com/heroku/heroku-legacy-taps.git
Then continue your db:push and db:pull workflow as usual.
(thanks to GantMan for the hint)
Since the taps servers will be decommissioned at some future point, the plugin is probably not the best long term solution. But of course you can run your own taps server.
Steps
Step 1: Start Your taps server
taps server `heroku config:get DATABASE_URL` db db
Step 2: Run the taps client
In a different shell:
taps pull sqlite://db/development.sqlite3 http://db:db#localhost:5000
Step 3: Shut down the taps server
Once the import is done you can shutdown the server with the normal Ctrl-C key combination.
Notes
This will pull my production database down into a local SQLite database. Of course if you are using MySQL or something locally just replace the sqlite URI with the equivalent MySQL URI.
Taps requires you to set a username/password. Since I am just running it locally for a short time I just use "db" for both. If you change these you will need to also update the username/password in the URL for step 2.
You can also use taps push to copy data to the production server although you should obviously do that with caution.
Taps has a number of bugs it has acquired over time due to the lack of activity by the maintainer:
The biggest annoyance is the fact that it stopped working after rack incorporated OKJson into Rack. The OKJson in Rack conflicts with the modified version that is included in taps. I created a patch to resolve this but no activity has been done to merge it. In the meantime workarounds include forcing taps to use an earlier rack. Paxa suggested an easy approach by modifying the bin/taps file. If you don't want to modify packaged installed files on your system you can also follow hax8or's instructions which use bundler to force the right version of Rack.
The progress bar does not render correctly. fd fixed this in his pull request but it has also not been merged in. Since this is purely cosmetic you can just ignore the bad output.
#wijet recently forked taps and incorporated some of the most important patches. He has named his gem "taps-taps" if you are looking for an easy out-of-the-box install.
This is still possible. Just run
heroku plugins:install https://github.com/heroku/heroku-taps.git
You'll be able to do your classic stuff, it's just a plugin now.
If you're having trouble still, you may need to make sure some other gems are installed. You can also run the following to be sure:
gem install heroku taps sequel
I hope this helps! I love db:push/pull just like the rest of the world, and I'm sad to see it go.
If you're still having problems take a look at this one: https://github.com/heroku/heroku-legacy-taps
GOODLUCK!
I used to use db:pull and it worked fine. After it was removed, I tried pg:pull but it is just not working for me.
I found a different solution.
If your local database is PostgreSQL, and you have the pgbackups addon enabled, this is the sequence of commands I'm using to copy the remote DB to my local machine:
$ wget "`heroku pgbackups:url --app app-name`" -O backup.dump
$ # Create the local database first, if it's not created yet. Then:
$ pg_restore -d database-name -c backup.dump -U database-user-name -O --no-acl -h localhost
Replace app-name, database-name and database-user-name with your own info.
You'll likely want to ask heroku to make a backup just before you pull your data:
heroku pgbackups:capture --expire
otherwise you get the data from whenever it did its own backup.
This is the error message I got when I tried db:pull.
db:pull is not a heroku command.
Perhaps you meant pg:pull.
See heroku help for a list of available commands.
Have you tried pg:pull?
Usage: heroku pg:pull <REMOTE_SOURCE_DATABASE> <LOCAL_TARGET_DATABASE>
Looks like db:pull etc is being deprecated & moved
See here https://github.com/heroku/heroku-pg-extras/issues/42
I found that the ability of db:push & pull to move single eg static tables of data up & down from dev to staging to production was invaluable - now looks like you need to create a new empty database and do an entire dump into it and then run pg commands to move an individual table
I found my answer here, but I put it in a rake task. I think this is a sensible way to deal with this situation. If you're running a local instance of postgres to work with your postgres on Heroku, you might try something like this:
# lib/tasks/database.rake
namespace :database do
desc "Gets the database from heroku and restores it to development"
task :pull => :environment do
dumpfile = 'tmp/latest.dump'
db_config = Rails.application.config.database_configuration[Rails.env]
File.delete(dumpfile) if File.exist?(dumpfile)
`heroku pgbackups:capture --app app-name-here`
system("curl -o #{dumpfile} `heroku pgbackups:url --app app-name-here`")
`pg_restore --verbose --clean --no-acl --no-owner -h localhost -d #{db_config['database']} #{dumpfile}`
end
end
Now, anytime I wish to pull my production data into dev I just run rake database:pull
This is a very rudimentary solution, but I only need it to do this one thing in my case.

How to keep a ruby script running persistently within a Rails app on Heroku?

I have a Mailman server script that checks for incoming email and loads it into the rails app database. The script (should) run continuously and checks for new email every 60 seconds. I was able to run the script on Heroku using heroku run:detached script/mailman_server, but when I checked back a few days later it wasn't running. How can I ensure it is always running?
You should use the Cedar stack, and add a Procfile. Eg. Something like...
web: bundle exec unicorn -p $PORT -c ./unicorn.rb
mailman: bundle exec script/mailman_server
Then:
heroku ps:scale mailman=1
On the command line will add one worker. However. Should the worker encounter some kind of error and close you would need additional config to restart it.
Sendgrid have a service which can accept incoming emails for your app:
http://docs.sendgrid.com/documentation/api/parse-api-2/
I haven't looked at the pricing.

Rails: start script on server and then "leave"

I want to run a rake script on my application on Heroku that will take several hours. If I start it from my console on my laptop, and shut down my laptop the script will stop (and I will have to shut down my laptop before the script is finished).
How do I do to start this rake script without it being "tied" to my laptop. I.e. so that it continues to run until it breaks or is finished?
heroku run rake update_feeds_complete --app myapp
is the script to run...
Giving me advice on what commands etc to Google would be helpful as well.
You can run commands with run:detached and close the terminal window and they will continue to run. So you simply need to run
heroku run:detached rake update_feeds_complete --app myapp
You might want to take a look at the scheduler, too. https://devcenter.heroku.com/articles/scheduler
Pretty handy for running rake tasks, even if one-offs.
In general, I use resque and redis for jobs I want to run on heroku. If it's a one-time job I may not, but if it's something I'm going to do regularly then having them installed is a great convenience.
redis installs through the 'Redis To Go' add-on with Heroku.
resque is a gem that's used for running background jobs of different kinds. There are lots of plugins for resque for sending email, for job scheduling, etc.
I'm not familiar with Heroku in particular, but in the past when i have run into this case I used remote execute via SSH:
ssh username#your.server -f 'your command here'
This will open an ssh session, execute your command and then close the connection. But your script will keep running remotely.

transfer db from one heroku app to another faster

Is there a faster way to transfer my production database to a test app?
Currently I'm doing a heroku db:pull to my local machine then heroku db:push --app testapp but this is becoming time consuming. I have some seed data but it is not nearly as accurate as simply testing with my real-world data. And since they're both stored on a neighboring AWS cloud, there must be a faster way to move the data?
I thought about using a heroku bundle, but I noticed the animate command is gone?
bundles:animate <bundle> # animate a bundle into a new app
It's quite common to migrate databases between staging, testing and production environments for Rails Apps. And heroku db:pull/push is painfully slow. The best way I have found so far is using Heroku PG Backups add-on and it's free. I followed following steps to migrate
production database to staging server:
1) Create the backup for the production-app db
heroku pg:backups capture --app production-app
This will generate b001 backup file from the main database (usually production db in database.yml)
2) To view all the backups (OPTIONAL)
heroku pg:backups --app production-app
3) Now use the pg:backups restore command to populate staging server database from the last backup file on production server
heroku pg:backups restore $(heroku pg:backups public-url --app production-app) DATABASE_URL --app staging-app
Remember that restore is a destructive operation, it will delete existing data before replacing it with the contents of the backup file.
So things are even easier now .. checkout the transfer command as part of pgbackups
heroku pgbackups:transfer HEROKU_POSTGRESQL_PINK sushi-staging::HEROKU_POSTGRESQL_OLIVE -a sushi
https://devcenter.heroku.com/articles/upgrading-heroku-postgres-databases#4b-alternative-transfer-data-between-applications
This has worked beautifully for me taking production code back to my staging site.
The correct answer has changed again as of March 11, 2015.
heroku pg:backups restore $(heroku pg:backups public-url --app myapp-production) DATABASE_URL --app myapp-staging
Note specifically that the argument is now public-url.
https://blog.heroku.com/archives/2015/3/11/pgbackups-levels-up
Update for mid-2015...
The pgbackups add-on has been deprecated. No more pgbackups:transfer. pg:copy is ideal for this scenario.
To copy a database from yourapp (example db name: HEROKU_POSTGRESQL_PINK_URL to yourapp_staging (example db name: HEROKU_POSTGRESQL_WHITE_URL)
# turn off the web dynos in staging
heroku maintenance:on -a yourapp-staging
# if you have non-web-dynos, do them too
heroku ps:scale worker=0 -a yourapp-staging
# backup the staging database if you are paranoid like me (optional)
heroku pg:backups capture -a yourapp-staging
# execute the copy to splat over the top of the staging database
heroku pg:copy yourapp::HEROKU_POSTGRESQL_PINK_URL HEROKU_POSTGRESQL_WHITE_URL -a yourapp-staging
Then when it's complete, turn staging back on:
# this is if you have workers, change '1' to whatever
heroku ps:scale worker=1 -a yourapp-staging
heroku maintenance:off -a yourapp-staging
Reminder: you can use heroku pg:info -a yourapp-staging (and yourapp) to get the database constants.
(source: https://devcenter.heroku.com/articles/upgrading-heroku-postgres-databases#upgrade-with-pg-copy-default)
psql -h test_host -c 'drop database test_db_name; create database test_db_name;'
pg_dump -h production_host production_db_name | psql -h test_host test_db_name`
This can be done on production_host or on test_host — will work both ways.
Have not tested this, but it might work.
Do this to get the URL of your source database:
heroku console "ENV['DATABASE_URL']" --app mysourceapp
Then try executing db:push with that.
heroku db:push database_url_from_before --app mytargetapp
This might not work if Heroku doesn't allow access to the DB machines from outside their network, which is probably the case. You could, perhaps, try using taps (gem that heroku db commands use internally) from within your app code somewhere (maybe a rake task). This would be even faster than the above approach because everything stays completely within AWS.
Edit:
Here's an (admittedly hacky) way to do what I described above:
Grab the database URL as in the first code snippet above. Then from a rake task (you could do it on console but you risk running into the 30 second timeout limit on console commands), execute a shell command to taps (couldn't easily determine whether it's possible to use taps directly from Ruby; all docs show use of the CLI):
`taps pull database_url_from_source_app #{ENV['DATABASE_URL']}`
The backticks are important; this is how Ruby denotes a shell command, which taps is. Hopefully the taps command is accessible from the app. This avoids the problem of accessing the database machine from outside Heroku, since you're running this command from within your app.
Heroku enables you to fork existing applications in production. Use heroku fork to copy an existing application, including add-ons, config vars, and Heroku Postgres data.
Follow the instructions on Heroku: https://devcenter.heroku.com/articles/fork-app
Update for mid-2016...
Heroku now have a --fast flag when creating forks, however they will be up to 30 hours out-of-date.
$ heroku addons:create heroku-postgresql:standard-4 --fork HEROKU_POSTGRESQL_CHARCOAL --fast --app sushi
https://devcenter.heroku.com/articles/heroku-postgres-fork#fork-fast-option

Resources