Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible to add a way to schedule maintenance every first Monday, Tuesday, etc...? #3186

Open
1 task done
b-a0 opened this issue May 22, 2023 · 11 comments
Open
1 task done
Labels
area:maintenance related to the maintenance mode feature-request Request for new features to be added

Comments

@b-a0
Copy link

b-a0 commented May 22, 2023

⚠️ Please verify that this feature request has NOT been suggested before.

  • I checked and didn't find similar feature request

🏷️ Feature Request Type

Other

🔖 Feature description

The maintenance scheduler allows scheduling with cron. While cron on Debian allows one to schedule something on the first Monday (or Tuesday) of a month, the used cron library croner does not.

However, croner does offer a legacy mode that would check the date of month and day of week conditions with an AND operator instead of the default OR operator.

✔️ Solution

By adding a checkmark next to the cron expression that would toggle croner legacy mode, you could create a cron expression:

0 18 1-7 * MON

Without the legacy box unchecked (as it is now) this would be:

Schedule: At 06:00 PM, between day 1 and 7 of the month, and on Monday

With the legacy box checked:

Schedule: At 06:00 PM, between day 1 and 7 of the month only if a Monday

❓ Alternatives

I have tried different cron expressions listed in this Superuser post. Unfortunately none of them work with the croner library.

📝 Additional Context

I only have a very rough understanding of JS, but to me it seems that a change would be needed in /server/model/maintenance.js#L264. Something like this fake code:

// Create Cron
this.beanMeta.job = new Cron(this.cron, {
    timezone: await this.getTimezone(),
}, { legacyMode: this.cronLegacy }, startEvent);

and in the UI around /src/pages/EditMaintenance.vue#L94.

@b-a0 b-a0 added the feature-request Request for new features to be added label May 22, 2023
@CommanderStorm
Copy link
Collaborator

I would not like to add this additional feature.
Any variable prefixed with legacy is something, that I would expect will not be there forever. => this would likely unexpectedly break in the future.

Would 0 0 0 * * L1 work for you?

@b-a0
Copy link
Author

b-a0 commented May 23, 2023

Thanks for the suggestion. My understanding is that the L parameter schedules something on the last specified weekday of the month. I am looking to schedule something on the first Wednesday of the month, not the last, i.e. 0 18 1-7 * 3 { legacyMode: false }.

Is it possible to do that as well in the current version of Uptime Kuma?

I am not sure "legacy" refers to this being ready to deprecate in this case. Note also that it is set to true by default. I will check in the linked croner issue what their intentions are with this parameter.

@Hexagon
Copy link

Hexagon commented May 23, 2023

Setting legacyMode to false is perfectly safe and a permanent feature of croner.

The default will always be legacyMode: true, which makes croner work like legacy cron parsers, which is expected behaviour, even though it's not optimal.

Confusing - yes! Need to worry - no 😄

@CommanderStorm
Copy link
Collaborator

@b-a0

Would adding such a toggle in the settings also solve #2621?

What do you think would be a good UI for this? (what kind of help text + what input element)

@b-a0
Copy link
Author

b-a0 commented May 25, 2023

Would adding such a toggle in the settings also solve #2621?

I think so, it seems to work for second and third $dayOfWeek.
Here are a few croner examples (all with legacyMode: false) which I've double checked with Excel for 2023 (marked with a ✔️ if it was the same):

First Monday: 0 18 1-7 * 1 ✔️
First Wednesday: 0 18 1-7 * 3 ✔️
Second Tuesday: 0 18 8-14 * 2 ✔️
Second Friday: 0 18 8-14 * 5 ✔️
Third Monday: 0 18 15-21 * 1 ✔️
Third Sunday: 0 18 15-21 * 7 ✔️

What do you think would be a good UI for this? (what kind of help text + what input element)

I'm not well versed in web-design, but as a user I think a checkbox (that is unchecked by default) next to the cron textbox would make sense:

image

Checking the checkbox would set legacyMode: false.

Regarding the helptext, something similar to the Cloudflare settings page would probably be clear in terms of formatting:

image

The text (in light gray) could say something like:

There are different modes of restricting the day on which the maintenance is scheduled. When the checkbox is unchecked, the default cron behaviour is used. The checkbox enables non-standard behaviour that enables you to restrict to the Nth weekday within a month. For more info see this link: Hexagon/croner#53

Instead of the croner issue, it could also link to the current issue.

Hope this helps? Let me know if I can provide anything else.

@louislam
Copy link
Owner

The checkbox should be easy to be implemented.

But the cron description (This message: Schedule: At 06:00 PM, between day 1 and 7 of the month only if a Monday) maybe a bit hard to implement, because it is actually generated by another library called crontrue.

@b-a0
Copy link
Author

b-a0 commented May 29, 2023

bit hard to implement, because it is actually generated by another library called crontrue.

That is tricky indeed. I see two options, both are less than elegent unfortunately:

  1. When the checkbox is checked (i.e. legacyMode: false) the text returned by crontrue is slightly alterend. A few examples:
    • First Monday: 0 18 1-7 * 1, instead of: "At 06:00 PM, between day 1 and 7 of the month, and on Monday", replace the last "and" with "only": "At 06:00 PM, between day 1 and 7 of the month, only on Monday".
    • Similarly works for other days: 0 18 15-21 * 7 would result in "At 06:00 PM, between day 15 and 21 of the month, only on Sunday"
    • Multiple days should work fine as well: 0 18 15-21 * 1,2,3,4 would result in "At 06:00 PM, between day 15 and 21 of the month, only on Monday, Tuesday, Wednesday, and Thursday"
    • Day ranges are a bit harder though: 0 18 15-21 * 1-5 currenly returns "At 06:00 PM, between day 15 and 21 of the month, Monday through Friday". You would need to somehow add "only" between the comma and "Monday".
      This does not take into account internationalisation with i18n...
  2. When the checkbox is checked (i.e. legacyMode: false) reparse the provided cron expression and use the # symbol in the day-of-week field to indicate the Nth day (which is supported by cronstrue, but not by croner). Some examples:
    • 0 18 1-7 * 1 -> 0 18 1-7 * 1#1: "At 06:00 PM, between day 1 and 7 of the month, on the first Monday of the month"
    • 0 18 1-7 * 1,2 -> 0 18 1-7 * 1#1,2#1: "At 06:00 PM, between day 1 and 7 of the month, on the first Monday and first Tuesday of the month"
    • 0 18 8-14 * 1-4 -> 0 18 8-14 * 1#2-4#2: "At 06:00 PM, between day 8 and 14 of the month, second Monday through second Thursday"

In the second option there is a bit of redundancy there as it specifies both "between day X and Y of the month" and "Nth day of the week".

@CommanderStorm
Copy link
Collaborator

CommanderStorm commented May 29, 2023

I thought about this a bit more:
Maybe a global toggle for this would not be super intuitive. I think adding nth-week of the month here would be more elegant (and most importantly, less confusing):
image

I don't fully know how specifically, though.

  • adding a new strategy
  • adding this to the form I opened (maybe Restrict to-selector with ["1st Week of the month","2nd Week of the month","3rd Week of the month", "last occurrance in month"])

Both sound like a messy idea, though.

On the other hand, adding a toggle box (with an appropriate tooltip, explaining how n-th day of the week could work) here could also make sense Connect Days of the week and Dates using -> AND/OR, OR being the default:
image

@Hexagon
Copy link

Hexagon commented Aug 8, 2023

Proper support for nth weekday of month through # specifier is now released in the dev-channel of croner. Progress tracked at Hexagon/croner#198 and will be released in 7.0.0 within a week.

This will enable patterns such as 0 0 0 * * FRI#2 or 0 0 0 * * 5#2 for second friday of month, and it will be possible to combine with other features, such as names, ranges and L to make more complex constructs - such as 0 0 0 * * MON-FRI#L for every last weekday of the month.

@CommanderStorm CommanderStorm added the area:maintenance related to the maintenance mode label Dec 5, 2023
@NoeMeinhardt
Copy link

Any progress on this? The data center we use performs scheduled maintenance every third Saturday and Sunday of the month. I would love to use 0 0 0 * * 6#2 with a duration of 2879 minutes, but it says it "contains illegal characters".

@CommanderStorm
Copy link
Collaborator

CommanderStorm commented Feb 14, 2024

The reason why this is not avaliable is that we have not found the time to migrate croner to v7. See

"croner": "~6.0.5",

This change either needs calling out or a migration:

Note

Compared to previous versions, there's a change in the way L functions in the day-of-week field. In version 6.x, L had flexibility in its positioning: both LSUN and SUNL were valid expressions to denote the last Sunday of the month. However, starting from version 7.x, L must be used in a more standardized way, in conjunction with the nth weekday specifier #, like so: SUN#L.

Here is our contribution guide: https://github.com/louislam/uptime-kuma/blob/master/CONTRIBUTING.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:maintenance related to the maintenance mode feature-request Request for new features to be added
Projects
None yet
Development

No branches or pull requests

5 participants