Skip to content

Commit

Permalink
Implementing louislam#928 with a cron expression. Limited code and wo…
Browse files Browse the repository at this point in the history
…rkflow changes.
  • Loading branch information
LLeny committed Feb 11, 2022
1 parent e7e30bf commit 5e609da
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 3 deletions.
7 changes: 7 additions & 0 deletions db/patch-monitor-active-cron.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;

ALTER TABLE monitor
ADD cron VARCHAR(99) DEFAULT NULL;

COMMIT;
1 change: 1 addition & 0 deletions server/database.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class Database {
"patch-2fa-invalidate-used-token.sql": true,
"patch-notification_sent_history.sql": true,
"patch-monitor-basic-auth.sql": true,
"patch-monitor-active-cron.sql": true,
}

/**
Expand Down
22 changes: 20 additions & 2 deletions server/model/monitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const { Notification } = require("../notification");
const { demoMode } = require("../config");
const version = require("../../package.json").version;
const apicache = require("../modules/apicache");
const later = require("@breejs/later");

/**
* status:
Expand Down Expand Up @@ -79,6 +80,7 @@ class Monitor extends BeanModel {
pushToken: this.pushToken,
notificationIDList,
tags: tags,
cron: this.cron,
};
}

Expand Down Expand Up @@ -377,7 +379,7 @@ class Monitor extends BeanModel {
}
}

let beatInterval = this.interval;
let beatInterval = this.getNextInterval();

debug(`[${this.name}] Check isImportant`);
let isImportant = Monitor.isImportantBeat(isFirstBeat, previousBeat?.status, bean.status);
Expand Down Expand Up @@ -457,12 +459,28 @@ class Monitor extends BeanModel {
if (this.type === "push") {
setTimeout(() => {
safeBeat();
}, this.interval * 1000);
}, this.getNextInterval() * 1000);
} else {
safeBeat();
}
}

getNextInterval() {
if (!this.cron || /^\s*$/.test(this.cron)) {
return this.interval;
}
const laterCron = later.parse.cron(this.cron);
const nextOccurences = later.schedule(laterCron).next(2);

let calculatedInterval = Math.floor((nextOccurences[0].getTime() - Date.now()) / 1000);
if (calculatedInterval < 20) { //beat interval too low, using next interval
calculatedInterval = Math.floor((nextOccurences[1].getTime() - Date.now()) / 1000);
}

console.log(`Monitor #${this.id} '${this.name}': getNextInterval - calculatedInterval: ${calculatedInterval} `);
return calculatedInterval;
}

stop() {
clearTimeout(this.heartbeatInterval);
this.isStop = true;
Expand Down
2 changes: 2 additions & 0 deletions server/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,7 @@ exports.entryPage = "dashboard";
bean.dns_resolve_type = monitor.dns_resolve_type;
bean.dns_resolve_server = monitor.dns_resolve_server;
bean.pushToken = monitor.pushToken;
bean.cron = monitor.cron;

await R.store(bean);

Expand Down Expand Up @@ -1165,6 +1166,7 @@ exports.entryPage = "dashboard";
dns_resolve_type: monitorListData[i].dns_resolve_type,
dns_resolve_server: monitorListData[i].dns_resolve_server,
notificationIDList: {},
cron: monitorListData[i].cron,
};

if (monitorListData[i].pushToken) {
Expand Down
2 changes: 2 additions & 0 deletions src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -361,4 +361,6 @@ export default {
smtpDkimHashAlgo: "Hash Algorithm (Optional)",
smtpDkimheaderFieldNames: "Header Keys to sign (Optional)",
smtpDkimskipFields: "Header Keys not to sign (Optional)",
Cron: "Cron scheduler",
cronDescription: "Schedule the monitor using a cron expression, overrides Heartbeat Interval",
};
2 changes: 2 additions & 0 deletions src/languages/fr-FR.js
Original file line number Diff line number Diff line change
Expand Up @@ -304,4 +304,6 @@ export default {
steamApiKeyDescription: "Pour surveiller un serveur Steam, vous avez besoin d'une clé Steam Web-API. Vous pouvez enregistrer votre clé ici : ",
"Current User": "Utilisateur actuel",
recent: "Récent",
Cron: "Cron planificateur",
cronDescription: "Planifie le monitor en utilisant une expression cron, outrepasse Intervalle de vérification",
};
2 changes: 2 additions & 0 deletions src/languages/zh-HK.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,4 +198,6 @@ export default {
pushbullet: "Pushbullet",
line: "Line Messenger",
mattermost: "Mattermost",
Cron: "Cron 時間表",
cronDescription: "用cron表達式設定監測器時間表,覆載間距",
};
14 changes: 13 additions & 1 deletion src/pages/EditMonitor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@
<input id="interval" v-model="monitor.interval" type="number" class="form-control" required min="20" step="1">
</div>

<!-- Cron -->
<div class="my-3">
<label for="cron" class="form-label">{{ $t("Cron") }}</label>
<input id="cron" v-model="monitor.cron" type="text" class="form-control" :pattern="cronRegex" maxlength="99">
<div class="form-text">
{{ $t("cronDescription") }}
</div>
</div>

<div class="my-3">
<label for="maxRetries" class="form-label">{{ $t("Retries") }}</label>
<input id="maxRetries" v-model="monitor.maxretries" type="number" class="form-control" required min="0" step="1">
Expand Down Expand Up @@ -321,7 +330,9 @@ export default {
// Source: https://digitalfortress.tech/tips/top-15-commonly-used-regex/
ipRegexPattern: "((^\\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\\s*$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$))",
// Source: https://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address
hostnameRegexPattern: "^(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\\-_]*[a-zA-Z0-9_])\\.)*([A-Za-z0-9_]|[A-Za-z0-9_][A-Za-z0-9\\-_]*[A-Za-z0-9_])$"
hostnameRegexPattern: "^(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\\-_]*[a-zA-Z0-9_])\\.)*([A-Za-z0-9_]|[A-Za-z0-9_][A-Za-z0-9\\-_]*[A-Za-z0-9_])$",
// Source: https://stackoverflow.com/questions/14203122/create-a-regular-expression-for-cron-statement/19046939
cronRegex: "(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\\d+(ns|us|µs|ms|s|m|h))+)|((((\\d+,)+\\d+|(\\d+(\\/|-)\\d+)|\\d+|\\*) ?){5,7})",
};
},
Expand Down Expand Up @@ -439,6 +450,7 @@ export default {
accepted_statuscodes: ["200-299"],
dns_resolve_type: "A",
dns_resolve_server: "1.1.1.1",
cron: "",
};
for (let i = 0; i < this.$root.notificationList.length; i++) {
Expand Down

0 comments on commit 5e609da

Please sign in to comment.