Scheduling jobs in the cloud that twiddle with my Beeminder goals

This is a thread because I decided I wanted the ability to update things in my Beeminder goals from the cloud. Possible use cases include:

  • Adding a datapoint, based on something I can see from the cloud - maybe a datapoint on another beeminder goal, or some public thing I did on Github, or whatever.
  • Adding breaks to goals automatically - maybe I want a break every full moon for three days while I wolf out, or maybe I just want to take every Tuesday and Saturday off as those are the days I redraw the pentagrams that protect my house from other werewolves
  • Sending me an email when a goal goes out of the green
  • Checking my diary for upcoming “DAY OFF” entries and automatically scheduling a Beeminder break for then

I wanted this all being in the cloud because my home machine isn’t on all the time. So I’ll be recording my progress here, and anyone who has any suggestions, feel free to join in!


Today’s progress:

  • Decided to have a goal that nudges me to keep goals back from the red/yellow states, and closer to the blue/green states
  • Set up a do-less goal test_load to track this
  • Selected Google Cloud as my target cloud service, as I’ve had some experience with that. Mutatis mutandis, I think it would be much the same for the other big providers.
  • Wrote a little Python script to give me some score - a lower score is “better”, as fewer goals are red/yellow
  • tested it locally with the Functions Framework, which basically builds a little local http server and runs the function I wrote within it, ready to be triggered by http (e.g. a curl command)
  • Created a Project in gcloud, and then used the Cloud Functions capability to just deploy my little script up in the cloud. It’s deployed as triggered by http:
gcloud functions deploy my_func \
         --region us-central1 \
         --runtime python38  --trigger-http --source .
  • Using the “source” flag allowed me to have includes in my Python file, and re-use my Beeminder API functions that I wrote for other scripts

All this worked fine, and I could test it locally, and also in the cloud.

Next I used the gcloud scheduler to set up a schedule “post” to my function’s url, which will in turn run the script automatically based on that schedule.

gcloud scheduler jobs create http my_func \
    --schedule "45 23 * * *" \
    --uri=  \

We shall see how all that goes!

1 Like

OK, that all worked! Well, mostly: I find that the datapoint went in an hour late. That’s because the cloud scheduler assumes GMT for all times, unless told otherwise. So I needed to modify, because although I live in GMT in winter, we’re currently in summer time. So I need to tell it the timezone for the job

gcloud scheduler jobs update http my_func --timezone="GB" --location=us-central1

And we can check with

gcloud scheduler jobs list --location=us-central1

Which all looks good now!

1 Like

I wonder what else would be interesting to run here? I may try something like a “weekends off, but mid-week”, so a job that schedules a break on (say) Monday, for Tue+Wed the week after. Might be some interesting edge cases if there are already things in the goal matrix around those days!

I was discussing with another user the problems of continuously updating the rate for a goal via a script. They had tried but it seemed to fail when confronted by an upcoming break. I hypothesised that the necessary code might go like this:

  1. ​do a getgoal, which returns the current road matrix (amongst other things)
  2. take the “roadall” value from the returned json; the final row will have your goal’s end date (e.g. 2099-12-31) and current ongoing rate
  3. Usually, just add new row to fix the end of the old rate. This goes just before the final row, with the date of today+7 and the old rate. But this is the tricky bit, if you have a break scheduled! You can’t just add the new row in the penultimate position; instead, if the new rate (so today+7) falls during the break, you would need to adjust the rate that applies after the break is finished. So I think you just skip this step.
  4. update the final row with your new rate
  5. post it back up with putgoal

So I may try that, and see if it can deal with breaks! (The tricky bit is step 3, where you can’t just add a new row if the date for that row would fall in the middle of a pre-scheduled upcoming break)

The appropriately lazy* solution, of course, is to use

Just because a perfectly good solution already exists, that’s not reason not to re-invent it! I love Taskratchet, but who knows where this might lead if I re-do the scheduling function, just for fun!

1 Like

q.v. Hubris*, another of the cardinal virtues!