Home Manual Reference Source Test Repository

src/operations/catalog/period/PeriodicityUpdateBuilder.js

'use strict';

import merge from 'merge';
import moment from 'moment';

import Operation from '../Operation';
import ExecuteEvery from './ExecuteEveryBuilder';
import ExecuteEach from './ExecuteEachBuilder';
import ByGeneric from './pattern/ByGeneric';

import { TIME_FORMAT, DATE_FORMAT } from './../../../util/DATE_FORMAT';

export default class PeriodicityUpdateBuilder {

    constructor(ogapi, taskId, taskObj) {
        this._ogapi = ogapi;
        this._task = taskObj;
        this.task_id = taskId;
        this._resource = "/tasks/" + this.task_id;
        this._build = merge(true, this._task.job.request);
    }

    /**
     * The operation will execute with a period that you must define with ExecuteEveryBuilder 
     * @param {!Date} date - Date when operation will be executed
     * @param {number or Date} end - When periodicity ends. By repetitions or by date
     * @throws {Error} throw error when date is not typeof Date
     * @return {ExecuteEvery}
     */
    executeEvery(date, end) {
        let args = Array.prototype.slice.call(arguments);
        let _end = this._getEnd(args.slice(1, 3));
        date = this._getStart(date);
        this._byGeneric = new ByGeneric(this, date, null, end)._build();
        return new ExecuteEvery(this, date, null, _end);
    }

    /**
     * The operation will execute with a period that you must define with ExecuteEachBuilder 
     * @param {!Date} date - Date when operation will be executed
     * @param {number or Date} end - When periodicity ends. By repetitions or by date 
     * @throws {Error} throw error when date is not typeof Date
     * @return {ExecuteEach}
     */
    executeEach(date, end) {
        let args = Array.prototype.slice.call(arguments);
        let _end = this._getEnd(args.slice(1, 3));
        let schedule = this._task.schedule;
        date = this._getStart(date);
        if (schedule && schedule.repeating && schedule.repeating.period) {
            let period = schedule.repeating.period;
            return new ExecuteEach(this, date, null, _end)._addPeriod(period.each, period.unit);
        }
        return new ExecuteEach(this, date, null, _end);
    }

    _getStart(date) {
        let schedule = this._task.schedule;
        if (!date && (schedule.start && schedule.start.date)) {
            date = new Date(schedule.start.date);
        }
        return date;
    }

    _getEnd(args) {
        for (let i = 0; i < args.length; i++) {
            if (typeof args[i] === "number" || args[i].constructor === Date) {
                return args[i];
            }
        }
        let schedule = this._task.schedule;
        if (schedule.stop && schedule.stop.date) {
            return new Date(schedule.stop.date);
        }
        return undefined;
    }

    build() {
        let _build = merge(true, this._build);
        let postObj;
        let errors = [];
        if (typeof this._build.task !== "undefined") {
            let task = this._build.task;
            // CHECK period and job timeout
            let jobTimeout = this._build.schedule.stop;
            if (typeof task.repeating.period !== "undefined") {
                let maxJobTimeout;
                switch (task.repeating.period.unit) {
                    case "DAYS":
                        maxJobTimeout = moment.duration(task.repeating.period.each, 'days').asMilliseconds();
                        break;
                    case "HOURS":
                        maxJobTimeout = moment.duration(task.repeating.period.each, 'hours').asMilliseconds();
                        break;
                    case "MINUTES":
                        maxJobTimeout = moment.duration(task.repeating.period.each, 'minutes').asMilliseconds();
                        break;
                }
                if (typeof jobTimeout !== "undefined" && typeof jobTimeout.delayed === "number") {
                    if (jobTimeout.delayed >= maxJobTimeout) {
                        errors.push("You can not execute an operation with a job timeout greater than the repetition period.");
                    }
                }
            }
        }

        if (errors.length > 0) {
            this._build = _build;
            throw errors;
        }
        if (typeof this._build.task !== "undefined") {
            postObj = this._updateTask(this._build);
        }
        let op = new Operation(this._ogapi, this._resource, postObj);
        // Se deshacen todos los por defectos aplicados al objeto builder, para no condicionar el siguiente .build 
        this._build = _build;
        return op;
    }

    _updateTask(_build) {
        let task = _build.task;
        let now = moment(new Date());
        let start = moment(task.start);
        
        let taskObj = {
            task: {
                schedule: {}
            }
        };
        try {
            if (task.start) {
                taskObj.task.schedule.start = { "date": start.format(DATE_FORMAT) };
            }

            if (task.stop) {
                taskObj.task.schedule.stop = { "date": moment(task.stop).format(DATE_FORMAT) };
            }

            if (task.repeating) {
                taskObj.task.schedule.repeating = task.repeating;
            }
        } catch (err) {
        }
        delete taskObj.task.schedule.name;
        if (typeof task.stop !== "undefined") {
            if (typeof task.stop.date !== "undefined") {
                taskObj.task.schedule.stop = {
                    date: moment(task.stop.date).format(DATE_FORMAT)
                };
            } else {
                taskObj.task.schedule.stop = task.stop;
            }
        }
        if (moment.max(now, start) == now) {
            if (typeof task.stop !== "undefined" && typeof task.stop.date !== "undefined") {
                let stopDate = moment(task.stop.date);
                if (moment.max(now, stopDate) == now) {
                    throw new Error("Can not create operation object because stop operation period is earlier than current date. " +
                        "It happened because you passed a lot of time between configuration of an operation and create the operation.");
                }
            }
            delete taskObj.task.schedule.start;
        }
        return taskObj;
    }
}