047b1f393090601b2441be1fca1235c934878054
[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.LoggingAnchor;
29 import org.onap.so.logger.ErrorCode;
30 import org.onap.so.logger.MessageEnum;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import org.springframework.stereotype.Component;
34
35 /**
36  * Workflow Context Holder instance which can be accessed elsewhere either in groovy scripts or Java
37  * 
38  * @version 1.0
39  *
40  */
41
42 @Component
43 public class WorkflowContextHolder {
44
45     private static Logger logger = LoggerFactory.getLogger(WorkflowContextHolder.class);
46     private static final String logMarker = "[WORKFLOW-CONTEXT-HOLDER]";
47     private static WorkflowContextHolder instance = null;
48
49
50     private long defaultContextTimeout = 60000;
51
52     /**
53      * Delay Queue which holds workflow context holder objects
54      */
55     private final DelayQueue<WorkflowContext> responseQueue = new DelayQueue<>();
56     private final TimeoutThread timeoutThread = new TimeoutThread();
57
58     private WorkflowContextHolder() {
59         timeoutThread.start();
60     }
61
62     /**
63      * Singleton holder which eliminates hot lock Since the JVM synchronizes static method there is no synchronization
64      * needed for this method
65      * 
66      * @return
67      */
68     public static synchronized WorkflowContextHolder getInstance() {
69         if (instance == null) {
70             instance = new WorkflowContextHolder();
71         }
72         return instance;
73     }
74
75     public void put(WorkflowContext context) {
76         logger.debug("{} Adding context to the queue: {}", logMarker, context.getRequestId());
77         responseQueue.put(context);
78     }
79
80     public void remove(WorkflowContext context) {
81         logger.debug("{} Removing context from the queue: {}", logMarker, context.getRequestId());
82         responseQueue.remove(context);
83     }
84
85     public WorkflowContext getWorkflowContext(String requestId) {
86         // Note: DelayQueue interator is threadsafe
87         for (WorkflowContext context : responseQueue) {
88             if (requestId.equals(context.getRequestId())) {
89                 return context;
90             }
91         }
92         return null;
93     }
94
95     /**
96      * Builds the callback response object to respond to client
97      * 
98      * @param processKey
99      * @param processInstanceId
100      * @param requestId
101      * @param callbackResponse
102      * @return
103      */
104     public void processCallback(String processKey, String processInstanceId, String requestId,
105             WorkflowCallbackResponse callbackResponse) {
106         WorkflowResponse workflowResponse = new WorkflowResponse();
107         workflowResponse.setResponse(callbackResponse.getResponse());
108         workflowResponse.setProcessInstanceID(processInstanceId);
109         workflowResponse.setMessageCode(callbackResponse.getStatusCode());
110         workflowResponse.setMessage(callbackResponse.getMessage());
111         WorkflowContext context = new WorkflowContext(processKey, requestId, defaultContextTimeout, workflowResponse);
112         put(context);
113     }
114
115
116     /**
117      * Timeout thread which monitors the delay queue for expired context and send timeout response to client
118      *
119      */
120     private class TimeoutThread extends Thread {
121         @Override
122         public void run() {
123             while (!isInterrupted()) {
124                 try {
125                     WorkflowContext requestObject = responseQueue.take();
126                     logger.debug("Time remaining for request id: {}:{}", requestObject.getRequestId(),
127                             requestObject.getDelay(TimeUnit.MILLISECONDS));
128                     logger.debug("Preparing timeout response for {}:{}", requestObject.getProcessKey(),
129                             requestObject.getRequestId());
130                 } catch (InterruptedException e) {
131                     Thread.currentThread().interrupt();
132                 } catch (Exception e) {
133                     logger.debug("WorkflowContextHolder timeout thread caught exception: ", e);
134                     logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION.toString(), "BPMN",
135                             ErrorCode.UnknownError.getValue(), "Error in WorkflowContextHolder timeout thread");
136                 }
137             }
138             logger.debug("WorkflowContextHolder timeout thread interrupted, quitting");
139         }
140     }
141 }