ESPWorkunit.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. /*##############################################################################
  2. # HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. ############################################################################## */
  16. define([
  17. "dojo/_base/declare",
  18. "dojo/_base/array",
  19. "dojo/_base/lang",
  20. "dojo/_base/Deferred",
  21. "dojo/data/ObjectStore",
  22. "dojo/store/util/QueryResults",
  23. "dojo/store/Observable",
  24. "hpcc/WsWorkunits",
  25. "hpcc/ESPUtil",
  26. "hpcc/ESPResult"
  27. ], function (declare, arrayUtil, lang, Deferred, ObjectStore, QueryResults, Observable,
  28. WsWorkunits, ESPUtil, ESPResult) {
  29. var _workunits = {};
  30. var Store = declare(null, {
  31. idProperty: "Wuid",
  32. _watched: {},
  33. constructor: function (options) {
  34. declare.safeMixin(this, options);
  35. },
  36. getIdentity: function (object) {
  37. return object[this.idProperty];
  38. },
  39. get: function (id) {
  40. if (!_workunits[id]) {
  41. _workunits[id] = new Workunit({
  42. Wuid: id
  43. });
  44. _workunits[id].refresh();
  45. }
  46. return _workunits[id];
  47. },
  48. remove: function (item) {
  49. if (_workunits[this.getIdentity(item)]) {
  50. _workunits[this.getIdentity(item)].stopMonitor();
  51. delete _workunits[this.getIdentity(item)];
  52. }
  53. },
  54. query: function (query, options) {
  55. var request = {};
  56. lang.mixin(request, options.query);
  57. if (options.start)
  58. request['PageStartFrom'] = options.start;
  59. if (options.count)
  60. request['Count'] = options.count;
  61. if (options.sort) {
  62. request['Sortby'] = options.sort[0].attribute;
  63. request['Descending'] = options.sort[0].descending;
  64. }
  65. var results = WsWorkunits.WUQuery({
  66. request: request
  67. });
  68. var deferredResults = new Deferred();
  69. deferredResults.total = results.then(function (response) {
  70. if (lang.exists("WUQueryResponse.NumWUs", response)) {
  71. return response.WUQueryResponse.NumWUs;
  72. }
  73. return 0;
  74. });
  75. var context = this;
  76. Deferred.when(results, function (response) {
  77. var workunits = [];
  78. for (key in context._watched) {
  79. context._watched[key].unwatch();
  80. }
  81. this._watched = {};
  82. if (lang.exists("WUQueryResponse.Workunits.ECLWorkunit", response)) {
  83. arrayUtil.forEach(response.WUQueryResponse.Workunits.ECLWorkunit, function (item, index) {
  84. var wu = context.get(item.Wuid);
  85. wu.updateData(item);
  86. workunits.push(wu);
  87. context._watched[wu.Wuid] = wu.watch("changedCount", function (name, oldValue, newValue) {
  88. if (oldValue !== newValue) {
  89. context.notify(wu, wu.Wuid);
  90. }
  91. });
  92. });
  93. }
  94. deferredResults.resolve(workunits);
  95. });
  96. return QueryResults(deferredResults);
  97. }
  98. });
  99. var Workunit = declare([ESPUtil.Singleton, ESPUtil.Monitor], {
  100. // Asserts ---
  101. _assertHasWuid: function () {
  102. if (!this.Wuid) {
  103. throw new Error("Wuid cannot be empty.");
  104. }
  105. },
  106. // Attributes ---
  107. _StateIDSetter: function (StateID) {
  108. this.StateID = StateID;
  109. var actionEx = lang.exists("ActionEx", this) ? this.ActionEx : null;
  110. this.set("hasCompleted", WsWorkunits.isComplete(this.StateID, actionEx));
  111. },
  112. _VariablesSetter: function (Variables) {
  113. var variables = [];
  114. for (var i = 0; i < Variables.ECLResult.length; ++i) {
  115. context.variables.push(lang.mixin({
  116. ColumnType: Variables.ECLResult[i].ECLSchemas && Variables.ECLResult[i].ECLSchemas.ECLSchemaItem.length ? Variables.ECLResult[i].ECLSchemas.ECLSchemaItem[0].ColumnType : "unknown"
  117. }, variables[i]));
  118. }
  119. this.set("variables", variables);
  120. },
  121. _ResultsSetter: function (Results) {
  122. var results = [];
  123. for (var i = 0; i < Results.ECLResult.length; ++i) {
  124. results.push(ESPResult.Get(lang.mixin({ wu: this.wu, Wuid: this.Wuid }, Results.ECLResult[i])));
  125. }
  126. this.set("results", results);
  127. },
  128. _SourceFilesSetter: function (SourceFiles) {
  129. var sourceFiles = [];
  130. for (var i = 0; i < SourceFiles.ECLSourceFile.length; ++i) {
  131. sourceFiles.push(ESPResult.Get(lang.mixin({ wu: this.wu, Wuid: this.Wuid }, SourceFiles.ECLSourceFile[i])));
  132. }
  133. this.set("sourceFiles", sourceFiles);
  134. },
  135. _TimersSetter: function (Timers) {
  136. var timers = [];
  137. for (var i = 0; i < Timers.ECLTimer.length; ++i) {
  138. var timeParts = Timers.ECLTimer[i].Value.split(":");
  139. var secs = 0;
  140. for (var j = 0; j < timeParts.length; ++j) {
  141. secs = secs * 60 + timeParts[j] * 1;
  142. }
  143. timers.push(lang.mixin(Timers.ECLTimer[i], {
  144. Seconds: Math.round(secs * 1000) / 1000,
  145. HasSubGraphId: Timers.ECLTimer[i].SubGraphId && Timers.ECLTimer[i].SubGraphId != "" ? true : false
  146. }));
  147. }
  148. this.set("timers", timers);
  149. },
  150. _GraphsSetter: function (Graphs) {
  151. this.set("graphs", Graphs.ECLGraph);
  152. },
  153. // --- --- ---
  154. onCreate: function () {
  155. },
  156. onUpdate: function () {
  157. },
  158. onSubmit: function () {
  159. },
  160. constructor: function (args) {
  161. this.inherited(arguments);
  162. declare.safeMixin(this, args);
  163. this.wu = this;
  164. },
  165. isComplete: function () {
  166. return this.hasCompleted;
  167. },
  168. monitor: function (callback) {
  169. if (this.hasCompleted) {
  170. if (callback) {
  171. callback(this);
  172. }
  173. } else {
  174. var context = this;
  175. this.watch("changedCount", function (name, oldValue, newValue) {
  176. if (oldValue !== newValue && newValue) {
  177. if (callback) {
  178. callback(context);
  179. }
  180. }
  181. });
  182. }
  183. },
  184. create: function (ecl) {
  185. var context = this;
  186. WsWorkunits.WUCreate({
  187. load: function (response) {
  188. _workunits[response.WUCreateResponse.Workunit.Wuid] = context
  189. context.updateData(response.WUCreateResponse.Workunit);
  190. context.onCreate();
  191. }
  192. });
  193. },
  194. update: function (request, appData) {
  195. this._assertHasWuid();
  196. lang.mixin(request, {
  197. Wuid: this.Wuid
  198. });
  199. lang.mixin(request, {
  200. StateOrig: this.State,
  201. JobnameOrig: this.Jobname,
  202. DescriptionOrig: this.Description,
  203. ProtectedOrig: this.Protected,
  204. ScopeOrig: this.Scope,
  205. ClusterOrig: this.Cluster,
  206. ApplicationValues: appData
  207. });
  208. var context = this;
  209. WsWorkunits.WUUpdate({
  210. request: request,
  211. load: function (response) {
  212. context.updateData(response.WUUpdateResponse.Workunit);
  213. context.onUpdate();
  214. }
  215. });
  216. },
  217. submit: function (target) {
  218. this._assertHasWuid();
  219. var context = this;
  220. WsWorkunits.WUSubmit({
  221. request: {
  222. Wuid: this.Wuid,
  223. Cluster: target
  224. },
  225. load: function (response) {
  226. context.onSubmit();
  227. }
  228. });
  229. },
  230. _resubmit: function (clone, resetWorkflow) {
  231. this._assertHasWuid();
  232. var context = this;
  233. WsWorkunits.WUResubmit({
  234. request: {
  235. Wuids: this.Wuid,
  236. CloneWorkunit: clone,
  237. ResetWorkflow: resetWorkflow
  238. },
  239. load: function (response) {
  240. context.refresh();
  241. }
  242. });
  243. },
  244. clone: function () {
  245. this._resubmit(true, false);
  246. },
  247. resubmit: function () {
  248. this._resubmit(false, false);
  249. },
  250. restart: function () {
  251. this._resubmit(false, true);
  252. },
  253. _action: function (action) {
  254. this._assertHasWuid();
  255. var context = this;
  256. WsWorkunits.WUAction([{ Wuid: this.Wuid }], action, {
  257. load: function (response) {
  258. context.refresh();
  259. }
  260. });
  261. },
  262. setToFailed: function () {
  263. this._action("setToFailed");
  264. },
  265. abort: function () {
  266. this._action("Abort");
  267. },
  268. doDelete: function () {
  269. this._action("Delete");
  270. },
  271. publish: function (jobName) {
  272. this._assertHasWuid();
  273. var context = this;
  274. WsWorkunits.WUPublishWorkunit({
  275. request: {
  276. Wuid: this.Wuid,
  277. JobName: jobName,
  278. Activate: 1,
  279. UpdateWorkUnitName: 1,
  280. Wait: 5000
  281. },
  282. load: function (response) {
  283. context.updateData(response.WUPublishWorkunitResponse);
  284. }
  285. });
  286. },
  287. refresh: function (full) {
  288. if (full) {
  289. this.getInfo({
  290. onGetText: function () {
  291. },
  292. onGetWUExceptions: function () {
  293. },
  294. onGetGraphs: function () {
  295. },
  296. onGetSourceFiles: function () {
  297. },
  298. onGetResults: function () {
  299. },
  300. onGetVariables: function () {
  301. },
  302. onGetTimers: function () {
  303. },
  304. onGetApplicationValues: function () {
  305. }
  306. });
  307. } else {
  308. this.getQuery();
  309. }
  310. },
  311. getQuery: function () {
  312. this._assertHasWuid();
  313. var context = this;
  314. WsWorkunits.WUQuery({
  315. request: {
  316. Wuid: this.Wuid,
  317. },
  318. load: function (response) {
  319. if (lang.exists("WUQueryResponse.Workunits.ECLWorkunit", response)) {
  320. arrayUtil.forEach(response.WUQueryResponse.Workunits.ECLWorkunit, function (item, index) {
  321. context.updateData(item);
  322. });
  323. }
  324. }
  325. });
  326. },
  327. getInfo: function (args) {
  328. this._assertHasWuid();
  329. var context = this;
  330. WsWorkunits.WUInfo({
  331. request: {
  332. Wuid: this.Wuid,
  333. TruncateEclTo64k: args.onGetText ? false : true,
  334. IncludeExceptions: args.onGetWUExceptions ? true : false,
  335. IncludeGraphs: args.onGetGraphs ? true : false,
  336. IncludeSourceFiles: args.onGetSourceFiles ? true : false,
  337. IncludeResults: args.onGetResults ? true : false,
  338. IncludeResultsViewNames: false,
  339. IncludeVariables: args.onGetVariables ? true : false,
  340. IncludeTimers: args.onGetTimers ? true : false,
  341. IncludeDebugValues: false,
  342. IncludeApplicationValues: args.onGetApplicationValues ? true : false,
  343. IncludeWorkflows: false,
  344. IncludeXmlSchemas: args.onGetResults ? true : false,
  345. SuppressResultSchemas: args.onGetResults ? false : true
  346. },
  347. load: function (response) {
  348. if (lang.exists("WUInfoResponse.Workunit", response)) {
  349. if (!args.onGetText && lang.exists("WUInfoResponse.Workunit.Query", response)) {
  350. // A truncated version of ECL just causes issues ---
  351. delete response.WUInfoResponse.Workunit.Query;
  352. }
  353. context.updateData(response.WUInfoResponse.Workunit);
  354. if (args.onGetText && lang.exists("Query.Text", context)) {
  355. args.onGetText(context.Query.Text);
  356. }
  357. if (args.onGetWUExceptions && lang.exists("Exceptions.ECLException", context)) {
  358. args.onGetWUExceptions(context.Exceptions.ECLException);
  359. }
  360. if (args.onGetApplicationValues && lang.exists("ApplicationValues.ApplicationValue", context)) {
  361. args.onGetApplicationValues(context.ApplicationValues.ApplicationValue)
  362. }
  363. if (args.onGetVariables && lang.exists("variables", context)) {
  364. args.onGetVariables(context.variables);
  365. }
  366. if (args.onGetResults && lang.exists("results", context)) {
  367. args.onGetResults(context.results);
  368. }
  369. if (args.onGetSourceFiles && lang.exists("sourceFiles", context)) {
  370. args.onGetSourceFiles(context.sourceFiles);
  371. }
  372. if (args.onGetTimers && lang.exists("timers", context)) {
  373. args.onGetTimers(context.timers);
  374. }
  375. if (args.onGetGraphs && lang.exists("graphs", context)) {
  376. if (context.timers || lang.exists("ApplicationValues.ApplicationValue", context)) {
  377. for (var i = 0; i < context.graphs.length; ++i) {
  378. if (context.timers) {
  379. context.graphs[i].Time = 0;
  380. for (var j = 0; j < context.timers.length; ++j) {
  381. if (context.timers[j].GraphName == context.graphs[i].Name) {
  382. context.graphs[i].Time += context.timers[j].Seconds;
  383. }
  384. context.graphs[i].Time = Math.round(context.graphs[i].Time * 1000) / 1000;
  385. }
  386. }
  387. if (lang.exists("ApplicationValues.ApplicationValue", context)) {
  388. var idx = context.getApplicationValueIndex("ESPWorkunit.js", context.graphs[i].Name + "_SVG");
  389. if (idx >= 0) {
  390. context.graphs[i].svg = context.ApplicationValues.ApplicationValue[idx].Value;
  391. }
  392. }
  393. }
  394. }
  395. args.onGetGraphs(context.graphs)
  396. }
  397. if (args.onAfterSend) {
  398. args.onAfterSend(context);
  399. }
  400. }
  401. }
  402. });
  403. },
  404. getGraphIndex: function (name) {
  405. for (var i = 0; i < this.graphs.length; ++i) {
  406. if (this.graphs[i].Name == name) {
  407. return i;
  408. }
  409. }
  410. return -1;
  411. },
  412. getApplicationValueIndex: function (application, name) {
  413. if (lang.exists("ApplicationValues.ApplicationValue", this)) {
  414. for (var i = 0; i < this.ApplicationValues.ApplicationValue.length; ++i) {
  415. if (this.ApplicationValues.ApplicationValue[i].Application == application && this.ApplicationValues.ApplicationValue[i].Name == name) {
  416. return i;
  417. }
  418. }
  419. }
  420. return -1;
  421. },
  422. getState: function () {
  423. return this.State;
  424. },
  425. getStateIconClass: function () {
  426. switch (this.StateID) {
  427. case 1:
  428. case 3:
  429. return "iconCompleted";
  430. case 2:
  431. case 11:
  432. case 15:
  433. return "iconRunning";
  434. case 4:
  435. case 7:
  436. return "iconFailed";
  437. case 5:
  438. case 8:
  439. case 10:
  440. case 12:
  441. case 13:
  442. case 14:
  443. case 16:
  444. return "iconArchived";
  445. case 6:
  446. return "iconAborting";
  447. case 9:
  448. return "iconSubmitted";
  449. case 999:
  450. return "iconDeleted";
  451. }
  452. return "iconWorkunit";
  453. },
  454. getStateImage: function () {
  455. switch (this.StateID) {
  456. case 1:
  457. return "img/workunit_completed.png";
  458. case 2:
  459. return "img/workunit_running.png";
  460. case 3:
  461. return "img/workunit_completed.png";
  462. case 4:
  463. return "img/workunit_failed.png";
  464. case 5:
  465. return "img/workunit_warning.png";
  466. case 6:
  467. return "img/workunit_aborting.png";
  468. case 7:
  469. return "img/workunit_failed.png";
  470. case 8:
  471. return "img/workunit_warning.png";
  472. case 9:
  473. return "img/workunit_submitted.png";
  474. case 10:
  475. return "img/workunit_warning.png";
  476. case 11:
  477. return "img/workunit_running.png";
  478. case 12:
  479. return "img/workunit_warning.png";
  480. case 13:
  481. return "img/workunit_warning.png";
  482. case 14:
  483. return "img/workunit_warning.png";
  484. case 15:
  485. return "img/workunit_running.png";
  486. case 16:
  487. return "img/workunit_warning.png";
  488. case 999:
  489. return "img/workunit_deleted.png";
  490. }
  491. return "img/workunit.png";
  492. },
  493. getProtectedImage: function () {
  494. if (this.Protected) {
  495. return "img/locked.png"
  496. }
  497. return "img/unlocked.png"
  498. },
  499. fetchText: function (onFetchText) {
  500. var context = this;
  501. if (lang.exists("Query.Text", context)) {
  502. onFetchText(this.Query.Text);
  503. return;
  504. }
  505. this.getInfo({
  506. onGetText: onFetchText
  507. });
  508. },
  509. fetchXML: function (onFetchXML) {
  510. if (this.xml) {
  511. onFetchXML(this.xml);
  512. return;
  513. }
  514. this._assertHasWuid();
  515. var context = this;
  516. WsWorkunits.WUFile({
  517. request: {
  518. Wuid: this.Wuid,
  519. Type: "XML"
  520. },
  521. load: function (response) {
  522. context.xml = response;
  523. onFetchXML(response);
  524. }
  525. });
  526. },
  527. fetchResults: function (onFetchResults) {
  528. if (this.results && this.results.length) {
  529. onFetchResults(this.results);
  530. return;
  531. }
  532. this.getInfo({
  533. onGetResults: onFetchResults
  534. });
  535. },
  536. fetchTimers: function (onFetchTimers) {
  537. if (this.timers && this.timers.length) {
  538. onFetchTimers(this.timers);
  539. return;
  540. }
  541. this.getInfo({
  542. onGetTimers: onFetchTimers
  543. });
  544. },
  545. fetchGraphs: function (onFetchGraphs) {
  546. if (this.graphs && this.graphs.length) {
  547. onFetchGraphs(this.graphs);
  548. return;
  549. }
  550. this.getInfo({
  551. onGetGraphs: onFetchGraphs
  552. });
  553. },
  554. fetchGraphXgmmlByName: function (name, onFetchGraphXgmml) {
  555. var idx = this.getGraphIndex(name);
  556. if (idx >= 0) {
  557. this.fetchGraphXgmml(idx, onFetchGraphXgmml);
  558. }
  559. },
  560. fetchGraphXgmml: function (idx, onFetchGraphXgmml) {
  561. this._assertHasWuid();
  562. var context = this;
  563. WsWorkunits.WUGetGraph({
  564. request: {
  565. Wuid: this.Wuid,
  566. GraphName: this.graphs[idx].Name
  567. },
  568. load: function (response) {
  569. context.graphs[idx].xgmml = response.WUGetGraphResponse.Graphs.ECLGraphEx[0].Graph;
  570. onFetchGraphXgmml(context.graphs[idx].xgmml, context.graphs[idx].svg);
  571. }
  572. });
  573. },
  574. setGraphSvg: function (graphName, svg) {
  575. var idx = this.getGraphIndex(graphName);
  576. if (idx >= 0) {
  577. this.graphs[idx].svg = svg;
  578. var appData = [];
  579. appData[graphName + "_SVG"] = svg;
  580. this.update({}, appData);
  581. }
  582. }
  583. });
  584. return {
  585. Create: function (params) {
  586. retVal = new Workunit(params);
  587. retVal.create();
  588. return retVal;
  589. },
  590. Get: function (wuid) {
  591. var store = new Store();
  592. return store.get(wuid);
  593. },
  594. CreateWUQueryObjectStore: function (options) {
  595. var store = new Store(options);
  596. store = Observable(store);
  597. var objStore = new ObjectStore({ objectStore: store });
  598. return objStore;
  599. }
  600. };
  601. });