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