package tv.dyndns.kishibe.qmaclone.client; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; /** * 自動再試行機能付きの {@link AsyncCallback}. * * @author nodchip * * @param <T> */ public abstract class RetryAsyncCallback<T> implements AsyncCallback<T> { public static final int DEFAULT_MAX_RETRY = 3; public static final int DEFAULT_RETRY_WAIT = 1000; private final int maxRetry; private final int retryWaitMs; private int retryCount; public RetryAsyncCallback() { this(DEFAULT_MAX_RETRY); } public RetryAsyncCallback(int maxRetry) { this(maxRetry, DEFAULT_RETRY_WAIT); } public RetryAsyncCallback(int maxRetry, int retryWaitMs) { this.maxRetry = maxRetry; this.retryWaitMs = retryWaitMs; } @Override public void onSuccess(T result) { if (onReceived(result)) { return; } retry(null); } @Override public void onFailure(Throwable caught) { retry(caught); } public void start() { request(); } private void retry(Throwable caught) { if (++retryCount > maxRetry) { onHeavyFailure(caught); return; } onLightFailure(caught); new Timer() { @Override public void run() { request(); } }.schedule(Math.max(1, retryWaitMs)); } /** * RPCリクエストを記述する。 */ protected abstract void request(); /** * RPCリクエストの結果を受信した場合の処理を記述する * * @param result * 受信結果 * @return 受信に成功した場合はtrue。そうでない場合はfalse。 */ protected abstract boolean onReceived(T result); /** * 軽微なエラーが起こった場合の処理を記述する。RPCリクエストの記述は不要。 * * @param caught * 起こったエラー */ protected abstract void onLightFailure(Throwable caught); /** * 重大なエラーが起こった場合の処理を記述する。RPCリクエストはこれ以降行われない。 * * @param caught * 起こったエラー */ protected abstract void onHeavyFailure(Throwable caught); }