Skip to content

Commit

Permalink
Added fix for recovering from connection timeout issues in filter, as…
Browse files Browse the repository at this point in the history
… per #279, #197, #144.
  • Loading branch information
conor10 committed Dec 14, 2017
1 parent 4078cb3 commit 8c3e545
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 8 deletions.
44 changes: 38 additions & 6 deletions core/src/main/java/org/web3j/protocol/core/filters/Filter.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.web3j.protocol.Web3j;

import org.web3j.protocol.core.Request;
Expand All @@ -23,6 +26,8 @@
*/
public abstract class Filter<T> {

private static final Logger log = LoggerFactory.getLogger(Filter.class);

final Web3j web3j;
final Callback<T> callback;

Expand All @@ -43,13 +48,38 @@ public void run(ScheduledExecutorService scheduledExecutorService, long blockTim
}

filterId = ethFilter.getFilterId();

scheduledExecutorService.submit(this::getInitialFilterLogs);

// this runs in the caller thread as if any exceptions are encountered, we shouldn't
// proceed with creating the scheduled task below
getInitialFilterLogs();

/*
We want the filter to be resilient against client issues. On numerous occasions
users have reported socket timeout exceptions when connected over HTTP to Geth and
Parity clients. For examples, refer to
https://github.com/web3j/web3j/issues/144 and
https://github.com/ethereum/go-ethereum/issues/15243.
Hence we consume errors and log them as errors, allowing our polling for changes to
resume. The downside of this approach is that users will not be notified of
downstream connection issues. But given the intermittent nature of the connection
issues, this seems like a reasonable compromise.
The alternative approach would be to have another thread that blocks waiting on
schedule.get(), catching any Exceptions thrown, and passing them back up to the
caller. However, the user would then be required to recreate subscriptions manually
which isn't ideal given the aforementioned issues.
*/
schedule = scheduledExecutorService.scheduleAtFixedRate(
() -> this.pollFilter(ethFilter),
() -> {
try {
this.pollFilter(ethFilter);
} catch (Throwable e) {
// All exceptions must be caught, otherwise our job terminates without
// any notification
log.error("Error sending request", e);
}
},
0, blockTime, TimeUnit.MILLISECONDS);

} catch (IOException e) {
throwException(e);
}
Expand All @@ -66,6 +96,7 @@ private void getInitialFilterLogs() {
ethLog.setResult(Collections.emptyList());
}
process(ethLog.getLogs());

} catch (IOException e) {
throwException(e);
}
Expand All @@ -80,8 +111,9 @@ private void pollFilter(EthFilter ethFilter) {
}
if (ethLog.hasError()) {
throwException(ethFilter.getError());
} else {
process(ethLog.getLogs());
}
process(ethLog.getLogs());
}

abstract EthFilter sendRequest() throws IOException;
Expand Down
2 changes: 0 additions & 2 deletions core/src/main/java/org/web3j/protocol/http/HttpService.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
import org.slf4j.LoggerFactory;

import org.web3j.protocol.Service;
import org.web3j.protocol.core.Request;
import org.web3j.protocol.core.Response;
import org.web3j.protocol.exceptions.ClientConnectionException;

/**
Expand Down
Binary file modified docs/source/images/transaction_process.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/source/images/web3j_transaction.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 8c3e545

Please sign in to comment.