f5dd49877b03d8e4a5e787a74599e9bdfcf07180
[policy/models.git] / models-interactions / model-actors / actorServiceProvider / src / main / java / org / onap / policy / controlloop / actorserviceprovider / parameters / ControlLoopOperationParams.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.controlloop.actorserviceprovider.parameters;
22
23 import java.util.Map;
24 import java.util.UUID;
25 import java.util.concurrent.CompletableFuture;
26 import java.util.concurrent.Executor;
27 import java.util.concurrent.ForkJoinPool;
28 import java.util.function.Consumer;
29 import lombok.AllArgsConstructor;
30 import lombok.Builder;
31 import lombok.EqualsAndHashCode;
32 import lombok.Getter;
33 import org.onap.policy.common.parameters.BeanValidationResult;
34 import org.onap.policy.common.parameters.BeanValidator;
35 import org.onap.policy.common.parameters.annotations.NotNull;
36 import org.onap.policy.controlloop.actorserviceprovider.ActorService;
37 import org.onap.policy.controlloop.actorserviceprovider.Operation;
38 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
39 import org.onap.policy.controlloop.actorserviceprovider.Util;
40 import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
41 import org.onap.policy.controlloop.policy.Target;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 /**
46  * Parameters for control loop operations. The executor defaults to
47  * {@link ForkJoinPool#commonPool()}, but may be overridden.
48  */
49 @Getter
50 @Builder(toBuilder = true)
51 @AllArgsConstructor
52 @EqualsAndHashCode
53 public class ControlLoopOperationParams {
54     private static final Logger logger = LoggerFactory.getLogger(ControlLoopOperationParams.class);
55
56     /**
57      * Actor name.
58      */
59     @NotNull
60     private String actor;
61
62     /**
63      * Actor service in which to find the actor/operation.
64      */
65     @NotNull
66     private ActorService actorService;
67
68     /**
69      * Event for which the operation applies.
70      */
71     @NotNull
72     private ControlLoopEventContext context;
73
74     /**
75      * Executor to use to run the operation.
76      */
77     @NotNull
78     @Builder.Default
79     private Executor executor = ForkJoinPool.commonPool();
80
81     /**
82      * Operation name.
83      */
84     @NotNull
85     private String operation;
86
87     /**
88      * Payload data for the request.
89      */
90     private Map<String, Object> payload;
91
92     /**
93      * {@code True} if the preprocessing steps have already been executed, {@code false}
94      * otherwise.
95      */
96     private boolean preprocessed;
97
98     /**
99      * Number of retries allowed, or {@code null} if no retries.
100      */
101     private Integer retry;
102
103     /**
104      * The entity's target information. May be {@code null}, depending on the requirement
105      * of the operation to be invoked.
106      */
107     private Target target;
108
109     /**
110      * Target entity.
111      */
112     @NotNull
113     private String targetEntity;
114
115     /**
116      * Timeout, in seconds, or {@code null} if no timeout. Zero and negative values also
117      * imply no timeout.
118      */
119     @Builder.Default
120     private Integer timeoutSec = 300;
121
122     /**
123      * The function to invoke when the operation starts. This is optional.
124      * <p/>
125      * Note: this may be invoked multiple times, but with different actor/operations. That
126      * may happen if the current operation requires other operations to be performed first
127      * (e.g., A&AI queries, guard checks).
128      */
129     private Consumer<OperationOutcome> startCallback;
130
131     /**
132      * The function to invoke when the operation completes. This is optional.
133      * <p/>
134      * Note: this may be invoked multiple times, but with different actor/operations. That
135      * may happen if the current operation requires other operations to be performed first
136      * (e.g., A&AI queries, guard checks).
137      */
138     private Consumer<OperationOutcome> completeCallback;
139
140     /**
141      * Starts the specified operation.
142      *
143      * @return a future that will return the result of the operation
144      * @throws IllegalArgumentException if the parameters are invalid
145      */
146     public CompletableFuture<OperationOutcome> start() {
147         return build().start();
148     }
149
150     /**
151      * Builds the specified operation.
152      *
153      * @return a new operation
154      * @throws IllegalArgumentException if the parameters are invalid
155      */
156     public Operation build() {
157         BeanValidationResult result = validate();
158         if (!result.isValid()) {
159             logger.warn("parameter error in operation {}.{} for {}:\n{}", getActor(), getOperation(), getRequestId(),
160                             result.getResult());
161             throw new IllegalArgumentException("invalid parameters");
162         }
163
164         // @formatter:off
165         return actorService
166                     .getActor(getActor())
167                     .getOperator(getOperation())
168                     .buildOperation(this);
169         // @formatter:on
170     }
171
172     /**
173      * Gets the requested ID of the associated event.
174      *
175      * @return the event's request ID, or {@code null} if no request ID is available
176      */
177     public UUID getRequestId() {
178         return (context == null || context.getEvent() == null ? null : context.getEvent().getRequestId());
179     }
180
181     /**
182      * Makes an operation outcome, populating it from the parameters.
183      *
184      * @return a new operation outcome
185      */
186     public OperationOutcome makeOutcome() {
187         OperationOutcome outcome = new OperationOutcome();
188         outcome.setActor(getActor());
189         outcome.setOperation(getOperation());
190         outcome.setTarget(targetEntity);
191
192         return outcome;
193     }
194
195     /**
196      * Invokes the callback to indicate that the operation has started. Any exceptions
197      * generated by the callback are logged, but not re-thrown.
198      *
199      * @param operation the operation that is being started
200      */
201     public void callbackStarted(OperationOutcome operation) {
202         logger.info("started operation {}.{} for {}", operation.getActor(), operation.getOperation(), getRequestId());
203
204         if (startCallback != null) {
205             Util.runFunction(() -> startCallback.accept(operation), "{}.{}: start-callback threw an exception for {}",
206                             operation.getActor(), operation.getOperation(), getRequestId());
207         }
208     }
209
210     /**
211      * Invokes the callback to indicate that the operation has completed. Any exceptions
212      * generated by the callback are logged, but not re-thrown.
213      *
214      * @param operation the operation that is being started
215      */
216     public void callbackCompleted(OperationOutcome operation) {
217         logger.info("completed operation {}.{} outcome={} for {}", operation.getActor(), operation.getOperation(),
218                         operation.getResult(), getRequestId());
219
220         if (completeCallback != null) {
221             Util.runFunction(() -> completeCallback.accept(operation),
222                             "{}.{}: complete-callback threw an exception for {}", operation.getActor(),
223                             operation.getOperation(), getRequestId());
224         }
225     }
226
227     /**
228      * Validates the parameters.
229      *
230      * @return the validation result
231      */
232     public BeanValidationResult validate() {
233         return new BeanValidator().validateTop(ControlLoopOperationParams.class.getSimpleName(), this);
234     }
235 }