package io.bitsquare.btc.blockchain;
import com.google.common.util.concurrent.*;
import io.bitsquare.btc.blockchain.providers.FeeProvider;
import io.bitsquare.common.Timer;
import io.bitsquare.common.UserThread;
import io.bitsquare.common.util.Utilities;
import io.bitsquare.http.HttpException;
import org.bitcoinj.core.Coin;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
class GetFeeRequest {
private static final Logger log = LoggerFactory.getLogger(GetFeeRequest.class);
private static final ListeningExecutorService executorService = Utilities.getListeningExecutorService("GetFeeRequest", 3, 5, 10 * 60);
private Timer timer;
private int faults;
public GetFeeRequest() {
}
public SettableFuture<Coin> request(String transactionId, FeeProvider provider) {
final SettableFuture<Coin> resultFuture = SettableFuture.create();
return request(transactionId, provider, resultFuture);
}
private SettableFuture<Coin> request(String transactionId, FeeProvider provider, SettableFuture<Coin> resultFuture) {
ListenableFuture<Coin> future = executorService.submit(() -> {
Thread.currentThread().setName("requestFee-" + provider.toString());
try {
return provider.getFee(transactionId);
} catch (IOException | HttpException e) {
log.debug("Fee request failed for tx {} from provider {}\n" +
"That is expected if the tx was not propagated yet to the provider.\n" +
"error={}",
transactionId, provider, e.getMessage());
throw e;
}
});
Futures.addCallback(future, new FutureCallback<Coin>() {
public void onSuccess(Coin fee) {
log.debug("Received fee of {}\nfor tx {}\nfrom provider {}", fee.toFriendlyString(), transactionId, provider);
resultFuture.set(fee);
}
public void onFailure(@NotNull Throwable throwable) {
if (timer == null) {
timer = UserThread.runAfter(() -> {
stopTimer();
faults++;
if (!resultFuture.isDone()) {
if (faults < 4) {
request(transactionId, provider, resultFuture);
} else {
resultFuture.setException(throwable);
}
} else {
log.debug("Got an error after a successful result. " +
"That might happen when we get a delayed response from a timer request.");
}
}, 1 + faults);
} else {
log.warn("Timer was not null");
}
}
});
return resultFuture;
}
private void stopTimer() {
timer.stop();
timer = null;
}
}