Avoid dependency on starting time

This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the algorithms category.

Last Updated: 2021-05-16

I had the following script for a scheduler:

while true; do
  minutes=$(date +%M)

  if [[ $(( 10#$minutes % 10)) -eq 0 ]]; then
    run_task scheduler:every_10_minutes
  fi

  if [[ $(( 10#$minutes )) -eq 0 ]]; then
    run_task scheduler:hourly
  fi
  sleep 60
done

Many times when I ran this script, it never executed the tasks. Why?

I debugged by printing the various times in each logical branch, and saw that if it started at a non- mod 10 minute (e.g. any minutes past the hour that does not have a 0 in it), then the two calculations in the square brackets [x -eq 0] will never be true. i.e. the algorithm is dependent on its starting time.

Here is how to rectify:

starting_minute=$(date +%M)
starting_hour=$(date +%H)

while true; do
  minutes=$(date +%M)
  hours=$(date +%H)

  if [[ $(( 10#$minutes % 10)) -eq $starting_minute ]]; then
    run_task scheduler:every_10_minutes
  fi

  if [[ $(( 10$minutes )) -eq $starting_minute ]]; then
    run_task scheduler:hourly
  fi

  sleep 60
done

The trick is to save the starting time and test any cycles relative to this point rather than a fixed time.