package com.griddynamics.jagger.master;
import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.JdkFutureAdapters;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.Service;
import com.google.common.util.concurrent.SettableFuture;
import com.griddynamics.jagger.coordinator.NodeId;
import com.griddynamics.jagger.coordinator.RemoteExecutor;
import com.griddynamics.jagger.master.configuration.Task;
import com.griddynamics.jagger.util.Nothing;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Created with IntelliJ IDEA.
* User: kgribov
* Date: 11/28/13
* Time: 12:57 PM
* To change this template use File | Settings | File Templates.
*/
public class ListenableService<T extends Task> implements Service {
private final ExecutorService executor;
private final String sessionId;
private final String taskId;
private final T task;
private final DistributionListener listener;
private final Map<NodeId, RemoteExecutor> remotes;
private final Service service;
public ListenableService(Service delegate, ExecutorService executor, String sessionId, String taskId, T task, DistributionListener listener, Map<NodeId, RemoteExecutor> remotes) {
this.executor = executor;
this.sessionId = sessionId;
this.taskId = taskId;
this.task = task;
this.listener = listener;
this.remotes = remotes;
this.service = delegate;
}
public ListenableFuture<State> start() {
ListenableFuture<Nothing> runListener = JdkFutureAdapters.listenInPoolThread(executor.submit(new Callable<Nothing>() {
@Override
public Nothing call() {
listener.onDistributionStarted(sessionId, taskId, task, remotes.keySet());
return Nothing.INSTANCE;
}
}));
return Futures.transform(runListener, new AsyncFunction<Nothing, State>() {
@Override
public ListenableFuture<State> apply(Nothing input) {
return doStart();
}
});
}
@Override
public State startAndWait() {
throw new UnsupportedOperationException();
}
@Override
public Service startAsync() {
throw new UnsupportedOperationException();
}
@Override
public boolean isRunning() {
return service.isRunning();
}
@Override
public State state() {
return service.state();
}
private ListenableFuture<State> doStart() {
return service.start();
}
public ListenableFuture<State> stop() {
ListenableFuture<State> stop = service.stop();
return Futures.transform(stop, new AsyncFunction<State, State>() {
@Override
public ListenableFuture<State> apply(final State input) {
final SettableFuture<State> result = SettableFuture.create();
executor.execute(new Runnable() {
@Override
public void run() {
try {
listener.onTaskDistributionCompleted(sessionId, taskId, task);
} finally {
result.set(input);
}
}
});
return result;
}
});
}
@Override
public State stopAndWait() {
throw new UnsupportedOperationException();
}
@Override
public Service stopAsync() {
throw new UnsupportedOperationException();
}
@Override
public void awaitRunning() {
throw new UnsupportedOperationException();
}
@Override
public void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException {
throw new UnsupportedOperationException();
}
@Override
public void awaitTerminated() {
throw new UnsupportedOperationException();
}
@Override
public void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException {
throw new UnsupportedOperationException();
}
@Override
public Throwable failureCause() {
return service.failureCause();
}
@Override
public void addListener(Listener listener, Executor executor) {
service.addListener(listener, executor);
}
}