package io.cattle.platform.process.common.handler;
import io.cattle.platform.engine.handler.HandlerResult;
import io.cattle.platform.engine.process.ProcessInstance;
import io.cattle.platform.engine.process.ProcessState;
import io.cattle.platform.eventing.EventCallOptions;
import io.cattle.platform.eventing.EventProgress;
import io.cattle.platform.eventing.EventService;
import io.cattle.platform.eventing.model.Event;
import io.cattle.platform.eventing.model.EventVO;
import io.cattle.platform.object.ObjectManager;
import io.cattle.platform.object.meta.ObjectMetaDataManager;
import io.cattle.platform.object.process.ObjectProcessManager;
import io.cattle.platform.object.util.ObjectUtils;
import io.cattle.platform.util.exception.ExecutionException;
import io.cattle.platform.util.type.CollectionUtils;
import io.cattle.platform.util.type.NamedUtils;
import io.cattle.platform.util.type.Priority;
import java.util.HashMap;
import java.util.Map;
import javax.inject.Inject;
import org.apache.commons.lang.StringUtils;
import org.jooq.exception.DataChangedException;
public class EventBasedProcessHandler extends AbstractObjectProcessHandler implements Priority {
public static String DEFAULT_NAME = "EventBased";
EventService eventService;
String[] processNames;
String eventName;
Integer retry;
Long timeoutMillis;
String onError;
int priority = Priority.SPECIFIC;
public EventBasedProcessHandler(EventService eventService, ObjectManager objectManager, ObjectProcessManager objectProcessManager,
ObjectMetaDataManager objectMetaDataManager) {
this();
this.eventService = eventService;
this.objectManager = objectManager;
this.objectProcessManager = objectProcessManager;
this.objectMetaDataManager = objectMetaDataManager;
}
public EventBasedProcessHandler() {
if (this.getClass() == EventBasedProcessHandler.class) {
setName(DEFAULT_NAME);
}
}
@Override
public String[] getProcessNames() {
if (DEFAULT_NAME.equals(getName())) {
return new String[0];
}
if (processNames == null) {
return new String[] { NamedUtils.toDotSeparated(getName()) };
}
return processNames;
}
@Override
public HandlerResult handle(ProcessState state, ProcessInstance process) {
final Object resource = state.getResource();
String type = objectManager.getType(resource);
if (type == null) {
type = resource.getClass().getName();
}
String idString = null;
Object id = ObjectUtils.getId(resource);
if (id != null) {
idString = id.toString();
}
String eventName = getEventName() == null ? process.getName() : getEventName();
Event request = EventVO.newEvent(eventName).withResourceId(idString).withResourceType(type).withData(state.getData());
EventCallOptions options = new EventCallOptions(retry, timeoutMillis);
options.setProgressIsKeepAlive(true);
options.setProgress(new EventProgress() {
@Override
public void progress(Event event) {
Map<String, Object> data = new HashMap<String, Object>();
String transitioning = event.getTransitioningMessage();
Integer progress = event.getTransitioningProgress();
if (transitioning != null) {
data.put(ObjectMetaDataManager.TRANSITIONING_MESSAGE_FIELD, transitioning);
}
if (progress != null) {
data.put(ObjectMetaDataManager.TRANSITIONING_PROGRESS_FIELD, progress);
}
if (data.size() > 0) {
DataChangedException dce = null;
for (int i = 0; i < 3 ; i++) {
try {
Object reloaded = objectManager.reload(resource);
objectManager.setFields(reloaded, data);
dce = null;
break;
} catch (DataChangedException e) {
dce = e;
}
}
if (dce != null) {
throw dce;
}
}
}
});
try {
Event response = eventService.callSync(request, options);
return postEvent(state, process, CollectionUtils.toMap(response.getData()));
} catch (ExecutionException e) {
if (!StringUtils.isEmpty(getOnError())) {
objectProcessManager.scheduleProcessInstance(getOnError(), state.getResource(), state.getData());
e.setResources(state.getResource());
}
throw e;
}
}
protected HandlerResult postEvent(ProcessState state, ProcessInstance process, Map<Object, Object> data) {
return new HandlerResult(data);
}
public EventService getEventService() {
return eventService;
}
@Inject
public void setEventService(EventService eventService) {
this.eventService = eventService;
}
@Override
public ObjectManager getObjectManager() {
return objectManager;
}
@Override
@Inject
public void setObjectManager(ObjectManager objectManager) {
this.objectManager = objectManager;
}
public void setProcessNames(String[] processNames) {
this.processNames = processNames;
}
public String getEventName() {
return eventName;
}
public void setEventName(String eventName) {
this.eventName = eventName;
}
public Integer getRetry() {
return retry;
}
public void setRetry(Integer retry) {
this.retry = retry;
}
public Long getTimeoutMillis() {
return timeoutMillis;
}
public void setTimeoutMillis(Long timeoutMillis) {
this.timeoutMillis = timeoutMillis;
}
@Override
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public String getOnError() {
return this.onError;
}
public void setOnError(String onError) {
this.onError = onError;
}
}