We have several demo/example/tutorial Apps deployed to Heroku.
Apps on the "free" tier
go to sleep after 30 minutes of inactivity.
see: https://devcenter.heroku.com/articles/free-dyno-hours
In order to wake them,
we wrote a few lines of code that can be added to any
Elixir/Phoenix App and invoked as an image
in the README.md
of the project that links to the App.
So the app is ready to go by the time the person
reading the README.md
clicks on the link. 🔗
We had implemented the "wake from sleep" endpoint
several times in our Heroku Apps,
most recently in our
email
app.
After copy-pasting the code a couple of times,
we decided to make it a DRY reusable package
that we can use in our next app(s)!
An easy way for us to wake our Heroku demo apps.
Note: our use case for this module is "just in time" waking of Heroku dynos.
If you need your "Free" Heroku app to be always awake or awake during specific times of day, consider combining theping
package with a CRON job. You can use a free service such as: https://cron-job.org as described by Mahdhi Rezvi in: https://medium.com/better-programming/keeping-my-heroku-app-alive-b19f3a8c3a82
This package is for anyone building an Elixir/Phoenix app deployed to Heroku.
Add ping
to your Phoenix App
and use it to wake your Heroku App in 4 easy steps:
Install by adding ping
to your list of dependencies in mix.exs
:
def deps do
[
{:ping, "~> 1.1.0"},
]
end
e.g:
mix.exs#L61
Open the router.ex
file of your Phoenix project
and add the following route to your default pipeline:
get "/ping", PingController, :ping
e.g:
lib/app_web/router.ex#L21
defmodule AppWeb.PingController do
use AppWeb, :controller
# see: github.com/dwyl/ping
def ping(conn, params) do
Ping.render_pixel(conn, params)
end
end
e.g:
lib/app_web/controllers/ping_controller.ex#L5-L7
You can either create a brand new controller,
or use an existing one if you prefer.
We've created a new controller for clarity/separation.
Create the corresponding test file to keep your Test coverage complete:
defmodule AppWeb.PingControllerTest do
use AppWeb.ConnCase
test "GET /ping (GIF) renders 1x1 pixel", %{conn: conn} do
conn = get(conn, Routes.ping_path(conn, :ping))
assert conn.status == 200
assert conn.state == :sent
assert conn.resp_body =~ <<71, 73, 70, 56, 57>>
end
end
e.g:
test/app_web/controllers/ping_controller_test.exs#L5-L10
Add an image linking to the endpoint of the App
to the README.md
file:
![wake-sleeping-heroku-app](https://phxtodo.herokuapp.com/ping)
e.g: pull/5/files
The GIF is a transparent 1x1 pixel, so it's both minimal in size to minimise response time and invisible to the person. The idea is just to make the most basic HTTP request to the Heroku app in order to wake it. We don't actually care what is returned. But we don't want it to
404
so the person reading theREADME.md
doesn't see an error in their console/browser.
Docs available at https://hexdocs.pm/ping. But there's really not much to it.