add jenkins-like "Hashed project value" cron parameter to avoid over scheduling at "nice" times
Background
For years Jenkins has allowed pipeline scheduling to use the H parameter to allow a sort of "ranged" scheduling in pipelines (https://www.jenkins.io/doc/book/pipeline/syntax/#cron-syntax). The parameter is taken as a hashed value of job name, but for our purposes it could be any fixed value related to that job (so you could do ${projectId}-${scheduleId} if needed). The parameter can additionally be given a particular range so you can limit the scope: H(0-7) will result in the use of an integer between 0 and 7 inclusive.
The purpose of the value is to avoid the problem that humans are not random: if you have multiple projects that need to run their pipelines "outside of business hours" (or, more concretely, "between 19:00 and 07:00" each day), then you'll find most of those get scheduled at the start of each hour, or just after 19:00, or at midnight. This can cause bottlenecks, pipeline failures and poor resource utilization.
It is worth noting (though not well documented) that the /pipeline_schedules/:id/edit page attempts something like this by presenting a different random value next to the Every Day, Ever week and Every Month pre-configured options whenever you refresh the page. Unfortunately these can not be configured to fall within a specific range and appear to always attempt to schedule at the start of each hour. Additionally, because they change every time the page is refreshed it can be confusing when someone is trying to set the schedule.
Proposal
Add in a template functionH() (or any other arbitrary name), that can be given two arguments "min" and "max" and places a pseudorandom integer into the cron template at that position.
The result is that Project X's can have a scheduled pipeline Y with the "Custom" specification:
H(0,59) H(19,23) * * *
That would run daily at some (fixed) point between 19:00 and 23:59. Note here that for simplicity, the H function cannot handle a range like H(19,7) (where the intention would be "between 19:00 and 07:00), because it would not be aware of the context of hours being mod24, so would not be able to know the range of values it could use.
Summary:
- Change pipeline_schedule's "Custom" cron field to allow a psuedo-random, ranged value to be given at any position
- The value can be given an inclusive range
- base "value" should be fairly "stable" and should remain "mostly" consistent across scheduled jobs' lifetime.
- hence the suggestion for
hash(${projectId}-${scheduleId})as the base value to be reduced from. UX improvement after:
- hence the suggestion for
- additional options on existing
/pipeline_schedules/:id/editpage next to pre-configured options to select ranges for values
Extension:
If we wanted to handle cases like "I want a pipeline to be able to run daily anytime between 19:00 and 07:00 the next day", then you could add some additional maths or offsetting ability to the template, or just do context aware modulus of value provided. For ease I would add a third "radix" parameter: H(19,7,24), as this would allow a readable argument list and also be a generic implementation that doesn't have different parsing needs dependent on it's location in the template. Note that this functionality is not present in Jenkins.