async run(throwError = false) {
        if (this.beanMeta.job) {
            log.debug("maintenance", "Maintenance is already running, stop it first. id: " + this.id);
            this.stop();
        }

        log.debug("maintenance", "Run maintenance id: " + this.id);

        // 1.21.2 migration
        if (!this.cron) {
            await this.generateCron();
            if (!this.timezone) {
                this.timezone = "UTC";
            }
            if (this.cron) {
                await R.store(this);
            }
        }

        if (this.strategy === "manual") {
            // Do nothing, because it is controlled by the user
        } else if (this.strategy === "single") {
            this.beanMeta.job = new Cron(this.start_date, { timezone: await this.getTimezone() }, () => {
                log.info("maintenance", "Maintenance id: " + this.id + " is under maintenance now");
                UptimeKumaServer.getInstance().sendMaintenanceListByUserID(this.user_id);
                apicache.clear();
            });
        } else if (this.cron != null) {
            // Here should be cron or recurring
            try {
                this.beanMeta.status = "scheduled";

                let startEvent = async (customDuration = 0) => {
                    log.info("maintenance", "Maintenance id: " + this.id + " is under maintenance now");

                    this.beanMeta.status = "under-maintenance";
                    clearTimeout(this.beanMeta.durationTimeout);

                    let duration = this.inferDuration(customDuration);

                    UptimeKumaServer.getInstance().sendMaintenanceListByUserID(this.user_id);

                    this.beanMeta.durationTimeout = setTimeout(() => {
                        // End of maintenance for this timeslot
                        this.beanMeta.status = "scheduled";
                        UptimeKumaServer.getInstance().sendMaintenanceListByUserID(this.user_id);
                    }, duration);
                };

                // Create Cron
                if (this.strategy === "recurring-interval") {
                    // For recurring-interval, Croner needs to have interval and startAt
                    const startDate = dayjs(this.startDate);
                    const [ hour, minute ] = this.startTime.split(":");
                    const startDateTime = startDate.hour(hour).minute(minute);
                    this.beanMeta.job = new Cron(this.cron, {
                        timezone: await this.getTimezone(),
                        interval: this.interval_day * 24 * 60 * 60,
                        startAt: startDateTime.toISOString(),
                    }, startEvent);
                } else {
                    this.beanMeta.job = new Cron(this.cron, {
                        timezone: await this.getTimezone(),
                    }, startEvent);
                }

                // Continue if the maintenance is still in the window
                let runningTimeslot = this.getRunningTimeslot();
                let current = dayjs();

                if (runningTimeslot) {
                    let duration = dayjs(runningTimeslot.endDate).diff(current, "second") * 1000;
                    log.debug("maintenance", "Maintenance id: " + this.id + " Remaining duration: " + duration + "ms");
                    startEvent(duration);
                }

            } catch (e) {
                log.error("maintenance", "Error in maintenance id: " + this.id);
                log.error("maintenance", "Cron: " + this.cron);
                log.error("maintenance", e);

                if (throwError) {
                    throw e;
                }
            }

        } else {
            log.error("maintenance", "Maintenance id: " + this.id + " has no cron");
        }
    }
Run the cron
@param {boolean} throwError Should an error be thrown on failure
@returns {Promise<void>}