Skip to content

Instantly share code, notes, and snippets.

@komiya-atsushi
Created November 18, 2012 13:17
Show Gist options
  • Save komiya-atsushi/4105218 to your computer and use it in GitHub Desktop.
Save komiya-atsushi/4105218 to your computer and use it in GitHub Desktop.
Twitter のサーバ側エラーを検知した場合に、リクエストを自動的に再試行してくれる twitter4j.Twitter インタフェースなオブジェクト生成機能。
package biz.k11i.twitter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import twitter4j.Twitter;
import twitter4j.TwitterException;
/**
* Twitter のサーバ側エラーを検知した場合に、リクエストを自動的に再試行する機能を提供します。
*
* @author KOMIYA Atsushi
*/
public class TwitterRetryingProxy {
@SuppressWarnings("rawtypes")
private static final Class[] INTERFACES = { Twitter.class };
private TwitterRetryingProxy() {
// コンストラクタを隠蔽する
}
/**
* 指定された Twitter オブジェクトに対して、リクエストを再試行する機能を付与した Twitter オブジェクトを生成して返却します。
*
* @param original
* @param maxRetryCount
* @return
*/
public static Twitter create(Twitter original, int maxRetryCount) {
return (Twitter) Proxy.newProxyInstance(
Twitter.class.getClassLoader(),
INTERFACES,
new RetryingTwitterInvocationHandler(original, maxRetryCount));
}
static class RetryingTwitterInvocationHandler implements InvocationHandler {
private final int MAX_RETRY_COUNT;
private Twitter original;
RetryingTwitterInvocationHandler(Twitter original, int maxRetryCount) {
this.original = original;
this.MAX_RETRY_COUNT = maxRetryCount;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
int retryCount = 0;
long sleepingMillis = 2000;
while (true) {
try {
return method.invoke(original, args);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof TwitterException) {
TwitterException te = (TwitterException) e.getCause();
int statusCode = te.getStatusCode();
// 再試行をするのはサーバエラーの場合のみ
if (500 <= statusCode && statusCode < 600) {
if (++retryCount >= MAX_RETRY_COUNT) {
throw te;
}
sleepingMillis = sleepExponentially(sleepingMillis);
continue;
}
throw te;
}
throw e;
}
}
}
private long sleepExponentially(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return millis * 2;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment