Retryã¦ã¼ãã£ãªãã£
çããæ±ãã¦SVNãªãã¸ããªãå¾å¾ãã¦ããããææ¸ããæãããã³ã¼ããçºè¦ããã®ã§å ¬éãã¦ã¿ã¾ãã
- ä»»æã®å¦çãå®è¡ãã
- å¦çã®æ»ãå¤ã¾ãã¯ä¾å¤ãè©ä¾¡ãã¦ããªãã©ã¤ããå¿ è¦ãããå ´åã
- æå®ãããåæ°ã ãå試è¡ãã
ããã®ãã¦ã¼ãã£ãªãã£ã§ãã
/** * ãªãã©ã¤ãè¡ãªãããã®æ©è½ã»ããã */ class Retry { /** * ãªãã©ã¤ããã * * <ul> * <li>{@link Logic}ãå®è¡ããçºçããä¾å¤ã¾ãã¯æ»ãå¤ããªãã©ã¤å¯¾è±¡ã§ããå ´åããªãã©ã¤ããã</li> * <li>ãªãã©ã¤å¯¾è±¡ãã©ããã¯ã{@link Condition}ã§è©ä¾¡ããã</li> * <li> * æå®åæ°ãªãã©ã¤ãã¦ãã{@link Logic}ããªãã©ã¤ããã¹ãçµæãè¿ãå ´åã * æå¾ã®å®è¡çµæãè¿ããã¾ãã¯ãæå¾ã«çºçããä¾å¤ãã¹ãã¼ããã * </li> * <li> * {@link Logic}ã®æ»ãå¤ãã¾ãã¯çºçããä¾å¤ããªãã©ã¤å¯¾è±¡ã§ãªãå ´åã * æ»ãå¤ããã®ã¾ã¾è¿ã(ã¾ãã¯ä¾å¤ãã¹ãã¼ã)ãå³åº§ã«å¾©å¸°ããã * </li> * </ul> * * @param <R> æ»ãå¤å * @param <E> çºçããä¾å¤ã®åºåºã¯ã©ã¹ * * @param retryCount ãªãã©ã¤åæ° * @param condition ãªãã©ã¤æ¡ä»¶ * @param logic å¦ç * @return æçµçãªå¦çã®å®è¡çµæ * @throws E ãªãã©ã¤ãã¦ãçºçããæå¾ã®ä¾å¤ã */ static final <R, E extends Exception> R retry( int retryCount, Condition<R, E> condition, Logic<R, E> logic ) throws E { // æå¾ã«å®è¡ããå¦çã¨çºçããä¾å¤ã // ãªãã©ã¤åæ°ãæå®åæ°ãè¶ ããå ´åããã®å¤ãè¿ãã R lastresult = null; E lastException = null; for ( int i = 0; i <= retryCount; i++ ) { try { lastException = null; lastresult = null; lastresult = logic.call(i); if ( !condition.isRetry(lastresult) ) { return lastresult; } } catch ( ContinueException e ) { // ãªãã©ã¤ } catch ( BreakException e ) { // ãªãã©ã¤ãå³å»ä¸æ¢ try { return (R) e.get(); } catch ( Throwable t ) { if ( t instanceof RuntimeException ) { throw (RuntimeException) t; } if ( t instanceof Error ) { throw (Error) t; } throw (E) t; } } catch ( Exception ex ) { // catch ã§åãã©ã¡ã¼ã¿ã¯ä½¿ããªãã®ã§ä»æ¹ãªãã lastException = (E) ex; if ( !condition.isRetry((E) ex) ) { throw (E) ex; } } } // ãªãã©ã¤åæ°ãæå®å¤ãè¶ ããå ´åãæå¾ã®å®è¡çµæãè¿ãã if ( lastException != null ) { throw lastException; } return lastresult; } /** * ãªãã©ã¤ããæ¡ä»¶ * * @param <R> æ»ãå¤å * @param <E> çºçããä¾å¤ã®åºåºã¯ã©ã¹ */ static interface Condition<R, E extends Exception> { /** * æ£å¸¸çµäºããçµæããã¨ã«ããªãã©ã¤ãããè©ä¾¡ããã * @param result å®è¡çµæ * @return ãªãã©ã¤ããå ´åtrue */ boolean isRetry( R result ); /** * çºçããä¾å¤ããã¨ã«ããªãã©ã¤ãããè©ä¾¡ããã * @param error çºçããä¾å¤ * @return ãªãã©ã¤ããå ´åtrue */ boolean isRetry( E error ); } /** * ãªãã©ã¤ããå¦ç * * @param <R> æ»ãå¤å * @param <E> çºçããä¾å¤ã®åºåºã¯ã©ã¹ */ static interface Logic<R, E extends Exception> { /** * å¦çãå®è¡ * @param count ãªãã©ã¤ããåæ° * @return å®è¡çµæ * @throws E çºçããä¾å¤ */ R call( int count ) throws E; } /** * ãªãã©ã¤ããå¦çã®æ½è±¡åºåºã¯ã©ã¹ * * @param <R> æ»ãå¤å * @param <E> çºçããä¾å¤ã®åºåºã¯ã©ã¹ */ static abstract class AbstractLogic<R, E extends Exception> implements Logic<R, E> { /** * å¦çãä¸æããã * @param result å¦çã®æ»ãå¤ */ void break_(R... result) { throw new BreakException( result != null && result.length > 0 ? result[0] : null ); } /** * å¦çãä¸æããã * @param error å¦çã§çºçããã¨ã©ã¼ */ void break_( E error ) { throw new BreakException( error ); } /** * 以éã®å¦çãä¸æãã次ã®ã«ã¼ãã¸ã */ void continue_() { throw new ContinueException(); } } /** * å¦çã®ä¸æã示ãä¾å¤ * ä¾å¤æ´¾çã¯ã©ã¹ã¯ãã©ã¡ã¼ã¿åã§ããªã */ private static final class BreakException extends RuntimeException { final Object returnValue; final Throwable t; BreakException( Object returnValue ) { super(); this.returnValue = returnValue; this.t = null; } BreakException( Throwable t ) { super(t); this.returnValue = null; this.t = t; } /** * çµæãåå¾ããã * @return çµæ * @throws Throwable å¦çãä¾å¤ã«ããä¸æãããå ´åã */ Object get() throws Throwable { if ( t != null ) throw t; return returnValue; } }; /** * å¦çã®ç¶ç¶ã示ãä¾å¤ */ private static final class ContinueException extends RuntimeException {}; }
使ãæ¹ã
// å¦çä¸ã§å®è¡æä¾å¤ãçºçããããªãã©ã¤ããæ¡ä»¶ Condition<String, Exception> ifRuntimeException = new Condition<String, Exception>() { public boolean isRetry ( String result ) { return false; } public boolean isRetry ( Exception error ) { return error instanceof RuntimeException; } }; // Logicã®å¦çãå®è¡ããå®è¡æä¾å¤ãçºçããå ´åã¯ã5åã¾ã§ãªãã©ã¤ããã String result = retry( 5, ifRuntimeException, new AbstractLogic<String, Exception>() { public String call ( int count ) throws Exception { // å¦ç System.out.println( "count : " + count ); if ( count < 3 ) throw new RuntimeException("test"); return String.valueOf( count ); } } ); System.out.println( "result : " + result );
å®è¡çµæã§ãã3åå®è¡æä¾å¤ãçºçããã®ã§å試è¡ãã4åç®ã®çµæãè¿ãã¦ãã¾ãã
count : 0 count : 1 count : 2 count : 3 result : 3
ã¨ããã§ããã£ããæ±ç¨çã«ä½ã£ãã®ã«ãã«ã¬ã³ãã®ã½ã¼ã¹ã«ã¯ã·ã¹ãã ä¾åã®ã³ã¼ã(ãªãã©ã¤ãããâÃãµã¼ãã¹ãåèµ·åãããã¨ã)ã追å ããã¦ãã¦ãã¡ãããããªãããã¸ãã¯å ã®å¦çã¨ãã¦å®è£ ããã®ã§ã¯åé¡ããã£ããã ããã?