blob: 4d9ee474b3643699eb4ac7cb232711214029f588 [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
Illyoung Choid8f79562019-07-25 12:54:55 -0700302 logger.log('debug', `event ${topic} is routed to a new workflow run ${workflowRunId}`);
Illyoung Choi59820ed2019-06-24 17:01:00 -0700303 workflowRun.enqueueEvent(topic, message);
304
305 // KICKSTART!
306 kickstart(workflowId, workflowRunId);
307 }
308 }
309 });
Illyoung Choid8f79562019-07-25 12:54:55 -0700310
311 return true;
Illyoung Choi59820ed2019-06-24 17:01:00 -0700312 };
313
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700314 const countQueuedEvents = (workflowRunId) => {
315 // this counts queued events
316 if(!(workflowRunId in workflowRuns)) {
317 logger.log('warn', `workflow run ${workflowRunId} does not exist`);
318 return null;
319 }
320
321 let workflowRun = workflowRuns[workflowRunId];
322 return workflowRun.lengthEventQueue();
323 };
324
Illyoung Choi59820ed2019-06-24 17:01:00 -0700325 const fetchEvent = (workflowRunId, taskId, topic) => {
326 // this returns an event or an empty obj when there is no message
327 if(!(workflowRunId in workflowRuns)) {
328 logger.log('warn', `workflow run ${workflowRunId} does not exist`);
329 return null;
330 }
331
332 let workflowRun = workflowRuns[workflowRunId];
333 let workflowId = workflowRun.getWorkflowId();
334
335 if(!(workflowId in workflows)) {
336 logger.log('warn', `workflow ${workflowId} does not exist`);
337 return null;
338 }
339
340 let workflow = workflows[workflowId];
341
342 let task = workflow.getTask(taskId);
343 if(!task) {
344 logger.log('warn', `workflow ${workflowId} does not have task ${taskId}`);
345 return null;
346 }
347
348 logger.log('debug', `workflow run ${workflowRunId}, task ${taskId} fetches an event`);
349
350 let event = workflowRun.dequeueEvent(topic);
351 if(event) {
352 return event;
353 }
354 else {
355 return {};
356 }
357 };
358
359 const addClient = (c) => {
360 let clientId = c.getId();
361 let socket = c.getSocket();
362
363 // check id that client is already there
364 if(clientId in allClients) {
365 logger.log('warn', `there exists a client with the same id - ${clientId}`);
366 return false;
367 }
368
369 if(c.getType() === Client.Type.PROBE) {
Illyoung Choi16c6d4f2019-07-24 18:09:26 -0700370 // probe
Illyoung Choi59820ed2019-06-24 17:01:00 -0700371 // probe protocol:
372 // REQ:
Illyoung Choi16c6d4f2019-07-24 18:09:26 -0700373 // topic: operation
374 // message: {
375 // req_id: <req_id>,
376 // topic: <topic>,
377 // message: <data>
378 // }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700379 // RES:
380 // topic: topic sent
Illyoung Choi16c6d4f2019-07-24 18:09:26 -0700381 // message: {
382 // req_id: <req_id>,
383 // error: <true/false>,
384 // result: <true/false>,
385 // message: <error message>
386 // }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700387 allClients[clientId] = c;
388 probeClients[clientId] = c;
389
Illyoung Choi16c6d4f2019-07-24 18:09:26 -0700390 // attach probe operations
391 let router = ws_probe.getRouter();
392 _.forOwn(router, (routerElem, _key) => {
393 socket.on(routerElem.topic, (msg) => {
394 // handle a common parameter - req_id
395 // when we get req_id, return the same req_id in response.
396 // this is to help identify a request from a response at client-side
397 let req_id = 101010; // default number, signiture
398 if(msg && checkObject(msg)) {
399 if('req_id' in msg) {
400 req_id = msg.req_id;
401 }
402 }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700403
Illyoung Choi16c6d4f2019-07-24 18:09:26 -0700404 routerElem.handler(routerElem.topic, msg || {}, (err, result) => {
405 if(err) {
406 logger.log('warn', `unable to handle a message - ${err}`);
407 socket.emit(routerElem.topic, {
408 req_id: req_id,
409 error: true,
410 result: result,
411 message: err
412 });
413 return;
414 }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700415
Illyoung Choi16c6d4f2019-07-24 18:09:26 -0700416 // we return result
417 if(routerElem.return === undefined || routerElem.return) {
418 socket.emit(routerElem.topic, {
419 req_id: req_id,
420 error: false,
421 result: result
422 });
423 }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700424 });
Illyoung Choi16c6d4f2019-07-24 18:09:26 -0700425 });
Illyoung Choi59820ed2019-06-24 17:01:00 -0700426 });
427 return true;
428 }
429 else if(c.getType() === Client.Type.WORKFLOW_MANAGER) {
430 // manager
431 // manager protocol:
432 // REQ:
433 // topic: operation
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700434 // message: {
435 // req_id: <req_id>,
436 // <data>...
437 // }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700438 // RES:
439 // topic: topic sent
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700440 // message: {
441 // req_id: <req_id>,
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700442 // error: <true/false>,
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700443 // result: <true/false>,
444 // message: <error message>
445 // }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700446 allClients[clientId] = c;
447 workflowManagerClients[clientId] = c;
448
449 // attach manager operations
450 let router = ws_manager.getRouter();
451 _.forOwn(router, (routerElem, _key) => {
452 socket.on(routerElem.topic, (msg) => {
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700453 // handle a common parameter - req_id
454 // when we get req_id, return the same req_id in response.
455 // this is to help identify a request from a response at client-side
456 let req_id = 101010; // default number, signiture
457 if(msg && checkObject(msg)) {
458 if('req_id' in msg) {
459 req_id = msg.req_id;
460 }
461 }
462
463 routerElem.handler(routerElem.topic, msg || {}, (err, result) => {
Illyoung Choi59820ed2019-06-24 17:01:00 -0700464 if(err) {
465 logger.log('warn', `unable to handle a message - ${err}`);
466 socket.emit(routerElem.topic, {
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700467 req_id: req_id,
468 error: true,
469 result: result,
Illyoung Choi59820ed2019-06-24 17:01:00 -0700470 message: err
471 });
472 return;
473 }
474
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700475 // we return result
Illyoung Choi59820ed2019-06-24 17:01:00 -0700476 if(routerElem.return === undefined || routerElem.return) {
477 socket.emit(routerElem.topic, {
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700478 req_id: req_id,
479 error: false,
Illyoung Choi59820ed2019-06-24 17:01:00 -0700480 result: result
481 });
482 }
483 });
484 });
485 });
486 return true;
487 }
488 else if(c.getType() === Client.Type.WORKFLOW_RUN) {
489 // workflow run
490 // workflow run protocol:
491 // REQ:
492 // topic: operation
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700493 // message: {
494 // req_id: <req_id>,
495 // <data>...
496 // }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700497 // RES:
498 // topic: topic sent
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700499 // message: {
500 // req_id: <req_id>,
501 // error: <true/false>,
502 // result: <true/false>,
503 // message: <error message>
504 // }
Illyoung Choi59820ed2019-06-24 17:01:00 -0700505
506 // map to WorkflowRun instance
507 let workflowId = c.getWorkflowId();
508 let workflowRunId = c.getWorkflowRunId();
509 let workflowRun;
510
511 if(!(workflowId in workflows)) {
512 logger.log('warn', `cannot find a workflow ${workflowId}`);
513 return false;
514 }
515
516 // register client to workflow run
517 if(!(workflowRunId in workflowRuns)) {
518 // workflow run not exist yet
519 logger.log('warn', `cannot find a workflow run ${workflowRunId}`);
520 return false;
521 }
522
523 //let workflow = workflows[workflowId];
524
525 allClients[clientId] = c;
526 workflowRunClients[clientId] = c;
527
528 // update
529 workflowRun = workflowRuns[workflowRunId];
530 workflowRun.addClientId(clientId);
531
532 // attach workflow run operations
533 let router = ws_workflowrun.getRouter();
534 _.forOwn(router, (routerElem, _key) => {
535 socket.on(routerElem.topic, (msg) => {
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700536 // handle a common parameter - req_id
537 // when we get req_id, return the same req_id in response.
538 // this is to help identify a request from a response at client-side
539 let req_id = 101010; // default number, signiture
540 if(msg && checkObject(msg)) {
541 if('req_id' in msg) {
542 req_id = msg.req_id;
543 }
544 }
545
546 routerElem.handler(routerElem.topic, msg || {}, (err, result) => {
Illyoung Choi59820ed2019-06-24 17:01:00 -0700547 if(err) {
548 logger.log('warn', `unable to handle a message - ${err}`);
549 socket.emit(routerElem.topic, {
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700550 req_id: req_id,
551 error: true,
Illyoung Choi59820ed2019-06-24 17:01:00 -0700552 result: false,
553 message: err
554 });
555 return;
556 }
557
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700558 // we return result
Illyoung Choi59820ed2019-06-24 17:01:00 -0700559 if(routerElem.return === undefined || routerElem.return) {
560 socket.emit(routerElem.topic, {
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700561 req_id: req_id,
562 error: false,
Illyoung Choi59820ed2019-06-24 17:01:00 -0700563 result: result
564 });
565 }
566 });
567 });
568 });
569 return true;
570 }
571 return false;
572 };
573
574 const removeClient = (id) => {
575 if(id in allClients) {
576 let removedClient = allClients[id];
577 delete allClients[id];
578
579 let type = removedClient.getType();
580 if(type === Client.Type.PROBE) {
581 delete probeClients[id];
582 }
583 else if(type === Client.Type.WORKFLOW_MANAGER) {
584 delete workflowManagerClients[id];
585 }
586 else if(type === Client.Type.WORKFLOW_RUN) {
587 delete workflowRunClients[id];
588
589 let workflowRunId = removedClient.getWorkflowRunId();
590 let workflowRun = workflowRuns[workflowRunId];
591
592 if(workflowRun) {
593 workflowRun.removeClientId(id);
594
595 //TODO
596 // WorkflowRun can have no clients between tasks
597 // So we should not remove the run until the workflow run finishes
598 }
599 }
600 }
601 };
602
603 const removeClients = () => {
604 let probeClients = {};
605
606 _.forOwn(probeClients, (_probeClient, clientId) => {
607 delete probeClients[clientId];
608 });
609
610 _.forOwn(workflowManagerClients, (_workflowManagerClient, clientId) => {
611 delete workflowManagerClients[clientId];
612 });
613
614 _.forOwn(workflowRunClients, (_workflowRunClients, clientId) => {
615 delete workflowRunClients[clientId];
616 });
617
618 _.forOwn(allClients, (client, clientId) => {
619 client.getSocket().disconnect(true);
620 delete allClients[clientId];
621 });
622 }
623
624 module.exports = {
625 serviceEvents: serviceEvents,
626 destroy: destroy,
627 getClients: () => { return allClients; },
628 getProbeClients: () => { return probeClients; },
629 getWorkflowManagerClients: () => { return workflowManagerClients; },
630 getWorkflowRunClients: () => { return workflowRunClients; },
631 clientType: Client.Type,
632 //setIO: setIO,
Illyoung Choi16c6d4f2019-07-24 18:09:26 -0700633 emitEvent: emitEvent,
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700634 countQueuedEvents: countQueuedEvents,
Illyoung Choi59820ed2019-06-24 17:01:00 -0700635 fetchEvent: fetchEvent,
636 addClient: addClient,
637 removeClient: removeClient,
638 removeClients: removeClients,
639 addWorkflow: addWorkflow,
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700640 getWorkflow: getWorkflow,
Illyoung Choi59820ed2019-06-24 17:01:00 -0700641 listWorkflows: listWorkflows,
642 checkWorkflow: checkWorkflow,
643 removeWorkflow: removeWorkflow,
644 clearWorkflows: clearWorkflows,
645 addWorkflowRun: addWorkflowRun,
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700646 getWorkflowRun: getWorkflowRun,
Illyoung Choi59820ed2019-06-24 17:01:00 -0700647 listWorkflowRuns: listWorkflowRuns,
648 checkWorkflowRun: checkWorkflowRun,
649 removeWorkflowRun: removeWorkflowRun,
650 clearWorkflowRuns: clearWorkflowRuns,
651 updateWorkflowRunStatus: updateWorkflowRunStatus,
652 setWorkflowRunKickstarted: setWorkflowRunKickstarted,
Illyoung Choic707c052019-07-18 13:50:49 -0700653 setWorkflowRunState: setWorkflowRunState
Illyoung Choi59820ed2019-06-24 17:01:00 -0700654 };
Illyoung Choib4fc0d82019-07-16 10:29:39 -0700655})();