Search code examples
pythonherokurequest

Turn off webapp dyno using api - Heroku


I am trying to make a script that checks to see if my dyno is idle, if it is then it stops the dyno/webapp. The only problem is that it seems to do nothing even though the post request will come back with accepted:

from email import header
import requests
import dotenv

heroku_api_token = "Bearer ENTERAPITOKENHERE"
headers = {
    'Accept': 'application/vnd.heroku+json; version=3',
    'Authorization': heroku_api_token
}
statecheck = requests.get("https://api.heroku.com/apps/rockosmodernapp/dynos/web.1",headers=headers).json()
print(statecheck)
if statecheck["state"] == "idle":
    print("shutting down web app worker")
elif statecheck["state"] == "up":
    print("app is still up, will check in 15 minutes to see if app is idle")

postheader = {
    "Content-Type": "application/json",
    "Accept": "application/vnd.heroku+json; version=3",
    'Authorization': heroku_api_token
}
stopdynoobject = {

}

stopdyno = requests.post("https://api.heroku.com/apps/rockosmodernapp/dynos/web.1/actions/stop",headers=postheader)
print(stopdyno.reason)

It will look like it will stop, then it just immediately restarts:

2022-10-20T03:05:55.221896+00:00 heroku[web.1]: State changed from up to down
2022-10-20T03:05:56.368472+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2022-10-20T03:05:56.673413+00:00 heroku[web.1]: Process exited with status 143
2022-10-20T03:06:13.858381+00:00 heroku[web.1]: State changed from down to starting

Also the dashboard still shows the web worker running: enter image description here


Solution

  • I figured it out - Use the FORMATION endpoint from Heroku's api to change the quantity of web workers to 0. This will turn off the dyno in heroku, thus saving money.

    from email import header
    import requests
    import json
    import dotenv
    
    heroku_api_token = "Bearer ENTERHEROKUAPIKEYHERE"
    headers = {
        'Accept': 'application/vnd.heroku+json; version=3',
        'Authorization': heroku_api_token
    }
    statecheck = requests.get("https://api.heroku.com/apps/rockosmodernapp/dynos/web.1",headers=headers).json()
    print(statecheck)
    if statecheck["state"] == "idle":
        print("shutting down web app worker")
    elif statecheck["state"] == "up":
        print("app is still up, will check in 15 minutes to see if app is idle")
    
    postheader = {
        "Content-Type": "application/json",
        "Accept": "application/vnd.heroku+json; version=3",
        'Authorization': heroku_api_token
    }
    
    stopdynoobject = {
        "updates" :[{"quantity":0,
                    "type": "web"}]
    }
    
    stopdynoobject_str = json.dumps(stopdynoobject)
    turnoffdyno = requests.patch("https://api.heroku.com/apps/rockosmodernapp/formation",headers=headers,data=stopdynoobject_str).json()
    print(turnoffdyno)