/** * Collects all elements with a due date. * * Retrospection: searches for next run dates in the past, so it doesn't miss any object in case, one or more executions went wrong. * * The search can be limited to a specific mask by configuration. * The default retrospection time in days can be overridden by configuration. * The default field containing the due date can be overridden by configuration. * * var collector = sol.create("sol.common_monitoring.as.collectors.NextRunCollector", { * soltype: "CONTRACT" * mask: "My Mask", * retrospection: 27, * nextRunField: "MY_DUE_DATE" * }); * * @eloas * * @requires sol.common.SordUtils * @requires sol.common.DateUtils */ sol.define("sol.common_monitoring.as.collectors.NextRunCollector", { /** * @cfg {String} [nextRunField="NEXT_RUN"] (optional) Spezifies, which field is used to search for the due items */ /** * @cfg {Number} [retrospection=365] (optional) Spezifies, how long the rule looks back for next_run dates from now (in days) (see also {@link #defaultRetrospectionTime}) */ /** * @cfg {Number} [searchPeriodEndDays=0] (optional) Spezifies the end of the search period, e.g. `1` for `until yesterday` */ /** * @cfg {String} mask (optional) If set, due items will be filtered by mask */ /** * @cfg {String} soltype (optional) If set, due items will be filtered by solution type (GRP-field `SOL_TYPE`) */ /** * @cfg {Object[]} additionalSearchCriteria (optional) additional criteria which will be used in the initial search for sords. multiple criterions will be "AND"ed * @cfg {Object} additionalSearchCriteria.Object the criterion * @cfg {String} additionalSearchCriteria.Object.key the GRP-field name * @cfg {String|Array} additionalSearchCriteria.Object.value the value, which should be searched for */ /** * @private * @property {String} defaultNextRunField */ defaultNextRunField: "NEXT_RUN", /** * @private * @property {String} defaultRetrospectionTime */ defaultRetrospectionTime: 365, /** * @private * @property {de.elo.ix.client.SordZ} defaultSordZ */ defaultBatchSize: 1000, /** * @private * @property {de.elo.ix.client.SordZ} defaultSordZ */ defaultSordZ: SordC.mbAllIndex, utils: { log: { findInfo: function (self, findInfo) { var findByIndex = (findInfo || {}).findByIndex || {}, name = ((findByIndex.objKeys || [])[0] || {}).name, data = (((findByIndex.objKeys || [])[0] || {}).data || {})[0], maskId = findByIndex.maskId; self.logger.debug(["perform search: nextRunField={0}, lookupPeriod={1}, limitToMask={2}", name, data, maskId]); }, postProcess: function (self, params) { params = params || {}; self.logger.info([ "update next run date(objId={0}, objKey={1}): oldValue='{2}', newValue='{3}'", (params.sord || {}).id, self.nextRunField, params.currentNextRunDate, params.newNextRunDate ]); } } }, initialize: function (config) { var me = this; me.$super("sol.Base", "initialize", [config]); me.nextRunField = (typeof me.nextRunField !== "undefined") ? me.nextRunField : me.defaultNextRunField; me.retrospection = (me.retrospection || (me.retrospection === 0)) ? me.retrospection : me.defaultRetrospectionTime; me.searchPeriodEndDays = (typeof me.searchPeriodEndDays !== "undefined") ? me.searchPeriodEndDays : 0; me._sordZ = me.defaultSordZ; me._batchSize = me.defaultBatchSize; me._findInfo = me.createFindInfo(); me._hasMoreResults = true; }, /** * Checks, if this collector has additional results. * @return {Boolean} */ hasMoreResults: function () { var me = this; return me._hasMoreResults; }, /** * Retrieves the next batch of work items. * @return {de.elo.ix.client.Sord[]} */ getResults: function () { var me = this; me.logger.enter("getResults"); me._workingSet = []; me._hasMoreResults = false; try { me.utils.log.findInfo(me, me._findInfo); if (!me._findResult) { me._idx = 0; me._findResult = ixConnect.ix().findFirstSords(me._findInfo, me._batchSize, me._sordZ); } else { me._findResult = ixConnect.ix().findNextSords(me._findResult.searchId, me._idx, me._batchSize, me._sordZ); } me._workingSet = me._findResult.sords; me._hasMoreResults = me._findResult.moreResults; me._idx += me._findResult.sords.length; } finally { if ((me._hasMoreResults === false) && me._findResult) { ixConnect.ix().findClose(me._findResult.searchId); me._findResult = null; } } me.logger.info(["return result batch: found {0} entries (hasMoreResults={1})", (me._workingSet || []).length, me._hasMoreResults]); me.logger.exit("getResults"); return me._workingSet; }, /** * Checks, if a result set contains any instruction for further executions (`nextRun`) and updates a sord with the most recent. * @param {de.elo.ix.client.Sord} sord * @param {Object[]} results The result object returned by an `analyzer` */ postProcess: function (sord, results) { var me = this, newNextRunDate = "", postprocessingRequired = false, currentNextRunDate; me.logger.enter("postProcess"); if (results && (results.length > 0)) { results.forEach(function (r) { if (r.nextRun) { newNextRunDate = (!newNextRunDate) ? r.nextRun : ((newNextRunDate < r.nextRun) ? newNextRunDate : r.nextRun); postprocessingRequired = true; } }); } if (postprocessingRequired && me.nextRunField) { currentNextRunDate = sol.common.SordUtils.getObjKeyValue(sord, me.nextRunField); me.logger.debug(["next runs: currentNextRunDate={0}, newNextRunDate={1}", currentNextRunDate, newNextRunDate]); if (currentNextRunDate != newNextRunDate) { sol.common.SordUtils.setObjKeyValue(sord, me.nextRunField, newNextRunDate); ixConnect.ix().checkinSord(sord, me._sordZ, LockC.NO); me.utils.log.postProcess(me, { sord: sord, currentNextRunDate: currentNextRunDate, newNextRunDate: newNextRunDate }); } } else { me.logger.debug("no 'nextRuns' defined, skip post processing"); } me.logger.exit("postProcess"); }, /** * Performes cleanup by closeing the search and removing the current working set. */ dispose: function () { var me = this; if (me._findResult) { ixConnect.ix().findClose(me._findResult.searchId); me._findResult = null; } me._workingSet = null; }, /** * @private * Creates a FindInfo object for the search using {@link #nextRunField}, {@link #getLookupPeriod} and {@link #mask}. * @return {de.elo.ix.client.FindInfo} */ createFindInfo: function () { var me = this, fi = new FindInfo(), fbi = new FindByIndex(), objKeys = [], nextRunObjKey = new ObjKey(), soltypeObjKey = new ObjKey(); if (me.nextRunField) { nextRunObjKey.name = me.nextRunField; nextRunObjKey.data = [me.getLookupPeriod()]; objKeys.push(nextRunObjKey); } if (me.mask) { fbi.maskId = me.mask; } if (me.soltype) { soltypeObjKey.name = "SOL_TYPE"; soltypeObjKey.data = [me.soltype]; objKeys.push(soltypeObjKey); } if (Array.isArray(me.additionalSearchCriteria)) { me.additionalSearchCriteria.forEach(function (criterion) { var objKey = new ObjKey(); if (typeof criterion === "object" && criterion.key && (typeof criterion.value === "string") || Array.isArray(criterion.value)) { objKey.name = criterion.key; objKey.data = Array.isArray(criterion.value) ? criterion.value : [criterion.value]; objKeys.push(objKey); } else { throw "an additional search criterion must consist of an object having a key and a value property"; } }); } else if (me.additionalSearchCriteria !== undefined) { throw "parameter additionalSearchCriteria must be an array"; } fbi.objKeys = objKeys; fi.findByIndex = fbi; return fi; }, /** * @private * Calculates the lookup period for the search using {@link #retrospection}. * The period String has the following form: * * "YYYYMMDD...YYYYMMDD" * * where the second ISO string is always the current date. * If {@link #retrospection} is set to 0, just the current date will be returned in ISO form. * * @return {String} */ getLookupPeriod: function () { var me = this, isoPattern = "YYYYMMDD", isoFrom, isoNow, isoEnd, retrospectionDays, searchPeriodEndDays, searchPeriod; if (retrospectionDays === 0) { isoNow = sol.common.DateUtils.format(new Date(), isoPattern); return isoNow; } retrospectionDays = -Math.abs(me.retrospection); searchPeriodEndDays = -Math.abs(me.searchPeriodEndDays); isoFrom = sol.common.DateUtils.shift(new Date(), retrospectionDays, { pattern: isoPattern }); isoEnd = sol.common.DateUtils.shift(new Date(), searchPeriodEndDays, { pattern: isoPattern }); searchPeriod = isoFrom + "..." + isoEnd; return searchPeriod; } });