package org.ovirt.engine.core.bll.tasks; import java.util.Map; import org.ovirt.engine.core.common.businessentities.CommandEntity; import org.ovirt.engine.core.compat.Guid; import org.ovirt.vdsm.jsonrpc.client.events.EventSubscriber; import org.reactivestreams.Subscription; public class CoCoEventSubscriber extends EventSubscriber { private Subscription subscription; private CommandEntity commandEntity; private CommandsRepository commandsRepository; public CoCoEventSubscriber(String subscriptionId, CommandEntity commandEntity, CommandsRepository commandsRepository) { super(subscriptionId); this.commandEntity = commandEntity; this.commandsRepository = commandsRepository; } @Override public void onSubscribe(Subscription subscription) { this.subscription = subscription; subscription.request(1); } @Override public void onNext(Map<String, Object> eventData) { // Invokes command's callback for processing the event processEvent(eventData); } @Override public void onError(Throwable throwable) { // communication issue is delivered as a message so we need to request for more subscription.request(1); } @Override public void onComplete() { } public void cancel() { subscription.cancel(); } /** * Processes the event of the current subscription by invoking the {@code CommandCallback.onEvent} of the associated * command. After the event is processed, the callback can be terminated from the {@code CommandCallback.onEvent} or * continue to the rest of command's callback execution. * * @param eventData * the requested data for the event processing */ private void processEvent(Map<String, Object> eventData) { Guid cmdId = commandEntity.getId(); CallbackTiming callbackTiming = commandsRepository.getCallbackTiming(cmdId); if (callbackTiming == null) { return; } try { // TODO there is a race condition between processing the callback here and by the polling, in case of an // event which has arrived during its timeout treatment by CommandCallbacksPoller. // Once Bug 1334926 is implemented, this code will be changed to mark the callback to be processed, and // the actual processing will be done by the CommandCallbacksPoller which will be the responsible to invoke // the CommandCallback.onEvent() on thread from a dedicated thread pool callbackTiming.getCallback().onEvent(cmdId, commandsRepository.getChildCommandIds(cmdId), eventData); } finally { subscription.cancel(); commandsRepository.removeEventSubscription(cmdId); CommandEntity commandEntityFromCache = commandsRepository.getCommandEntity(cmdId); if (commandEntityFromCache != null) { commandEntityFromCache.setWaitingForEvent(false); } } } }