kevincianfarini / cardiologist

Build job schedules with kotlinx-datetime and kotlinx-coroutines
https://kevincianfarini.github.io/cardiologist/docs/0.x/
Apache License 2.0
158 stars 4 forks source link

Add a way to schedule tasks on a day of week #2

Open kevincianfarini opened 11 months ago

kevincianfarini commented 11 months ago

Similar to cron's API.

5 4 * * sun     echo "run at 5 after 4 every sunday"
JakeWharton commented 1 week ago

A full-on cron parser would be great, simply because it's a standard way of expressing when something occurs that a user can supply.

kevincianfarini commented 1 week ago

I agree. I suspect there's two parts to implement this:

  1. Implement day of week functionality with a similar API to the existing Clock.schedulePulse. This might not end up being a separate function overload, but instead an additional parameter to this function. The cron format allows you to specify both day of month and day of week simultaneously.
  2. Implement cron parsing which delegates to ~either the day or week or day of month operators~ the type safe Kotlin APIs.

I am unfortunately extremely busy in my personal life right now so I won't be able to get to this any time soon, but I'd be happy to accept PRs.

kevincianfarini commented 1 week ago

For reference @JakeWharton here's #65

kevincianfarini commented 12 hours ago

After some investigations, cron's method for scheduling on days of week has proven very annoying. Dropping here so I don't forget.

First, the cron API allows specifying schedules that include both a day of month and a day of week. Unlike what you might expect, this isn't and-ed together such that if I specify 0 0 13 * Fri a job will run on every Friday the 13th. No -- instead, this means execute a job at midnight of the thirteenth of every month in addition to executing this job every Friday at midnight. Essentially, the day values are or-ed together instead of and-ed like everything else.

minute && hour && (dayOfMonth || dayOfWeek) && month

Second, the specifier that * means every value is not necessarily true. For other fields, specifying * is a substitute for specifying the full range of values, like 0-59 for minute. However, when used on day of week, this specifier actually means "don't consider day of week". For example, today is December 4th. If I specified 0 0 12 * * the job would execute next on December 12th. However, if I specified 0 0 12 * mon the job would next execute on December 9th. If * actually translated to SUN-SAT like it does for other fields, then * would basically mean execute this job every day. This is not how this behaves.

We should strive to replicate this somewhat broken behavior in cardiologist so that we can support full cron parsing like requested in #65. To do so, we will need to calculate the next matching day of month alongside the next matching day of week and return whichever value occurs sooner. Furthermore, we will need to distinguish between two scenarios:

  1. We want to execute a job on a specific day of week.
  2. We don't want to consider day of week at all.