Created
November 18, 2012 13:17
-
-
Save komiya-atsushi/4105218 to your computer and use it in GitHub Desktop.
Twitter のサーバ側エラーを検知した場合に、リクエストを自動的に再試行してくれる twitter4j.Twitter インタフェースなオブジェクト生成機能。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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