enonic / xp

Enonic XP
https://enonic.com
GNU General Public License v3.0
202 stars 34 forks source link

libtask get() and perhaps list() should include endTime and duration #6724

Closed ComLock closed 6 years ago

ComLock commented 6 years ago

Workaround: Calculate and store this in JSON.stringified progress.info.

ComLock commented 6 years ago
export function progress({
    current = undefined,
    total = undefined,
    info = {}
} = {}) {
    info.currentTime = currentTimeMillis(); // eslint-disable-line no-param-reassign
    if (info.startTime) {
        info.duration = info.currentTime - info.startTime; // eslint-disable-line no-param-reassign
    } else {
        info.startTime = info.currentTime; // eslint-disable-line no-param-reassign
        info.duration = 0; // eslint-disable-line no-param-reassign
    }
    return _progress({
        current,
        total,
        info: info ? JSON.stringify(info) : undefined
    });
}
alansemenov commented 6 years ago

@ComLock Tasks are stored in memory and live for as long as they are running + some minutes after until they are removed from the memory. Implementing endTime/duration would mean storing task info indefinitely, which would mean storing them not in memory but in the node layer which would mean redoing the whole task engine (and then there are questions like cleanup, permissions etc.).

You should probably gather all your requirements to the tasks lib in one big list - which we will discuss on PAB - rather than creating all these small issues. As of now, what you are asking for is not doable unfortunately, so you'll have to use a workaround.

ComLock commented 6 years ago

@alansemenov I have expanded a bit with left, averageTimePerItem and estimatedTimeLeftHr, which can give you stuff like this:

[
    {
        "description": "Root",
        "id": "052a52a6-c7ff-4259-b7db-d49ef965396e",
        "name": "com.enonic.app.crawler:root",
        "state": "RUNNING",
        "application": "com.enonic.app.crawler",
        "user": "user:system:su",
        "startTime": "2018-11-07T12:57:32.694Z",
        "progress": {
            "info": {
                "rootId": "a3ee03fe-136c-4bcd-a4d2-43f2dcd2829d",
                "currentTime": 153469012.971663,
                "startTime": 153412236.092074,
                "duration": 56776.8795889914,
                "durationHR": "56s 776ms 879µs 588ns",
                "left": 34,
                "state": "Prosessing url SNIPPED",
                "url": "SNIPPED",
                "averageTimePerItem": 1957.8234341031518,
                "estimatedTimeLeftHr": "1m 6s 565ms 996µs 759ns",
                "nodeId": null
            },
            "current": 29,
            "total": 63
        }
    }
]
//──────────────────────────────────────────────────────────────────────────────
// Polyfill
//──────────────────────────────────────────────────────────────────────────────
if (Number.isFinite === undefined) { // Needed by pretty-ms
    Number.isFinite = value => typeof value === 'number' && isFinite(value); // eslint-disable-line no-restricted-globals
}
/* eslint-disable import/first */
import mathTrunc from 'math-trunc';

if (!Math.trunc) { Math.trunc = mathTrunc; } // Needed by pretty-ms

//──────────────────────────────────────────────────────────────────────────────
// Node modules (webpacked)
//──────────────────────────────────────────────────────────────────────────────
import prettyMs from 'pretty-ms';

//──────────────────────────────────────────────────────────────────────────────
// Enonic XP libs (externals not webpacked)
//──────────────────────────────────────────────────────────────────────────────
import {progress as _progress} from '/lib/xp/task';

//──────────────────────────────────────────────────────────────────────────────
// Local libs (Absolute path without extension so it doesn't get webpacked)
//──────────────────────────────────────────────────────────────────────────────
import {nanoTime} from '/lib/appCrawler/nanoTime';

//──────────────────────────────────────────────────────────────────────────────
// Public function
//──────────────────────────────────────────────────────────────────────────────
export function progress({
    current = undefined,
    total = undefined,
    info = {}
} = {}) {
    info.currentTime = nanoTime() / 1000000; // eslint-disable-line no-param-reassign
    if (info.startTime) {
        info.duration = info.currentTime - info.startTime; // eslint-disable-line no-param-reassign
    } else {
        info.startTime = info.currentTime; // eslint-disable-line no-param-reassign
        info.duration = 0; // eslint-disable-line no-param-reassign
    }
    info.durationHR = prettyMs(info.duration, {  // eslint-disable-line no-param-reassign
        formatSubMs: true,
        separateMs: true
    });
    info.left = total - current; // eslint-disable-line no-param-reassign
    if (info.duration && current) {
        info.averageTimePerItem = info.duration / current; // eslint-disable-line no-param-reassign
        info.estimatedTimeLeftHr = prettyMs(info.left * info.averageTimePerItem, { // eslint-disable-line no-param-reassign
            formatSubMs: true,
            separateMs: true
        });
    }
    log.info(`[${current}/${total}] ${info.url || ''}`);
    return _progress({
        current,
        total,
        info: info ? JSON.stringify(info) : undefined
    });
}