33fb78b3060b778ae39af0e05824d4cf52a0cd21
[so.git] /
1 package org.onap.so.bpmn.common.workflow.context;
2 /*-
3  * ============LICENSE_START=======================================================
4  * ONAP - SO
5  * ================================================================================
6  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
7  * ================================================================================
8  * Modifications Copyright (c) 2019 Samsung
9  * ================================================================================
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  * 
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  * 
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  * ============LICENSE_END=========================================================
22  */
23
24
25
26 import java.util.concurrent.DelayQueue;
27 import java.util.concurrent.TimeUnit;
28 import org.onap.so.logger.ErrorCode;
29 import org.onap.so.logger.MessageEnum;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32 import org.springframework.stereotype.Component;
33
34 /**
35  * Workflow Context Holder instance which can be accessed elsewhere either in groovy scripts or Java
36  * 
37  * @version 1.0
38  *
39  */
40
41 @Component
42 public class WorkflowContextHolder {
43
44     private static Logger logger = LoggerFactory.getLogger(WorkflowContextHolder.class);
45     private static final String logMarker = "[WORKFLOW-CONTEXT-HOLDER]";
46     private static WorkflowContextHolder instance = null;
47
48
49     private long defaultContextTimeout = 60000;
50
51     /**
52      * Delay Queue which holds workflow context holder objects
53      */
54     private final DelayQueue<WorkflowContext> responseQueue = new DelayQueue<>();
55     private final TimeoutThread timeoutThread = new TimeoutThread();
56
57     private WorkflowContextHolder() {
58         timeoutThread.start();
59     }
60
61     /**
62      * Singleton holder which eliminates hot lock Since the JVM synchronizes static method there is no synchronization
63      * needed for this method
64      * 
65      * @return
66      */
67     public static synchronized WorkflowContextHolder getInstance() {
68         if (instance == null) {
69             instance = new WorkflowContextHolder();
70         }
71         return instance;
72     }
73
74     public void put(WorkflowContext context) {
75         logger.debug("{} Adding context to the queue: {}", logMarker, context.getRequestId());
76         responseQueue.put(context);
77     }
78
79     public void remove(WorkflowContext context) {
80         logger.debug("{} Removing context from the queue: {}", logMarker, context.getRequestId());
81         responseQueue.remove(context);
82     }
83
84     public WorkflowContext getWorkflowContext(String requestId) {
85         // Note: DelayQueue interator is threadsafe
86         for (WorkflowContext context : responseQueue) {
87             if (requestId.equals(context.getRequestId())) {
88                 return context;
89             }
90         }
91         return null;
92     }
93
94     /**
95      * Builds the callback response object to respond to client
96      * 
97      * @param processKey
98      * @param processInstanceId
99      * @param requestId
100      * @param callbackResponse
101      * @return
102      */
103     public void processCallback(String processKey, String processInstanceId, String requestId,
104             WorkflowCallbackResponse callbackResponse) {
105         WorkflowResponse workflowResponse = new WorkflowResponse();
106         workflowResponse.setResponse(callbackResponse.getResponse());
107         workflowResponse.setProcessInstanceID(processInstanceId);
108         workflowResponse.setMessageCode(callbackResponse.getStatusCode());
109         workflowResponse.setMessage(callbackResponse.getMessage());
110         WorkflowContext context = new WorkflowContext(processKey, requestId, defaultContextTimeout, workflowResponse);
111         put(context);
112     }
113
114
115     /**
116      * Timeout thread which monitors the delay queue for expired context and send timeout response to client
117      *
118      */
119     private class TimeoutThread extends Thread {
120         @Override
121         public void run() {
122             while (!isInterrupted()) {
123                 try {
124                     WorkflowContext requestObject = responseQueue.take();
125                     logger.debug("Time remaining for request id: {}:{}", requestObject.getRequestId(),
126                             requestObject.getDelay(TimeUnit.MILLISECONDS));
127                     logger.debug("Preparing timeout response for {}:{}", requestObject.getProcessKey(),
128                             requestObject.getRequestId());
129                 } catch (InterruptedException e) {
130                     Thread.currentThread().interrupt();
131                 } catch (Exception e) {
132                     logger.debug("WorkflowContextHolder timeout thread caught exception: ", e);
133                     logger.error("{} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION.toString(), "BPMN",
134                             ErrorCode.UnknownError.getValue(), "Error in WorkflowContextHolder timeout thread");
135                 }
136             }
137             logger.debug("WorkflowContextHolder timeout thread interrupted, quitting");
138         }
139     }
140 }