blob: cc7d222fd509976403cbad462d143b6b4349121f [file] [log] [blame]
Illyoung Choi59820ed2019-06-24 17:01:00 -07001/*
2 * Copyright 2019-present Open Networking Foundation
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
17
18(function () {
19 'use strict';
20
21 const _ = require('lodash');
22 const logger = require('../config/logger.js');
23 const Client = require('../types/client.js');
24 const WorkflowRun = require('../types/workflowrun.js');
Illyoung Choi16c6d4f2019-07-24 18:09:26 -070025 const ws_probe = require('./ws_probe.js');
Illyoung Choi59820ed2019-06-24 17:01:00 -070026 const ws_manager = require('./ws_manager.js');
27 const ws_workflowrun = require('./ws_workflowrun.js');
28
29 let allClients = {}; // has publishers and subscribers
30 let probeClients = {}; // a subset of clients
31 let workflowManagerClients = {}; // a subset of clients
32 let workflowRunClients = {}; // a subset of clients
33
34 //let io;
35
36 // key: workflow id
37 // value: Workflow instance
38 let workflows = {};
39
40 // key: workflow run id
41 // value: WorkflowRun instance
42 let workflowRuns = {};
43
44 let serviceEvents = {
45 GREETING: 'cord.workflow.ctlsvc.greeting'
46 };
47
Illyoung Choi16c6d4f2019-07-24 18:09:26 -070048 // add ws_probe events
49 _.forOwn(ws_probe.serviceEvents, (wsServiceEvent, key) => {
50 serviceEvents[key] = wsServiceEvent;
51 });
52
53 // add ws_manager events
Illyoung Choi59820ed2019-06-24 17:01:00 -070054 _.forOwn(ws_manager.serviceEvents, (wsServiceEvent, key) => {
55 serviceEvents[key] = wsServiceEvent;
56 });
57
Illyoung Choi16c6d4f2019-07-24 18:09:26 -070058 // add ws_workflowrun events
Illyoung Choi59820ed2019-06-24 17:01:00 -070059 _.forOwn(ws_workflowrun.serviceEvents, (wsServiceEvent, key) => {
60 serviceEvents[key] = wsServiceEvent;
61 });
62
63 //const setIO = (ioInstance) => {
64 // io = ioInstance;
65 //};
66
Illyoung Choie3ce4cf2019-06-28 11:07:47 -070067 const checkObject = (obj) => {
68 return Object.prototype.toString.call(obj) === '[object Object]';
69 };
70
Illyoung Choi59820ed2019-06-24 17:01:00 -070071 const destroy = () => {
72 removeClients();
73 clearWorkflowRuns();
74 clearWorkflows();
75 };
76
77 const listWorkflows = () => {
78 let workflowList = [];
79 _.forOwn(workflows, (_workflow, workflowId) => {
80 workflowList.push(workflowId);
81 });
82 return workflowList;
83 };
84
85 const checkWorkflow = (workflowId) => {
86 if(workflowId in workflows) {
87 return true;
88 }
89 return false;
90 };
91
92 const addWorkflow = (workflow) => {
93 if(workflow.getId() in workflows) {
94 logger.log('error', `there exists a workflow with the same id - ${workflow.getId()}`);
95 return false;
96 }
97
98 let workflowId = workflow.getId();
99 workflows[workflowId] = workflow;
100 return true;
101 };
102
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700103 const getWorkflow = (workflowId) => {
104 if(workflowId in workflows) {
105 logger.log('warn', `cannot find a workflow with id - ${workflowId}`);
106 return null;
107 }
108
109 return workflows[workflowId];
110 };
111
Illyoung Choi59820ed2019-06-24 17:01:00 -0700112 const clearWorkflows = () => {
113 _.forOwn(workflows, (_workflow, workflowId) => {
114 delete workflows[workflowId];
115 });
116 };
117
118 const listWorkflowRuns = () => {
119 let workflowRunList = [];
120 _.forOwn(workflowRuns, (_workflowRun, workflowRunId) => {
121 workflowRunList.push(workflowRunId);
122 });
123 return workflowRunList;
124 };
125
126 const checkWorkflowRun = (workflowRunId) => {
127 if(workflowRunId in workflowRuns) {
128 return true;
129 }
130 return false;
131 };
132
133 const addWorkflowRun = (workflowRun) => {
134 let workflowId = workflowRun.getWorkflowId();
135 let workflowRunId = workflowRun.getId();
136
137 if(workflowRunId in workflowRuns) {
138 logger.log('warn', `there exists a workflow run with the same id - ${workflowRunId}`);
139 return false;
140 }
141
142 if(!(workflowId in workflows)) {
143 logger.log('warn', `cannot find a workflow with id - ${workflowId}`);
144 return false;
145 }
146
147 workflowRuns[workflowRunId] = workflowRun;
148 return true;
149 };
150
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700151 const getWorkflowRun = (workflowRunId) => {
152 if(workflowRunId in workflowRuns) {
153 logger.log('warn', `cannot find a workflow run with id - ${workflowRunId}`);
154 return null;
155 }
156
157 return workflowRuns[workflowRunId];
158 };
159
Illyoung Choi59820ed2019-06-24 17:01:00 -0700160 const clearWorkflowRuns = () => {
161 _.forOwn(workflowRuns, (_workflowRun, workflowRunId) => {
162 delete workflowRuns[workflowRunId];
163 });
164 };
165
166 const updateWorkflowRunStatus = (workflowRunId, taskId, status) => {
167 if(!(workflowRunId in workflowRuns)) {
168 logger.log('warn', `cannot find a workflow run with the id - ${workflowRunId}`);
169 return false;
170 }
171
172 let workflowRun = workflowRuns[workflowRunId];
173 workflowRun.updateTaskStatus(taskId, status);
174 return true;
175 };
176
177 const setWorkflowRunKickstarted = (workflowRunId) => {
178 if(!(workflowRunId in workflowRuns)) {
179 logger.log('warn', `cannot find a workflow run with the id - ${workflowRunId}`);
180 return false;
181 }
182
183 let workflowRun = workflowRuns[workflowRunId];
184 workflowRun.setKickstarted();
185 return true;
186 };
187
Illyoung Choic707c052019-07-18 13:50:49 -0700188 const setWorkflowRunState = (workflowRunId, state) => {
189 if(!(workflowRunId in workflowRuns)) {
190 logger.log('warn', `cannot find a workflow run with the id - ${workflowRunId}`);
191 return false;
192 }
193
194 if(state in ['success', 'failed', 'end']) {
195 removeWorkflowRun(workflowRunId);
196 }
197 return true;
198 };
199
Illyoung Choi59820ed2019-06-24 17:01:00 -0700200 const kickstart = (workflowId, workflowRunId) => {
201 if(!(workflowId in workflows)) {
202 logger.log('warn', `cannot find a workflow with the id - ${workflowId}`);
203 return false;
204 }
205
206 if(!(workflowRunId in workflowRuns)) {
207 logger.log('warn', `cannot find a workflow run with the id - ${workflowRunId}`);
208 return false;
209 }
210
211 ws_manager.kickstartWorkflow(workflowId, workflowRunId);
Illyoung Choic707c052019-07-18 13:50:49 -0700212 return true;
Illyoung Choi59820ed2019-06-24 17:01:00 -0700213 };
214
215 const removeWorkflow = (workflowId) => {
216 if(!(workflowId in workflows)) {
217 logger.log('warn', `cannot find a workflow with the id - ${workflowId}`);
218 return false;
219 }
220
221 // check if there are workflow runs
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700222 for(let key in workflowRuns) {
223 if (!workflowRuns.hasOwnProperty(key)) {
224 continue;
225 }
226
227 let workflowRun = workflowRuns[key];
Illyoung Choi59820ed2019-06-24 17:01:00 -0700228 if(workflowRun.getWorkflowId() === workflowId) {
229 logger.log('warn', `there exists a workflow run for a workflow id - ${workflowId}`);
230 return false;
231 }
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700232 }
233
234 // we don't use below code becuase it cannot properly stop and return value with 'return'
235 // _.forOwn(workflowRuns, (workflowRun, _workflowRunId) => {
236 // if(workflowRun.getWorkflowId() === workflowId) {
237 // logger.log('warn', `there exists a workflow run for a workflow id - ${workflowId}`);
238 // return false;
239 // }
240 // });
Illyoung Choi59820ed2019-06-24 17:01:00 -0700241
242 delete workflows[workflowId];
243 return true;
244 };
245
246 const removeWorkflowRun = (workflowRunId) => {
247 if(!(workflowRunId in workflowRuns)) {
248 logger.log('warn', `cannot find a workflow run with the id - ${workflowRunId}`);
249 return false;
250 }
251
252 let workflowRun = workflowRuns[workflowRunId];
253 delete workflowRuns[workflowRunId];
254
255 workflowRun.setFinished();
256 return true;
257 };
258
Illyoung Choi16c6d4f2019-07-24 18:09:26 -0700259 const emitEvent = (topic, message) => {
Illyoung Choi59820ed2019-06-24 17:01:00 -0700260 // list of workflowIds
261 // to check if there are workflow runs for the events
262 let workflowIdsRunning = [];
263
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700264 logger.log('debug', `event is raised : topic ${topic}, message ${JSON.stringify(message)}`);
265
Illyoung Choi59820ed2019-06-24 17:01:00 -0700266 // route event to running instances
267 _.forOwn(workflowRuns, (workflowRun, workflowRunId) => {
268 let workflowId = workflowRun.getWorkflowId();
269 let workflow = workflows[workflowId];
270
271 // event will be routed to workflow runs that meet following criteria
272 // 1) the workflow is currently interested in the same topic
273 // (already finished tasks are not counted)
274 // 2) the task's key field and value
275 if(workflowRun.isEventAcceptable(workflow, topic, message)) {
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700276 //console.log(`event ${topic} is routed to workflow run ${workflowRunId}`);
Illyoung Choi59820ed2019-06-24 17:01:00 -0700277 logger.log('debug', `event ${topic} is routed to workflow run ${workflowRunId}`);
278 workflowRun.enqueueEvent(topic, message);
279
280 if(!workflowIdsRunning.includes(workflowId)) {
281 workflowIdsRunning.push(workflowId);
282 }
283 }
284 });
285
286 // check if the event is a kickstart event
287 _.forOwn(workflows, (workflow, workflowId) => {
288 if(workflow.isKickstartTopic(topic)) {
289 // check if there is a workflow run for the event
290 // kickstart a workflow if there is no workflows runs for the event
291 if(!workflowIdsRunning.includes(workflowId)) {
292 // we need to buffer the event until workflow run is brought up
293 let workflowRun = WorkflowRun.WorkflowRun.makeNewRun(workflow);
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700294 workflowRun.updateEventKeyFieldValueFromMessage(topic, message);
295
Illyoung Choi59820ed2019-06-24 17:01:00 -0700296 let workflowRunId = workflowRun.getId();
297
298 // register for management
299 workflowRuns[workflowRunId] = workflowRun;
300
301 // route event
302 logger.log('debug', `event ${topic} is routed to workflow run ${workflowRunId}`);
303 workflowRun.enqueueEvent(topic, message);
304
305 // KICKSTART!
306 kickstart(workflowId, workflowRunId);
307 }
308 }
309 });
310 };
311
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700312 const countQueuedEvents = (workflowRunId) => {
313 // this counts queued events
314 if(!(workflowRunId in workflowRuns)) {
315 logger.log('warn', `workflow run ${workflowRunId} does not exist`);
316 return null;
317 }
318
319 let workflowRun = workflowRuns[workflowRunId];
320 return workflowRun.lengthEventQueue();
321 };
322
Illyoung Choi59820ed2019-06-24 17:01:00 -0700323 const fetchEvent = (workflowRunId, taskId, topic) => {
324 // this returns an event or an empty obj when there is no message
325 if(!(workflowRunId in workflowRuns)) {
326 logger.log('warn', `workflow run ${workflowRunId} does not exist`);
327 return null;
328 }
329
330 let workflowRun = workflowRuns[workflowRunId];
331 let workflowId = workflowRun.getWorkflowId();
332
333 if(!(workflowId in workflows)) {
334 logger.log('warn', `workflow ${workflowId} does not exist`);
335 return null;
336 }
337
338 let workflow = workflows[workflowId];
339
340 let task = workflow.getTask(taskId);
341 if(!task) {
342 logger.log('warn', `workflow ${workflowId} does not have task ${taskId}`);
343 return null;
344 }
345
346 logger.log('debug', `workflow run ${workflowRunId}, task ${taskId} fetches an event`);
347
348 let event = workflowRun.dequeueEvent(topic);
349 if(event) {
350 return event;
351 }
352 else {
353 return {};
354 }
355 };
356
357 const addClient = (c) => {
358 let clientId = c.getId();
359 let socket = c.getSocket();
360
361 // check id that client is already there
362 if(clientId in allClients) {
363 logger.log('warn', `there exists a client with the same id - ${clientId}`);
364 return false;
365 }
366
367 if(c.getType() === Client.Type.PROBE) {
Illyoung Choi16c6d4f2019-07-24 18:09:26 -0700368 // probe
Illyoung Choi59820ed2019-06-24 17:01:00 -0700369 // probe protocol:
370 // REQ:
Illyoung Choi16c6d4f2019-07-24 18:09:26 -0700371 // topic: operation
372 // message: {
373 // req_id: <req_id>,
374 // topic: <topic>,
375 // message: <data>
376 // }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700377 // RES:
378 // topic: topic sent
Illyoung Choi16c6d4f2019-07-24 18:09:26 -0700379 // message: {
380 // req_id: <req_id>,
381 // error: <true/false>,
382 // result: <true/false>,
383 // message: <error message>
384 // }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700385 allClients[clientId] = c;
386 probeClients[clientId] = c;
387
Illyoung Choi16c6d4f2019-07-24 18:09:26 -0700388 // attach probe operations
389 let router = ws_probe.getRouter();
390 _.forOwn(router, (routerElem, _key) => {
391 socket.on(routerElem.topic, (msg) => {
392 // handle a common parameter - req_id
393 // when we get req_id, return the same req_id in response.
394 // this is to help identify a request from a response at client-side
395 let req_id = 101010; // default number, signiture
396 if(msg && checkObject(msg)) {
397 if('req_id' in msg) {
398 req_id = msg.req_id;
399 }
400 }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700401
Illyoung Choi16c6d4f2019-07-24 18:09:26 -0700402 routerElem.handler(routerElem.topic, msg || {}, (err, result) => {
403 if(err) {
404 logger.log('warn', `unable to handle a message - ${err}`);
405 socket.emit(routerElem.topic, {
406 req_id: req_id,
407 error: true,
408 result: result,
409 message: err
410 });
411 return;
412 }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700413
Illyoung Choi16c6d4f2019-07-24 18:09:26 -0700414 // we return result
415 if(routerElem.return === undefined || routerElem.return) {
416 socket.emit(routerElem.topic, {
417 req_id: req_id,
418 error: false,
419 result: result
420 });
421 }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700422 });
Illyoung Choi16c6d4f2019-07-24 18:09:26 -0700423 });
Illyoung Choi59820ed2019-06-24 17:01:00 -0700424 });
425 return true;
426 }
427 else if(c.getType() === Client.Type.WORKFLOW_MANAGER) {
428 // manager
429 // manager protocol:
430 // REQ:
431 // topic: operation
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700432 // message: {
433 // req_id: <req_id>,
434 // <data>...
435 // }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700436 // RES:
437 // topic: topic sent
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700438 // message: {
439 // req_id: <req_id>,
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700440 // error: <true/false>,
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700441 // result: <true/false>,
442 // message: <error message>
443 // }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700444 allClients[clientId] = c;
445 workflowManagerClients[clientId] = c;
446
447 // attach manager operations
448 let router = ws_manager.getRouter();
449 _.forOwn(router, (routerElem, _key) => {
450 socket.on(routerElem.topic, (msg) => {
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700451 // handle a common parameter - req_id
452 // when we get req_id, return the same req_id in response.
453 // this is to help identify a request from a response at client-side
454 let req_id = 101010; // default number, signiture
455 if(msg && checkObject(msg)) {
456 if('req_id' in msg) {
457 req_id = msg.req_id;
458 }
459 }
460
461 routerElem.handler(routerElem.topic, msg || {}, (err, result) => {
Illyoung Choi59820ed2019-06-24 17:01:00 -0700462 if(err) {
463 logger.log('warn', `unable to handle a message - ${err}`);
464 socket.emit(routerElem.topic, {
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700465 req_id: req_id,
466 error: true,
467 result: result,
Illyoung Choi59820ed2019-06-24 17:01:00 -0700468 message: err
469 });
470 return;
471 }
472
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700473 // we return result
Illyoung Choi59820ed2019-06-24 17:01:00 -0700474 if(routerElem.return === undefined || routerElem.return) {
475 socket.emit(routerElem.topic, {
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700476 req_id: req_id,
477 error: false,
Illyoung Choi59820ed2019-06-24 17:01:00 -0700478 result: result
479 });
480 }
481 });
482 });
483 });
484 return true;
485 }
486 else if(c.getType() === Client.Type.WORKFLOW_RUN) {
487 // workflow run
488 // workflow run protocol:
489 // REQ:
490 // topic: operation
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700491 // message: {
492 // req_id: <req_id>,
493 // <data>...
494 // }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700495 // RES:
496 // topic: topic sent
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700497 // message: {
498 // req_id: <req_id>,
499 // error: <true/false>,
500 // result: <true/false>,
501 // message: <error message>
502 // }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700503
504 // map to WorkflowRun instance
505 let workflowId = c.getWorkflowId();
506 let workflowRunId = c.getWorkflowRunId();
507 let workflowRun;
508
509 if(!(workflowId in workflows)) {
510 logger.log('warn', `cannot find a workflow ${workflowId}`);
511 return false;
512 }
513
514 // register client to workflow run
515 if(!(workflowRunId in workflowRuns)) {
516 // workflow run not exist yet
517 logger.log('warn', `cannot find a workflow run ${workflowRunId}`);
518 return false;
519 }
520
521 //let workflow = workflows[workflowId];
522
523 allClients[clientId] = c;
524 workflowRunClients[clientId] = c;
525
526 // update
527 workflowRun = workflowRuns[workflowRunId];
528 workflowRun.addClientId(clientId);
529
530 // attach workflow run operations
531 let router = ws_workflowrun.getRouter();
532 _.forOwn(router, (routerElem, _key) => {
533 socket.on(routerElem.topic, (msg) => {
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700534 // handle a common parameter - req_id
535 // when we get req_id, return the same req_id in response.
536 // this is to help identify a request from a response at client-side
537 let req_id = 101010; // default number, signiture
538 if(msg && checkObject(msg)) {
539 if('req_id' in msg) {
540 req_id = msg.req_id;
541 }
542 }
543
544 routerElem.handler(routerElem.topic, msg || {}, (err, result) => {
Illyoung Choi59820ed2019-06-24 17:01:00 -0700545 if(err) {
546 logger.log('warn', `unable to handle a message - ${err}`);
547 socket.emit(routerElem.topic, {
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700548 req_id: req_id,
549 error: true,
Illyoung Choi59820ed2019-06-24 17:01:00 -0700550 result: false,
551 message: err
552 });
553 return;
554 }
555
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700556 // we return result
Illyoung Choi59820ed2019-06-24 17:01:00 -0700557 if(routerElem.return === undefined || routerElem.return) {
558 socket.emit(routerElem.topic, {
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700559 req_id: req_id,
560 error: false,
Illyoung Choi59820ed2019-06-24 17:01:00 -0700561 result: result
562 });
563 }
564 });
565 });
566 });
567 return true;
568 }
569 return false;
570 };
571
572 const removeClient = (id) => {
573 if(id in allClients) {
574 let removedClient = allClients[id];
575 delete allClients[id];
576
577 let type = removedClient.getType();
578 if(type === Client.Type.PROBE) {
579 delete probeClients[id];
580 }
581 else if(type === Client.Type.WORKFLOW_MANAGER) {
582 delete workflowManagerClients[id];
583 }
584 else if(type === Client.Type.WORKFLOW_RUN) {
585 delete workflowRunClients[id];
586
587 let workflowRunId = removedClient.getWorkflowRunId();
588 let workflowRun = workflowRuns[workflowRunId];
589
590 if(workflowRun) {
591 workflowRun.removeClientId(id);
592
593 //TODO
594 // WorkflowRun can have no clients between tasks
595 // So we should not remove the run until the workflow run finishes
596 }
597 }
598 }
599 };
600
601 const removeClients = () => {
602 let probeClients = {};
603
604 _.forOwn(probeClients, (_probeClient, clientId) => {
605 delete probeClients[clientId];
606 });
607
608 _.forOwn(workflowManagerClients, (_workflowManagerClient, clientId) => {
609 delete workflowManagerClients[clientId];
610 });
611
612 _.forOwn(workflowRunClients, (_workflowRunClients, clientId) => {
613 delete workflowRunClients[clientId];
614 });
615
616 _.forOwn(allClients, (client, clientId) => {
617 client.getSocket().disconnect(true);
618 delete allClients[clientId];
619 });
620 }
621
622 module.exports = {
623 serviceEvents: serviceEvents,
624 destroy: destroy,
625 getClients: () => { return allClients; },
626 getProbeClients: () => { return probeClients; },
627 getWorkflowManagerClients: () => { return workflowManagerClients; },
628 getWorkflowRunClients: () => { return workflowRunClients; },
629 clientType: Client.Type,
630 //setIO: setIO,
Illyoung Choi16c6d4f2019-07-24 18:09:26 -0700631 emitEvent: emitEvent,
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700632 countQueuedEvents: countQueuedEvents,
Illyoung Choi59820ed2019-06-24 17:01:00 -0700633 fetchEvent: fetchEvent,
634 addClient: addClient,
635 removeClient: removeClient,
636 removeClients: removeClients,
637 addWorkflow: addWorkflow,
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700638 getWorkflow: getWorkflow,
Illyoung Choi59820ed2019-06-24 17:01:00 -0700639 listWorkflows: listWorkflows,
640 checkWorkflow: checkWorkflow,
641 removeWorkflow: removeWorkflow,
642 clearWorkflows: clearWorkflows,
643 addWorkflowRun: addWorkflowRun,
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700644 getWorkflowRun: getWorkflowRun,
Illyoung Choi59820ed2019-06-24 17:01:00 -0700645 listWorkflowRuns: listWorkflowRuns,
646 checkWorkflowRun: checkWorkflowRun,
647 removeWorkflowRun: removeWorkflowRun,
648 clearWorkflowRuns: clearWorkflowRuns,
649 updateWorkflowRunStatus: updateWorkflowRunStatus,
650 setWorkflowRunKickstarted: setWorkflowRunKickstarted,
Illyoung Choic707c052019-07-18 13:50:49 -0700651 setWorkflowRunState: setWorkflowRunState
Illyoung Choi59820ed2019-06-24 17:01:00 -0700652 };
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700653})();