RenderSequenceImpl.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. 'use strict';
  2. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  3. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  4. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  5. /**
  6. * Licensed Materials - Property of IBM
  7. * IBM Business Analytics (C) Copyright IBM Corp. 2019, 2020
  8. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  9. */
  10. /**
  11. * @class RenderSequenceImpl
  12. * @hideconstructor
  13. * @classdesc
  14. */
  15. define(['underscore', '../../../../lib/@waca/dashboard-common/dist/api/impl/CallbackInvoker', '../../../../lib/@waca/dashboard-common/dist/core/APIFactory', '../../../../lib/@waca/dashboard-common/dist/api/Error', '../api/RenderContextAPI', '../s12y/RenderSequenceInfo', '../s12y/ServiceabilityRenderingInfo', '../s12y/ServiceabilitySQLInfo', './RenderContextImpl', '../s12y/RenderingInfo'], function (_, CallbackInvoker, APIFactory, APIError, RenderContextAPI, RenderSequenceInfo, ServiceabilityRenderingInfo, ServiceabilitySQLInfo, RenderContextImpl, RenderingInfo) {
  16. var _class, _temp;
  17. var RenderSequenceImpl = (_temp = _class = function (_CallbackInvoker) {
  18. _inherits(RenderSequenceImpl, _CallbackInvoker);
  19. /**
  20. * TODO: remove the usage of dashboardAPI.getService when dashboardAPI.getFeature includes the glass service
  21. * @param {Object} options
  22. * @param {DashboardAPI} options.dashboardAPI
  23. * @param {Object[]} options.features
  24. */
  25. function RenderSequenceImpl(_ref) {
  26. var dashboardAPI = _ref.dashboardAPI,
  27. features = _ref.features,
  28. content = _ref.content;
  29. _classCallCheck(this, RenderSequenceImpl);
  30. var logger = dashboardAPI.getService(dashboardAPI.GLOBAL_SERVICES.LOGGER);
  31. var _this = _possibleConstructorReturn(this, _CallbackInvoker.call(this, { logger: logger }));
  32. _this._logger = logger;
  33. _this._s12yAPI = features['Serviceability'];
  34. _this._renderStepProviders = [];
  35. _this._currentRenderContext = {};
  36. _this.content = content;
  37. var impl = _this;
  38. _this.onStartTaskExecution(function (options) {
  39. impl.s12yOnStartTaskExecution(options);
  40. });
  41. _this.onResolveTaskExecution(function (options) {
  42. impl.s12yOnResolveTaskExecution(options);
  43. });
  44. _this.onRejectTaskExecution(function (options) {
  45. impl.s12yOnRejectTaskExecution(options);
  46. });
  47. return _this;
  48. }
  49. RenderSequenceImpl.prototype.registerRenderEngine = function registerRenderEngine(renderEngine) {
  50. this._engine = renderEngine;
  51. };
  52. /**
  53. * @implements RenderSequenceInternalAPI#triggerRenderSequence
  54. */
  55. RenderSequenceImpl.prototype.triggerRenderSequence = function triggerRenderSequence(options) {
  56. var _this2 = this;
  57. this._currentRenderContext = {};
  58. this._s12yStartRenderSequence(options);
  59. return this._engine.process(options).then(function (result) {
  60. _this2._s12yResolveRenderSequence(options);
  61. return result;
  62. }).catch(function (error) {
  63. _this2._s12yResolveRenderSequence(options);
  64. throw error;
  65. });
  66. };
  67. /**
  68. * @private
  69. * @function _s12yStartRenderSequence
  70. * @description Start tracking the widget render time by creating a current render object
  71. * @param {Object} options
  72. * @param {number} options.renderId - the current render ID that is being executed
  73. */
  74. RenderSequenceImpl.prototype._s12yStartRenderSequence = function _s12yStartRenderSequence(options) {
  75. try {
  76. var contentInfo = this._s12yAPI.getContentInfo();
  77. if (contentInfo) {
  78. var s12ySQLInfo = contentInfo.getData(RenderSequenceImpl.S12Y_SQL_INFO);
  79. if (!s12ySQLInfo) {
  80. //TODO:Seems out of place to access DataQueryExecution inside render sequence
  81. //see if there is a better way to access this
  82. //ServiceabilitySQLInfo could be used in other render tasks in theory
  83. var queryExecution = this.content.getFeature('DataQueryExecution');
  84. var visApi = this.content.getFeature('WidgetAPI.deprecated').getVisApi();
  85. s12ySQLInfo = new ServiceabilitySQLInfo(visApi, queryExecution);
  86. contentInfo.setData(RenderSequenceImpl.S12Y_SQL_INFO, s12ySQLInfo);
  87. }
  88. var s12yRenderingInfo = contentInfo.getData(RenderSequenceImpl.S12Y_RENDERING_INFO);
  89. if (!s12yRenderingInfo) {
  90. s12yRenderingInfo = new ServiceabilityRenderingInfo(this._logger);
  91. contentInfo.setData(RenderSequenceImpl.S12Y_RENDERING_INFO, s12yRenderingInfo);
  92. }
  93. var renderingInfo = s12yRenderingInfo.getCurrentRendering();
  94. if (renderingInfo === undefined) {
  95. renderingInfo = new RenderingInfo({ renderId: options.renderId });
  96. s12yRenderingInfo.setCurrentRendering(renderingInfo);
  97. } else {
  98. renderingInfo.registerSequenceId(options.renderId);
  99. }
  100. } else {
  101. this._logger.info('Serviceability feature is not enabled');
  102. }
  103. } catch (error) {
  104. this._logger.error('Failed to track RenderingInfo for renderId [' + options.renderId + ']', error);
  105. }
  106. };
  107. /**
  108. * @private
  109. * @function s12yResolveRenderSequence
  110. * @description Resolve the tracking for RenderInfo
  111. * @param {Object} options
  112. * @param {number} options.renderId - the current render ID that is being executed
  113. */
  114. RenderSequenceImpl.prototype._s12yResolveRenderSequence = function _s12yResolveRenderSequence(options) {
  115. try {
  116. var contentInfo = this._s12yAPI.getContentInfo();
  117. if (contentInfo) {
  118. var s12yRenderingInfo = contentInfo.getData(RenderSequenceImpl.S12Y_RENDERING_INFO);
  119. var renderingInfo = s12yRenderingInfo.getCurrentRendering();
  120. if (renderingInfo && renderingInfo.getLastSequenceId() === options.renderId) {
  121. renderingInfo.setEndTime(Date.now());
  122. if (renderingInfo.isWithData()) {
  123. s12yRenderingInfo.setLastRendering(renderingInfo);
  124. }
  125. s12yRenderingInfo.setCurrentRendering(undefined);
  126. }
  127. }
  128. } catch (error) {
  129. this._logger.error('Failed to track RenderingInfo for renderId [' + options.renderId + ']', error);
  130. }
  131. };
  132. RenderSequenceImpl.prototype.getCurrentRenderContext = function getCurrentRenderContext(taskId) {
  133. return this._currentRenderContext[taskId];
  134. };
  135. /**
  136. * TODO: remove the call to _isStepComplete as a task should be processed only when it needs
  137. * @implements RenderSequenceInternalAPI#startTaskExecution
  138. */
  139. RenderSequenceImpl.prototype.startTaskExecution = function startTaskExecution(taskInfo) {
  140. var taskId = taskInfo.task.instance.getId();
  141. try {
  142. if (taskInfo.task.instance._isStepComplete(taskInfo.renderContext, taskId) === true) {
  143. this._logger.info('execution of task [' + taskId + '] is ignored for s12y as it is already complete');
  144. } else {
  145. this._setSQLFetchParams(taskInfo.renderContext);
  146. var taskRenderContext = this._createTaskRenderContext(taskInfo.renderContext);
  147. this.invokeCallbacks(RenderSequenceImpl.START_TASK_EXECUTION, { renderContext: taskRenderContext, taskId: taskId });
  148. }
  149. } catch (error) {
  150. this._logger.error('fail to check if task [' + taskId + '] is complete', error);
  151. }
  152. return taskInfo.task.instance.process(taskInfo.renderContext);
  153. };
  154. /**
  155. * @implements RenderSequenceInternalAPI#resolveTaskExecution
  156. */
  157. RenderSequenceImpl.prototype.resolveTaskExecution = function resolveTaskExecution(taskInfo) {
  158. var taskId = taskInfo.task.instance.getId();
  159. var taskRenderContext = this._createTaskRenderContext(taskInfo.renderContext);
  160. this.invokeCallbacks(RenderSequenceImpl.RESOLVE_TASK_EXECUTION, { renderContext: taskRenderContext, taskId: taskId });
  161. taskInfo.taskExecution.resolve();
  162. this._currentRenderContext[taskInfo.task.id] = taskRenderContext;
  163. };
  164. /**
  165. * @implements RenderSequenceInternalAPI#rejectTaskExecution
  166. */
  167. RenderSequenceImpl.prototype.rejectTaskExecution = function rejectTaskExecution(taskInfo) {
  168. var taskRenderContext = this._createTaskRenderContext(taskInfo.renderContext);
  169. this.invokeCallbacks(RenderSequenceImpl.REJECT_TASK_EXECUTION, { error: taskInfo.error, renderContext: taskRenderContext, taskId: taskInfo.task.instance.getId() });
  170. taskInfo.taskExecution.reject(taskInfo.error);
  171. this._currentRenderContext[taskInfo.task.id] = taskRenderContext;
  172. };
  173. /**
  174. * @implements RenderSequenceAPI#onStartTaskExecution
  175. */
  176. RenderSequenceImpl.prototype.onStartTaskExecution = function onStartTaskExecution(method) {
  177. this.registerCallback(RenderSequenceImpl.START_TASK_EXECUTION, method);
  178. };
  179. /**
  180. * @implements RenderSequenceAPI#onSuccessEndTaskExecution
  181. */
  182. RenderSequenceImpl.prototype.onResolveTaskExecution = function onResolveTaskExecution(method) {
  183. this.registerCallback(RenderSequenceImpl.RESOLVE_TASK_EXECUTION, method);
  184. };
  185. /**
  186. * @implements RenderSequenceAPI#onFailureEndTaskExecution
  187. */
  188. RenderSequenceImpl.prototype.onRejectTaskExecution = function onRejectTaskExecution(method) {
  189. this.registerCallback(RenderSequenceImpl.REJECT_TASK_EXECUTION, method);
  190. };
  191. /**
  192. * @implements RenderSequenceAPI#registerRenderStepProvider
  193. */
  194. RenderSequenceImpl.prototype.registerRenderStepProvider = function registerRenderStepProvider(provider) {
  195. if (provider) {
  196. if (typeof provider.getRenderStepList !== 'function') {
  197. throw new Error('the provide must implement "getRenderStepList()" ');
  198. }
  199. this._renderStepProviders.push(provider);
  200. }
  201. };
  202. /**
  203. * @implements RenderSequenceAPI#getProvidersRenderStepList
  204. */
  205. RenderSequenceImpl.prototype.getProvidersRenderStepList = function getProvidersRenderStepList() {
  206. var _this3 = this;
  207. var steps = [];
  208. this._renderStepProviders.forEach(function (provider) {
  209. try {
  210. var extraSteps = provider.getRenderStepList();
  211. if (Array.isArray(extraSteps)) {
  212. steps.push.apply(steps, extraSteps);
  213. } else {
  214. _this3._logger.warn('Provide render steps are ignored. The render step provider did not return an array. ');
  215. }
  216. } catch (e) {
  217. _this3._logger.error('An error while getting the render step list from the provider', e);
  218. }
  219. });
  220. return steps;
  221. };
  222. /**
  223. * creates an instance of RenderContext with the API method of {@link RenderContextAPI}
  224. * @param {Object} renderContext - sequence renderContext
  225. */
  226. RenderSequenceImpl.prototype._createTaskRenderContext = function _createTaskRenderContext(renderContext) {
  227. var renderContextImpl = new RenderContextImpl({ logger: this._logger, renderContext: renderContext });
  228. var api = APIFactory.createAPI(renderContextImpl, [RenderContextAPI]);
  229. return api;
  230. };
  231. /**
  232. * Callback to task execution start
  233. * @param {RenderContextAPI} payload
  234. */
  235. RenderSequenceImpl.prototype.s12yOnStartTaskExecution = function s12yOnStartTaskExecution(payload) {
  236. var s12yInfo = this._s12yAPI.getContentInfo();
  237. if (!s12yInfo) {
  238. this._logger.info('Serviceability feature is not enabled');
  239. } else {
  240. var sequenceId = payload.renderContext.getSequenceId();
  241. var renderingInfo = s12yInfo.getData(RenderSequenceImpl.S12Y_RENDERING_INFO);
  242. var currentRender = renderingInfo.getCurrentRendering();
  243. if (currentRender) {
  244. currentRender.setWithData(true);
  245. var renderSequenceInfo = currentRender.getRenderSequenceWithData();
  246. if (this._isNewerSequence(sequenceId, renderSequenceInfo)) {
  247. renderSequenceInfo = new RenderSequenceInfo({ id: sequenceId });
  248. renderSequenceInfo.addTaskInfo({ taskId: payload.taskId });
  249. currentRender.setRenderSequenceWithData(renderSequenceInfo);
  250. }
  251. }
  252. }
  253. };
  254. /**
  255. * Callback to task resolution
  256. * TODO: introduce a generic way to get task providing their own result
  257. * @param {RenderContextAPI} payload
  258. */
  259. RenderSequenceImpl.prototype.s12yOnResolveTaskExecution = function s12yOnResolveTaskExecution(payload) {
  260. var taskExecInfo = this._setTaskExecEndTime(payload);
  261. this._setQueryFeedbackSQLResult(payload.renderContext.getData(payload.taskId));
  262. if (taskExecInfo) {
  263. this._setDataResult(taskExecInfo, payload.renderContext.getData(payload.taskId));
  264. }
  265. };
  266. /**
  267. * Callback to task rejection
  268. * TODO: remove the assumption the task is a data task
  269. * @param {RenderContextAPI} payload
  270. */
  271. RenderSequenceImpl.prototype.s12yOnRejectTaskExecution = function s12yOnRejectTaskExecution(payload) {
  272. var taskExecInfo = this._setTaskExecEndTime(payload);
  273. if (taskExecInfo) {
  274. this._setTaskExecError(taskExecInfo, payload.error);
  275. }
  276. };
  277. RenderSequenceImpl.prototype._setQueryFeedbackSQLResult = function _setQueryFeedbackSQLResult(data) {
  278. var contentInfo = this._s12yAPI.getContentInfo();
  279. if (contentInfo) {
  280. var sqlInfo = contentInfo.getData(RenderSequenceImpl.S12Y_SQL_INFO);
  281. if (!_.isEmpty(data)) {
  282. data.getQueryResultIdList().forEach(function (id) {
  283. var queryResult = data.getResult(id);
  284. sqlInfo.widgetsLastCognosQuery = queryResult.getPropertyValue('QueryFeedback.cognosSQL');
  285. sqlInfo.widgetsLastNativeQuery = queryResult.getPropertyValue('QueryFeedback.nativeSQL');
  286. sqlInfo.widgetsLastMDXQuery = queryResult.getPropertyValue('QueryFeedback.MDX');
  287. });
  288. }
  289. } else {
  290. this._logger.info('Serviceability feature is not enabled');
  291. }
  292. };
  293. RenderSequenceImpl.prototype._setSQLFetchParams = function _setSQLFetchParams(renderContext) {
  294. var contentInfo = this._s12yAPI.getContentInfo();
  295. if (contentInfo) {
  296. renderContext.extraInfo = renderContext.extraInfo || {};
  297. var sqlInfo = contentInfo.getData(RenderSequenceImpl.S12Y_SQL_INFO);
  298. if (sqlInfo.shouldFetchQuery) {
  299. renderContext.extraInfo.dataQueryParams = { qfb: 'nativeCommandText,nativeCommandType,CognosCommandText' };
  300. }
  301. } else {
  302. this._logger.info('Serviceability feature is not enabled');
  303. }
  304. };
  305. /**
  306. * @private
  307. * @param {integer} startedSequenceId
  308. * @param {RenderSequenceInfo} s12ySequenceInfo
  309. * @returns {boolean} true if s12ySequenceInfo is undefined or the startedSequenceId is greater than the s12ySequenceInfo one
  310. */
  311. RenderSequenceImpl.prototype._isNewerSequence = function _isNewerSequence(startedSequenceId, s12ySequenceInfo) {
  312. return !s12ySequenceInfo || startedSequenceId > s12ySequenceInfo.getId();
  313. };
  314. /**
  315. * sets the task end time if needed
  316. * @private
  317. * @param {RenderContextAPI} options - callback payload
  318. * @returns {RenderTaskExecInfo} - the task exec info or undefined if none is to be updated
  319. */
  320. RenderSequenceImpl.prototype._setTaskExecEndTime = function _setTaskExecEndTime(options) {
  321. var taskExecInfo = void 0;
  322. var s12yInfo = this._s12yAPI.getContentInfo();
  323. if (!s12yInfo) {
  324. this._logger.info('Serviceability feature is not enabled');
  325. } else {
  326. var sequenceId = options.renderContext.getSequenceId();
  327. var s12yRenderingInfo = s12yInfo.getData(RenderSequenceImpl.S12Y_RENDERING_INFO);
  328. var currentRenderInfo = s12yRenderingInfo.getCurrentRendering();
  329. if (currentRenderInfo) {
  330. var renderSequenceInfo = currentRenderInfo.getRenderSequenceWithData();
  331. if (renderSequenceInfo && sequenceId === renderSequenceInfo.getId()) {
  332. taskExecInfo = renderSequenceInfo.getTaskInfo(options.taskId);
  333. taskExecInfo.setEndTime();
  334. } else {
  335. this._logger.info('s12y - setting end time - task [' + options.taskId + '] sequence ' + sequenceId + ' from is ignored by the registered s12y sequence info', renderSequenceInfo);
  336. }
  337. }
  338. }
  339. return taskExecInfo;
  340. };
  341. /**
  342. * creates an error object and sets it in the taskExecInfo
  343. * TODO: there should be only one logic to generate the error object; there is one in VisRenderSequence and one here
  344. * @param {RenderTaskExecInfo} taskExecInfo
  345. * @param {Object} error
  346. */
  347. RenderSequenceImpl.prototype._setTaskExecError = function _setTaskExecError(taskExecInfo, error) {
  348. var msg = 'dwErrorRenderingVisualization';
  349. if (error) {
  350. if (error.msg) {
  351. msg = error.msg;
  352. } else if (error.message) {
  353. msg = error.message;
  354. }
  355. }
  356. var errorInfo = error ? error.errorInfo : undefined;
  357. taskExecInfo.setError(new APIError({ msg: msg, params: { errorInfo: errorInfo } }));
  358. if (errorInfo && typeof errorInfo.getResponseHeader === 'function') {
  359. taskExecInfo.addRequestTimeInfo(errorInfo.getResponseHeader('x-ca-requesttime'));
  360. }
  361. };
  362. /**
  363. * set data result; create a data with a toJSON method to make sure to grab the values only when needed
  364. * @param {RenderTaskExecInfo} taskExecInfo
  365. * @param {QueryResultObject} data
  366. */
  367. RenderSequenceImpl.prototype._setDataResult = function _setDataResult(taskExecInfo, data) {
  368. if (taskExecInfo && !_.isEmpty(data)) {
  369. data.getQueryResultIdList().forEach(function (id) {
  370. var queryResult = data.getResult(id);
  371. var requestTime = queryResult.getPropertyValue('RequestTime.internal');
  372. taskExecInfo.addRequestTimeInfo(requestTime);
  373. });
  374. var taskResults = {
  375. toJSON: function toJSON() {
  376. var result = [];
  377. data.getQueryResultIdList().forEach(function (id) {
  378. var queryResult = data.getResult(id);
  379. result.push({
  380. 'spec': JSON.parse(queryResult.getPropertyValue('QuerySpec.internal')),
  381. 'data': JSON.parse(queryResult.getPropertyValue('RawData.internal')),
  382. requestTime: queryResult.getPropertyValue('RequestTime.internal')
  383. });
  384. });
  385. return result;
  386. }
  387. };
  388. taskExecInfo.setData('queryResults', taskResults);
  389. }
  390. };
  391. return RenderSequenceImpl;
  392. }(CallbackInvoker), _class.START_TASK_EXECUTION = 'startTaskExecution', _class.RESOLVE_TASK_EXECUTION = 'resolveTaskExecution', _class.REJECT_TASK_EXECUTION = 'rejectTaskExecution', _class.LAST_RENDER_WITH_DATA = 'lastRenderingWithDataRequest', _class.S12Y_RENDERING_INFO = 'ServiceabilityRenderingInfo', _class.S12Y_SQL_INFO = 'ServiceabilitySQLInfo', _temp);
  393. return RenderSequenceImpl;
  394. });
  395. //# sourceMappingURL=RenderSequenceImpl.js.map