Heroku Cedar: How to scale WEB dynos based on time of day - ruby-on-rails-3

I want my Rails 3.1 app to scale up to 1 web dyno at 8am, then down to 0 web dynos at 5pm.
BUT, I do not want to sign up for a paid service, and I cannot count on my home computer being connected to the internet.
It seems like the Heroku Scheduler should make this trivial. Any quick solutions or links?

The answer is 'yes' you can do this from scheduler and it's trivial once you know the answer:
Add a heroku config var with your app name: heroku config:add APP_NAME:blah
Add gem 'heroku' to your Gemfile
In order to verify, manually scale up/down your app: heroku ps:scale web=2
Add a rake task to lib/tasks/scheduler.rake:
desc "Scale up dynos"
task :spin_up => :environment do
heroku = Heroku::Client.new('USERNAME', 'PASSWORD')
heroku.ps_scale(ENV['APP_NAME'], :type=>'web', :qty=>2)
end
# Add a similar task to Spin down
Add the Scheduler addon: heroku addons:add scheduler:standard
Use the Scheduler web interface to add "rake spin_up" at whatever time you like
Add a rake spin_down task and schedule it for whenever.
Notes:
Step 1 is needed because I couldn't find any other way to be certain of the App name (and I use 'staging' and 'production' environments for my apps.
Step 3 is required because otherwise the ruby command errors out as it requires that you first agree (via Yes/No response) that you will be charged money as a result of this action.
In step 4, I couldn't find any docs about how to do this with an API key via the heroku gem, so it looks like user/pass is required.
Hope this helps someone else!

Just implemented this approach (good answer above #dnszero), thought I would update the answer with Heroku's new API.
Add your app name as a heroku config variable
require 'heroku-api'
desc "Scale UP dynos"
task :spin_up => :environment do
heroku = Heroku::API.new(:api_key => 'YOUR_ACCOUNT_API_KEY')
heroku.post_ps_scale(ENV['APP_NAME'], 'web', 2)
end
This is with heroku (2.31.2), heroku-api (0.3.5)

You can scale your web process to zero by
heroku ps:scale web=0
or back to 1 via
heroku ps:scale web=1
you'd then have to have a task set to run at 8 that scales it up and one that runs at 17 that scales it down. Heroku may require you to verify your account (ie enter credit card details) to use the Heroku Scheduler plus then you'd have to have the Heroku gem inside your app and your Heroku credentials too so it can turn your app on or off.
But like Neil says - you get 750hrs a month free which can't roll over into the next month so why not just leave it running all the time?

See also this complete gist, which also deals with the right command to use from the Heroku scheduler: https://gist.github.com/maggix/8676595

So I decided to implement this in 2017 and saw that the Heroku gem used by the accepted answer has been deprecated in favor of the 'platform-api' gem. I just thought I'd post what worked for me, since i haven't seen any other posts with a more up-to-date answer.
Here is my rake file that scales my web dynos to a count of 2. I used 'httparty' gem to make a PATCH request with appropriate headers to the Platform API, as per their docs, in the "Formation" section.
require 'platform-api'
require 'httparty'
desc "Scale UP dynos"
task :scale_up => :environment do
headers = {
"Authorization" => "Bearer #{ENV['HEROKU_API_KEY']}",
"Content-Type" => "application/json",
"Accept" => "application/vnd.heroku+json; version=3"
}
params = {
:quantity => 2,
:size => "standard-1X"
}
response = HTTParty.patch("https://api.heroku.com/apps/#{ENV['APP_NAME']}/formation/web", body: params.to_json, headers: headers)
puts response
end

As an update to #Ren's answer, Heroku's Platform API gem makes this really easy.
heroku = PlatformAPI.connect_oauth(<HEROKU PLATFORM API KEY>)
heroku.formation.batch_update(<HEROKU APP NAME>, {"updates" =>
[{"process" => <PROCESS NAME>,
"quantity" => <QUANTITY AS INTEGER>,
"size" => <DYNO SIZE>}]
})

If you're running on the cedar stack, you won't be able to scale to zero web dynos without changing the procfile and deploying.
Also, why bother if you get one free dyno a month (750 dyno hours, a little over a month in fact)?

Related

laravel-shopify osiset Uninstallation webhook not getting work

https://github.com/osiset/laravel-shopify/wiki/Installation
I follow the step to add Uninstallation Job, But not getting any webhook call after uninstalling the app.
So when I try to install getting an error.
There’s no page at this address.
Can anyone help me with an example to check or debug that uninstallation Process?
It is an exercise in two parts. One, your App needs to listen to an endpoint. Create an endpoint that accepts webhooks and has the capability of ensuring security with the Shopify HMAC. Test your endpoint is working with Postman or some other simple too. By working we mean NOT 404. Now setup your webhook with the App API key you have, in your test store. Usually this is done by installing your App. Now uninstall. Watch your endpoint logs. Nothing much else to it.
If you are getting 404 errors, your App is not working properly. Work on that aspect of your web development before trying more complex things.
Did you type in ‘php artisan vendor:publish --tag=shopify-jobs‘
And also check if there is an Job at ‘App/Jobs/AppUninstalledJob‘
Also make sure that your shopify-config looks like this:
'webhooks' => [
[
'topic' => env('SHOPIFY_WEBHOOK_1_TOPIC', 'app/uninstalled'),
'address' => env('SHOPIFY_WEBHOOK_1_ADDRESS', env('APP_URL').'webhook/app-uninstalled')
]
]
Now you should also be aware of the fact that the webhook will not work on your local installation. If you went through all of the steps correctly and deploy your app to a public Server it will work.

ActionMailer sending real emails in test mode! - How to turn off?

Newly signed up users to my little app must be approved by the admin (me) before they can gain access to the site. I've succeeded in generating such emails in development with an after_create :send_admin_email in my user model which works great. My problem is that I'm generating multiple users during my tests (using FactoryGirl) and each test user created sends off a real email. Running my tests is like pouring molasses in January and I've got to delete hundreds of emails sent to my inbox. How do I turn that off?
Action Mailer Basics in the Rails Guides tells me that "By default Action Mailer does not send emails in the test environment. They are just added to the ActionMailer::Base.deliveries array."
Moreover, in config/environments/test.rb I've got:
config.action_mailer.delivery_method = :test
That's in addition to in config/environment.rb having:
# Configuration for using SendGrid on Heroku
ActionMailer::Base.smtp_settings = {
:address => 'smtp.sendgrid.net',
:port => '587',
:authentication => :plain,
:user_name => 'app[my app number]#heroku.com',
:password => '[something super secret]',
:domain => '[let's get this party started!.com]',
:enable_starttls_auto => true
}
ActionMailer::Base.delivery_method = :smtp
I'm sure that I'm missing something simple and basic. I've searched around and related questions and posts deal with how to test that ActionMailer actually sent email.
Humble gratitude in advance for any thoughts or help.
Addendum: Following answer to similar question found at Is it possible to turn off ActionMailer emails when cucumber testing is happening on development? I was able to stop the email sending madness. Still, I had to add ActionMailer::Base.delivery_method = :test to several rspec files. Is there a way I can shut this down globally? Anyone have any thoughts on what's going on?
So I've figured it out. Having the line ActionMailer::Base.delivery_method = :smtp in config/environment.rb overrides ActionMailer::Base.delivery_method = :test in config/environments/test.rb.
So, delete that line, ActionMailer::Base.delivery_method = :smtp'
from config/environment.rb and place it in config/environments/production.rb.
That allows you to place ActionMailer::Base.delivery_method = :test in config/environments/test.rb and the version you want in config/environments/development.rb. I made development.rb :test as I populated my database using Faker and changed it to smtp so I was sure that real emails were sent as an additional check.
Note: You must restart your server for these changes to take effect.
Another note: Heroku's current SendGrid Instructions put the SendGrid Heroku configuration code in a new config/initializers/mail.rb file which will likely require removing its last line and placing the desired version in each config/environments/[production.rb, development.rb, test.rb]
Perhaps useful...
My config/environment.rb did not contain ActionMailer::Base.delivery_method = :smtp and my config/environments/test.rb did contain ActionMailer::Base.delivery_method = :test but Rails still delivered mailers while testing.
I simply added the following to config/environments/test.rb to fix:
config.action_mailer.perform_deliveries = false
I faced the similar situation in Rails4.2 (ActiveJob integration with ActionMailer) even if I didn't write delivery_method = :smtp in config/environment.rb.
In my case, The issue here happened after using "resque" as background worker. Finally, I found out that the following config was WRONG:
config/initializers/active_job.rb:
Rails.application.config.active_job.queue_adapter = :resque # here is WRONG
...because it effected to test mode as well.
So, I set "queue_adapter = :resque" only in config/environments/{development,production.rb}. Now, that works as I expect.

Heroku is driving me nuts! Is my code amazingly sloppy, or is Heroku amazingly picky?

wow. going super nuts here trying to deploy to staging on heroku cedar from Rails 3.2.2. I've gotten everything to work, but I wanted to run these issues up the flagpole to see if there's something wrong with... me. eheh
Both of these issues give me the not-helpful "We're sorry, but something went wrong." error page. So it was frustrating when I had 2 different issues (that acted like 3) in one deploy (that worked fine on my local).
Heroku won't give me my logs.
when I run
heroku logs
I get a long error message that starts with,
c:/RailsInstaller/Ruby1.9.3/lib/ruby/1.9.1/net/http.rb:762:in `initialize': Permission denied - connect(2) (Errno::EACCES)
so i've been doing all this troubleshooting via small slices of commits. maddening.
Heroku chokes when it can't find an image with image_tag
this works on heroku:
= image_tag("content/portfolio/maskphoto_rubble_rebel_blur.jpg", :alt => params[:photo], :width => "100%")
This doesn't (only difference is an extra letter in the file name, though it works on my local):
= image_tag("content/portfolio/maskphoto_rubble_rebell_blur.jpg", :alt => params[:photo], :width => "100%")
Am i nuts in thinking that heroku should just serve up the image tag as-is and let it just not display, rather than crashing the entire page? I'm running compass; not sure if that has anything to do with anything.
Heroku hates nested expressions in an array ref
this works:
n = f.index(params[:photo]) +1
#nextphoto = f[ n ]
this doesn't (but does on my local):
#nextphoto = f[ f.index(params[:photo]) +1 ]
i guess it's better form to separate expressions, but still. why would it work on my local and not on deploy?
I can't directly answer all of your questions, but here are a few things to look at:
Heroku won't give me my logs.
The error you are getting indicates Permission denied ... Perhaps your account credentials are not setup properly? I see you are on a windows box ... on a unix machine, the heroku client writes a file at ~/.heroku/credentials with the username and what appears to be an API token. Check to see if you have a similar file. You can also check https://toolbelt.herokuapp.com/windows and make sure you have successfully performed the heroku login command.
Heroku chokes when it can't find an image with image_tag
I don't have many ideas here. Perhaps it is related to the asset-pipeline?
Heroku hates nested expressions in an array ref
This one doesn't make a whole lot of sense either. Perhaps the logs can shed some light here. I did notice that you appear to be running Ruby 1.9.3 on your system, and I don't believe heroku supports 1.9.3 yet. Maybe you have hit a version-specific bug.
I hope that helps. Good luck.

Panda gem and heroku

I've tried following the instructions here:
http://devcenter.heroku.com/articles/pandastream
However, when I open up the heroku console and run the command:
video = Panda::Video.create(:source_url => "http://panda-test-harness-videos.s3.amazonaws.com/panda.mp4")
I've tried adding lots of dynos with:
heroku dynos 100
However I still get the following error from Heroku:
Your application is too busy to open a console session.
Console sessions require an open dyno to use for execution.
Where could I be going wrong?
Cheers,
Richard
That seems more like a problem with Heroku not having setup your app yet, or some other underlying problem.
I have no trouble with this, so write them, and ask what's up :)

Debugging admin_data in Heroku

I'm new to rails and ruby and was able to stitch together my first app and launch it on heroku. All is well, and now I'm trying to solve the problem of how to manage my data. I found the plugin called "admin_data" and it seemed to be the right choice.
Admin_data works great locally but when I deploy it to heroku I just get the message "We're sorry, but something went wrong. (500)". If I restrict access I get the correct response of "not authorized".
I have no idea what's going wrong, and more importantly, don't know how to look into the cause of the error. Any tips on getting a verbose message from heroku or tuning admin_data are much appreciated.
Thanks!
'admin_data' by default only works in a 'development' environment.
You can either set your Heroku app to 'development' environment (http://docs.heroku.com/config-vars) or add your environment to an 'admin_data' config file (config instructions for a Rails 3 app are here: https://github.com/neerajdotname/admin_data/wiki/admin_data-security-configuration-for-a-Rails3-application):
AdminData.config do |config|
config.is_allowed_to_view = lambda {|controller| return true if (Rails.env.development? || Rails.env.test?) }
config.is_allowed_to_update = lambda {|controller| return true if (Rails.env.development? || Rails.env.test?) }
end