From ec2204f8228ef6bd0a2eb977db2ba413d2c0c85d Mon Sep 17 00:00:00 2001 From: mitimugdho Date: Tue, 30 Jun 2026 15:01:37 +0600 Subject: [PATCH 1/3] miti --- .DS_Store | Bin 0 -> 10244 bytes core/.DS_Store | Bin 0 -> 6148 bytes core/src/.DS_Store | Bin 0 -> 8196 bytes core/src/main/.DS_Store | Bin 0 -> 8196 bytes core/src/main/java/.DS_Store | Bin 0 -> 6148 bytes core/src/main/java/dev/.DS_Store | Bin 0 -> 6148 bytes core/src/main/java/dev/failsafe/.DS_Store | Bin 0 -> 6148 bytes .../failsafe/internal/CircuitBreakerImpl.java | 52 ++-- core/src/test/.DS_Store | Bin 0 -> 6148 bytes core/src/test/java/.DS_Store | Bin 0 -> 6148 bytes core/src/test/java/dev/.DS_Store | Bin 0 -> 6148 bytes pmd-report.txt | 229 ++++++++++++++++++ 12 files changed, 265 insertions(+), 16 deletions(-) create mode 100644 .DS_Store create mode 100644 core/.DS_Store create mode 100644 core/src/.DS_Store create mode 100644 core/src/main/.DS_Store create mode 100644 core/src/main/java/.DS_Store create mode 100644 core/src/main/java/dev/.DS_Store create mode 100644 core/src/main/java/dev/failsafe/.DS_Store create mode 100644 core/src/test/.DS_Store create mode 100644 core/src/test/java/.DS_Store create mode 100644 core/src/test/java/dev/.DS_Store create mode 100644 pmd-report.txt diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..f04422db5e3bc5f46bedf6d81d89d021566270d4 GIT binary patch literal 10244 zcmeHNJ8u&~5S~c_wh4htNPzH=PPjoL5+=Nb5RL&sgixY53JD3AJ9}e}oNvwDIRT!@YNbN} zHUK243$!-V@Pj7SMPJq0^h}BnNgtxB>vNZ`p1ajmyUm1Qz%XDKFbo(53H@PG>k4J+pg|r12s>z6Hj*tN5ZW5E8tV#ag&HbVLZyoO zh=EF-=54(%tFf+7sRQc62WrcxPbes@)BSC^9WblVjD`Wjz-k7>*}WZH@E~v(R-WH| zFN!mnci7h6v0-B(kxFzXuH|p?g?#M9wJ7I=)8cBJbKh;qjyvJ8g@V<4mItxp1uT>b zUWw6`nJZpU;tM%m3rdmH&8vk}Dw!%+I~NxR4-F33gP9Xc1NP#{!OVbtYIXN)>+bFD z>+9RTV`qQQ?mY!-o9h(k%At79v)t!l&abh8wKXDdhl@NI4cR<-IT^D%ao)Q}OFbu*?ls?WnLiTbcpUS}q(@$eCzmGkRj23$<@A}) zipo?vyI)Bbq#NuedmEBQOusDJQXUVS3L~XawUW+W(p!>n0EQqBGjJQ~@Ccs3Gk67W z;Uj#3Z`g&~aUUMQ0X&MwF^fYuhSPWh9lWLV+ZwNUufCrKj7ZP{JD(2&p9f`{5xYB} z2pmFS>m-ny{+Li+zoFcG$t}U0fC>e332NX2gJ_+Ebc{Xp8#)`Jey(zt)ds>=_0O18c|t zcAU$f%aOrG&85}0sI}YFZ%`La?5iu3Dm2J)JfSSd(}gI<%R&;(Wk{Bdk3Jt c_BVeF_{*g%bN-kA82j}atvUb0A36Vj2gaTN=l}o! literal 0 HcmV?d00001 diff --git a/core/.DS_Store b/core/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..0fbb35f80529e23eb02d8e0ed432e084f116f3be GIT binary patch literal 6148 zcmeHKO-~a+7@mP@w;-}Wix@T8*oz5GEcH7cTo#NW9w02i62P*%9qP(PC$biN% zGX&jFg!_5xlL2KJ1jKxdq~%AArje>EhXnwg(tH1$GCVv!Km350As z2x*;l9M-1wMC7{Ck;@smnmM(cc9OR5b@$&8E+D_D@ z?75^5!)_yFL}3qJfTF4igI%>7;rD(^R`ba;RXs*-X!z8~=}~iRd}1s=RwxuE&rF>i zKX<-nPWWE1(}?*x=UBvICu)ZZ#j!^l#M#@7JfB31)M07Ln$-}h;42qXx-BmVX`^`Oi{vm@v@c1`M8zJh zM!u&h#KpIPCG-{QH3=jwNl($fuR;tojb@RHHqaB)MK94S^cuZGAJAv?6@9}acoJX4 z)3}7M;Tzb-vv?V=<1Osr$1;DQ_lhs5@f6?$6!nUC-Izvb9w3xp31Hc6hq|(zsk>V$5|W%e(93|R-D6M(8(d(A>vyN&xj~rA zeIhlcrrd1UoSr6tzu}0&7ffWtK!!Z=bqD%ZD-k~t+J7t;ViUWM*S$jtx|MZ zd*ZSxZxwixRf8zDC=JPEB3U*jc6akr`K+1G-QCNYyZ7?Btad_$Om zW$FirJu#&f+xKl&qlKMy&vvLc&k8&YdA;Of7GmeolEsEyaak?%;D;nLnX#@($$(6U z-$be-DI}SX6*H2Tm|dqBv>+`R>#=f4z$8pV5!T=ZwBaqhgZJ7k%b&Rzscek3k3&0tipdVOII* z!+e?#v%1J#hgltX4Vr;tV4z>lIU(x*hev<^KZcd{l$rs}z)4|%#Ab`L1>8;NeXDz8 zqSiLCZ(tWq__ZZQAvi?kIATUBF0kKmWUc`|Kvl!$$OdA&;RH&=;3cM F@EeL9nH~TD literal 0 HcmV?d00001 diff --git a/core/src/main/.DS_Store b/core/src/main/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..faf983f6b2e87ff484b3705a7f3a6632332b001d GIT binary patch literal 8196 zcmeHMPfrs;6n_KNwj#1Xi#2Mpu@@7XSnB_Ha48r=JV022C4gnOUFyPirtWTAk&yJP zAHWab2k`1qKY$*+dhiQ)@vLulra)Rb5hKBwWajtw&3iNRemkArw*>%FY*wcLG60ak z%26A_<`0GU^V(Miq~ZqWsaRE`6Xh`e`#2zd}xFQNyB2x?^ z+)=MfJ40eepl}BwlMf(li?S|(D zVLtzr3=GE3oQ=nm@uB#-`JA=Q&W#-IXnS*>&1wEj7bvXt~t!BL}zY zpvl@(msVN3$eOeoM82lzNG21>vX4}S( zOJkR>l(li&s%+PMzS0@yF~8_Fow7C(V7zk`Mi+dig>jZb=VfTRudr*Z$6?W_K08n? z?KIFPb)bj_ee639U9I_Ub$)X*aKh3dd4u)qynMpxFN*+Zv3M>iSH$X77m z;9bG8;|GX+KBX1Q_bpm;iaYC`Wjo$HEwV6V^^%KG@RdhXnhmSs(pvW64?$)!Yg`wS z2H7sZiBwmTNU|R*dL%DVtL~uFg6PQ_Pozl#CSe*(Sc4bPfw%Au-oq#O0^i{${363- zf?Ok$Bu8$OyTl;VWRa|r4Puck;Xly5$yeog5=el;{-$l2KJ^%_p^n?fyPFxRz@TzU zwscQaYGa??joovrd$zay2`Equ9GihbF+zst|BsIT{(tOw)BuVB#lXpBfW&6a*&?p5 z`@Yq?RGw?=SU0fp!tFW&BNuFS KFI4k)8Tbtb9w01%62P+C4s~TaQ+KzmNJx6t zAK(x02YB_UKR}OOJ@^N_c-D758o(+?V|3nR=6U!1n3?z4?92{A2$x#58H6l^kO7Tj zY6!Yt2>0{WCj-hd2#EO@anlc(4^MCXW?!^6Xa+O`e;Wh*+Z{wTL{QuB9Q}U7AWjN} zPk3N3b?S6FZKj9QTkd1laT70T#U(G=;7==zg?>->{MCSTDpqEW(ZmZVi9|wBBM`E= z7SI~&lvs<_Vv*}ghiMvS#hTjRFU}P6cCm2#AaC#ADHihf^=mf|4ooAPyLxxIvKuxi zdm-t=u-gb3QP_i*pr~qsYFq6__=De+)qJ)rRgYl~4WAh~J8F%MPmE>8vf1q9xvBHx z7cN$;3E!*k)+4^oITo_06t+mk8jYdag({;<5otq}<%B#-+~7I5#(zp!CbdV0rj@-W z#AFT)V$cT>A#|f21+~SUotPx$BlfjMUhAAq_npcdOiskX^ABXYm@`1g0Eam={CJ;K}18-vwKau$Zy;pomji&&|pr}{eb|V@xS_exn`gpK@I*|cInlXH0 zly+(cGz0%51AKq5p>cE+b|s3f13Ga908D{d24`)@PJ^M3Mf;tx?*6N z4t86`ISRWHWjexQW*A4!jMWVVi`l_$i*SS;iMrPeXa4 literal 0 HcmV?d00001 diff --git a/core/src/main/java/dev/.DS_Store b/core/src/main/java/dev/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..b6ff5e04794b1b2c42f5090abe1c4a096e8ebf3d GIT binary patch literal 6148 zcmeHKUr*Ce6h9ZHYeA&IK$K`2_hJHxV-lk=hB`2cK7f?q2;gkDyV20~&bDJBlI&R% zKY$;=&%mQEeg$KE@eBCilh2;}X91l0XpHnE_x?`LzuWU`+S>~Nq|mHP0~i3H;oz9+ z!|4~o{d{yukFxY45>X=p2dY5bR@CT-=hkG2iXzj=Sp7R>{cBu^@K5fQBN$ zt56KtcDpYEgib9=_O-)Z!bTcpEC2g8~an{-pzb&%AC1&eScrqMzdFM zEtj_adca;uA_;zXgbXO`z-v^x`tr&<4cQm@)amPsVW`eDy|4ewz}Z1#Xn15OGc-Cn zc5eLqg^7uaC1b>O%GEj<;kIGWw(Jb znL~r9buXkeSg(a%WwBa~Xk0v^ua%6!s2noiUt*CLdn{Pnh>+}snAR79D#I0bkm$t* zcSWl-j1aqWifc|7Izf#Vb~k;;rT$`2U~$aqJd#(#MwUX#D~Yx3hEw)}T6XrEWHW0m zb(AYoF(4}yfULD6RV~voDJ0qVWmD)Yfm5ftp0yq-mj;t?2OfY8ThM|x@D|>|0epbZ z@D;w36d5Cz$t0N}x5+HIPactFQYJomMnV$F3O$|Yeo0kSKwhHK_1t&tFz{JWLtiKF zc-qOlQe0^LC$s&e>x6-Xfj=<7zYiu3j+Vl|Z?ZEx06>bZ+9ZGp02yoo zQ+=q85D^!xOM0}Y7m>(00$|{P@9u=nuF;7jVIX1PUt>UgyBYBCyN!Utq3_rAxr?!P zZqxU|D4+jCdU{hQPNvgFx<9>Mddhc7krTDTq7$r&-V*1&8{3Y%?9rWynVsP*ay&)@ znc&qZ4q1Ebu^Qhg@)oOwGPk4xhLJHU=4iWJm@G_Kh5U{E39Egxke{%ou3g{XH!>r+ ztG5;_TYiJ_mx@S&`;L^;8e@2cMps>4b-StRBA?^BzM7`4EMxTbpE`YJz#JSJ9?TAo zjGR3;dj7)L#j%Px>^jx0dLZ6-hWk7y`YpOz54>8b=~O*dFGuuwRPy#{#T@!==pwB> zIdCoQHgQb$z#*r*7f{ONeDj-|A&tt1?3Ic+5LN^3`wKkuB9F6`wGjE9i)dqxZE}3# zHgY}R6rpgL1|ecsPI<)%0*BRUad+K!T%LtIn9o@q zV{u-baGX(dk?B9qBqX&b3?vL3$$;1&ENlX8jU9z@>p&&10Ej7cOF>)QB}9&;(bm{e zh!GT`QV~@u!ChPVWjgvT-M2M%6smL}^2s=lelpQF6r$3BSaLWJTVbLT1`-B-WkCG< zqnP6Szx(I=zZ{gPgn@*C|C0fdnk~&1u{M3Sc2z0PS_|6-HX&kMN1;qXrH^B2h@*HE cn-q*$!a%e&b`+uqCHWDMG$blv;IA_96EgzNx&QzG literal 0 HcmV?d00001 diff --git a/core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java b/core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java index 1169adca..a78f54f7 100644 --- a/core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java +++ b/core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java @@ -24,6 +24,8 @@ import java.time.Duration; import java.util.concurrent.atomic.AtomicReference; +import java.util.logging.Level; +import java.util.logging.Logger; /** * A {@link CircuitBreaker} implementation. @@ -34,6 +36,8 @@ * @see CircuitBreakerOpenException */ public class CircuitBreakerImpl implements CircuitBreaker, FailurePolicy, DelayablePolicy { + private static final Logger LOGGER = Logger.getLogger(CircuitBreakerImpl.class.getName()); + private final CircuitBreakerConfig config; /** Writes guarded by "this" */ @@ -154,26 +158,15 @@ protected void recordResult(R result, Throwable exception) { /** * Transitions to the {@code newState} if not already in that state and calls any associated event listener. */ - protected void transitionTo(State newState, EventListener listener, + protected void transitionTo(State newState, EventListener listener, /*extracted method for solo responsibility-MITI*/ ExecutionContext context) { boolean transitioned = false; State currentState; synchronized (this) { currentState = getState(); - if (!getState().equals(newState)) { - switch (newState) { - case CLOSED: - state.set(new ClosedState<>(this)); - break; - case OPEN: - Duration computedDelay = computeDelay(context); - state.set(new OpenState<>(this, state.get(), computedDelay != null ? computedDelay : config.getDelay())); - break; - case HALF_OPEN: - state.set(new HalfOpenState<>(this)); - break; - } + if (!currentState.equals(newState)) { + state.set(createState(newState, context)); transitioned = true; } } @@ -181,11 +174,38 @@ protected void transitionTo(State newState, EventListener + * Extracting this from {@link #transitionTo} resolves the prior non-exhaustive {@code switch} (PMD: + * NonExhaustiveSwitch) by making {@link State} coverage explicit and enforced at compile time, and gives + * state-construction a single, testable seam independent of transition/locking concerns. + * + * @throws IllegalArgumentException if {@code newState} is not a recognized transition target + */ + protected CircuitState createState(State newState, ExecutionContext context) { + switch (newState) { + case CLOSED: + return new ClosedState<>(this); + case OPEN: + Duration computedDelay = computeDelay(context); + return new OpenState<>(this, state.get(), computedDelay != null ? computedDelay : config.getDelay()); + case HALF_OPEN: + return new HalfOpenState<>(this); + default: + throw new IllegalArgumentException("Unexpected circuit breaker state: " + newState); + } + } + /** * Records an execution failure. */ @@ -205,4 +225,4 @@ protected void open(ExecutionContext context) { public PolicyExecutor toExecutor(int policyIndex) { return new CircuitBreakerExecutor<>(this, policyIndex); } -} +} \ No newline at end of file diff --git a/core/src/test/.DS_Store b/core/src/test/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..28b3405f6e8f4e0e93ae3e667b4bd4b7ba4a97c7 GIT binary patch literal 6148 zcmeHKO-~a+7@mP@TM${GMU0wk?8Ss8miiqJE(^vG4-l4U31Hc6hq|zxsk_@&BqTlS z5AX;01H5|FAD~CC9{dAdJnK6j%ZHV#F*l!3-E zH3Z#ng!_5xlL2KJ1jKv{uN$?zfO+uzt}j{}Gy|G}zl{ODc2j5@xu}EOqwCje1%4El zN}ut-VCvNAbUK?JPH#9*S=Wi(xEWHf&<@(9YK%ru??R2yrI2)>&Pq(4$BzF3T;snaER*_^L(|G` z3u1DI1~KS^kPy1o2>trv)>cH~$`O5)&sGar5G=9Ck9|g0*Tw8HX)e$$1~c+ESZr}u z^oWEJU|&vU)eS?JHi*5u5x5=+7OBnRm^CXtRKed|OzE`Tnok>rd*39B*@AUNY6dDK z#Ab4drVtn2*G!?WP`61SX-Rqt)g6Jc1|j zWju|G_y)d(Ej){t@fzO5F5Z^;1Ib6eq{dT#BTx=La>og2z-R+(N&N9}{d58YimuG? z34U$X3}^=aUk3R8U_#?)DeOrUTL*OF3ILb_vk=hvU4rMB3N3{_iQoajG8Is!Vs*v9 zG9B!uinA2b9w01%62P+C4s~TaQ+KzmNJx6t zAK(x02YB_UKR}OOJ@^N_c-D758o(+?V|3nR=6U!1n3?z4?92{A2$x#58H6l^kO7Tj zY6!Yt2>0{WCj-hd2#EO@anlc(4^MCXW?!^6Xa+O`e;Wh*+Z{wTL{QuB9Q}U7AWjN} zPk3N3b?S6FZKj9QTkd1laT70T#U(G=;7==zg?>->{MCSTDpqEW(ZmZVi9|wBBM`E= z7SI~&lvs<_Vv*}ghiMvS#hTjRFU}P6cCm2#AaC#ADHihf^=mf|4ooAPyLxxIvKuxi zdm-t=u-gb3QP_i*pr~qsYFq6__=De+)qJ)rRgYl~4WAh~J8F%MPmE>8vf1q9xvBHx z7cN$;3E!*k)+4^oITo_06t+mk8jYdag({;<5otq}<%B#-+~7I5#(zp!CbdV0rj@-W z#AFT)V$cT>A#|f21+~SUotPx$BlfjMUhAAq_npcdOiskX^ABXYm@`1g0Eam={CJ;K}18-vwKau$Zy;pomji&&|pr}{eb|V@xS_exn`gpK@I*|cInlXH0 zly+(cGz0%51AKq5p>cE+b|s3f13Ga908D{d24`)@PJ^M3Mf;tx?*6N z4t86`ISRWHWjexQW*A4!jMWVVi`l_$i*SS;iMrPeXa4 literal 0 HcmV?d00001 diff --git a/core/src/test/java/dev/.DS_Store b/core/src/test/java/dev/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..97ac27be3230f89af75a6a9910f2603c7d0db6d3 GIT binary patch literal 6148 zcmeHK&2G~`5T0!Vaau~r z&hP*{01v>GBfJ1d#Ek?iNU2?$1~37@z`-#! zfYUF8`}ydRK4s}gBw~#iT&M%}w&GS#v^Ho4Gz0${1N_}J@SSzRhXD4yzh1yR^u6_3 zfgdM@!bj5ApE`0hozA2O(`(K;+j0^&X~!iuTH#lVj0Ij-cfBQ_ZdJ_e3=0$24{0P4 z{2IlO)dzl9V_PNG4r{T!nNJJwR62#$Xk~#UfJEv7~{DM zH||$9f@a8GNFoV-cZ3Wn?7~Y_diwIKn=RQF`PA*}vuUc%jLg8`v7zI`=E&&SNOoj= zeB#99$y1}J&s5AY&#i7WB7Vm+EMQS7Xw!;09An>eRTeHpbQAk6C-iCJ_|MQa`cuMv zT6?%>THJ17Om@#87QGWu8m=@Vzcyd5$22ML)0cU*YQ%zIfyI8}vv7G;R8MGgF03=G z$nRjj#a;0djbg-}obs|8MQ+%jrR}xA^=L33mRORoX4%Is_??TAPRp(OVIz0*t7J2i zv(HP-gj|>4oW0%=x{>Xg6q4M#swMQr&}~x8UXY%geNTlLFa@{3fmL_{9e4$=;SIcp z5AX%P!FMu5CdfH5Me^h_xk_v@NA8jpQX@WjOk%l0U-!A6RVykW&r#`l?wd{&1}to# zubX!;?QmWxE{ws$*}m>tGoTsx0|Wf~VBz3sE9^)VpAMYF5dblTW+ABavjoqv6xs?q z648S~WGbReCF+PlWIEa{6=y5#NR;V7L}gq@RVM0$LPT}6TOu5YEm6;!0nNZc2Kc`} ziplr?+rK~miy%E|1~dczCj%rk>&%w0H?_C+bjkNx3&$fITzFhZqDa9>ZO204Tk#|g bA?UNXf@mx3NJI;Y{t*x~=t(p1R~h&LzTwVK literal 0 HcmV?d00001 diff --git a/pmd-report.txt b/pmd-report.txt new file mode 100644 index 00000000..3a2cd2d3 --- /dev/null +++ b/pmd-report.txt @@ -0,0 +1,229 @@ +core/src/main/java/dev/failsafe/AsyncExecutionImpl.java:19: UnnecessaryImport: Unused import 'dev.failsafe.spi.*' +core/src/main/java/dev/failsafe/AsyncExecutionImpl.java:45: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/AsyncExecutionImpl.java:56: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/AsyncExecutionImpl.java:148: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/AsyncExecutionImpl.java:153: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/AsyncExecutionImpl.java:156: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/Bulkhead.java:92: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/CallImpl.java:25: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/CallImpl.java:40: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/CircuitBreaker.java:121: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/CircuitBreakerConfig.java:50: UncommentedEmptyConstructor: Document empty constructor +core/src/main/java/dev/failsafe/DelayablePolicyConfig.java:34: UncommentedEmptyConstructor: Document empty constructor +core/src/main/java/dev/failsafe/ExecutionImpl.java:43: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/ExecutionImpl.java:56: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/ExecutionImpl.java:58: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/ExecutionImpl.java:60: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/ExecutionImpl.java:62: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/ExecutionImpl.java:64: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/ExecutionImpl.java:66: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/ExecutionImpl.java:68: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/ExecutionImpl.java:126: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/ExecutionImpl.java:181: EmptyCatchBlock: Avoid empty catch blocks +core/src/main/java/dev/failsafe/ExecutionImpl.java:181: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/ExecutionImpl.java:195: EmptyCatchBlock: Avoid empty catch blocks +core/src/main/java/dev/failsafe/ExecutionImpl.java:195: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/Failsafe.java:29: UseUtilityClass: All members are static. Consider adding a private no-args constructor to prevent instantiation. +core/src/main/java/dev/failsafe/FailsafeException.java:27: UncommentedEmptyConstructor: Document empty constructor +core/src/main/java/dev/failsafe/FailsafeExecutor.java:20: UnnecessaryImport: Unused import 'dev.failsafe.function.*' +core/src/main/java/dev/failsafe/FailsafeExecutor.java:55: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/FailsafeExecutor.java:56: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/FailsafeExecutor.java:57: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/FailsafeExecutor.java:353: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/FailsafeExecutor.java:355: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/FailsafeExecutor.java:413: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/FailsafeExecutor.java:415: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/FailsafeExecutor.java:417: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/FailurePolicyBuilder.java:180: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/FailurePolicyBuilder.java:181: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/FailurePolicyBuilder.java:183: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/FallbackConfig.java:45: UncommentedEmptyConstructor: Document empty constructor +core/src/main/java/dev/failsafe/Functions.java:18: UnnecessaryImport: Unused import 'dev.failsafe.function.*' +core/src/main/java/dev/failsafe/Functions.java:20: UnnecessaryImport: Unused import 'dev.failsafe.spi.*' +core/src/main/java/dev/failsafe/Functions.java:31: UseUtilityClass: All members are static. Consider adding a private no-args constructor to prevent instantiation. +core/src/main/java/dev/failsafe/Functions.java:47: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/Functions.java:62: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/Functions.java:84: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/Functions.java:109: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/Functions.java:145: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/Functions.java:149: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/Functions.java:155: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/Functions.java:200: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/Functions.java:202: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/Functions.java:215: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/Functions.java:217: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/Functions.java:251: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/Functions.java:264: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/Functions.java:273: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/Functions.java:275: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/PolicyConfig.java:28: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/PolicyConfig.java:29: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/PolicyConfig.java:31: UncommentedEmptyConstructor: Document empty constructor +core/src/main/java/dev/failsafe/RateLimiter.java:187: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/RetryPolicyConfig.java:58: UncommentedEmptyConstructor: Document empty constructor +core/src/main/java/dev/failsafe/SyncExecutionImpl.java:26: UnnecessaryImport: Unused import 'java.util.concurrent.atomic.AtomicReference' +core/src/main/java/dev/failsafe/SyncExecutionImpl.java:54: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/SyncExecutionImpl.java:81: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/SyncExecutionImpl.java:84: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/SyncExecutionImpl.java:99: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/SyncExecutionImpl.java:193: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/SyncExecutionImpl.java:195: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/event/EventListener.java:33: EmptyCatchBlock: Avoid empty catch blocks +core/src/main/java/dev/failsafe/event/EventListener.java:33: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/BulkheadExecutor.java:84: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/BulkheadImpl.java:56: EmptyCatchBlock: Avoid empty catch blocks +core/src/main/java/dev/failsafe/internal/BulkheadImpl.java:74: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/BurstyRateLimiterStats.java:68: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/BurstyRateLimiterStats.java:74: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java:18: UnnecessaryImport: Unused import 'dev.failsafe.*' +core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java:149: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java:151: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java:165: NonExhaustiveSwitch: Switch statements or expressions should be exhaustive, add a default case (or missing enum branches) +core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java:184: EmptyCatchBlock: Avoid empty catch blocks +core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java:184: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/CircuitState.java:20: UnnecessaryImport: Unused import 'dev.failsafe.CircuitBreakerOpenException' +core/src/main/java/dev/failsafe/internal/CircuitState.java:34: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/CircuitState.java:64: UncommentedEmptyMethodBody: Document empty method body +core/src/main/java/dev/failsafe/internal/CircuitState.java:67: UncommentedEmptyMethodBody: Document empty method body +core/src/main/java/dev/failsafe/internal/CircuitState.java:72: UncommentedEmptyMethodBody: Document empty method body +core/src/main/java/dev/failsafe/internal/CircuitStats.java:28: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CircuitStats.java:38: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CircuitStats.java:40: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/ClosedState.java:53: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/ClosedState.java:62: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/ClosedState.java:64: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:28: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:29: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:30: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:31: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:53: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:54: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:114: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:116: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:123: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:125: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:128: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:130: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:144: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/DefaultCircuitStats.java:7: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:19: UnnecessaryImport: Unused import 'dev.failsafe.spi.*' +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:52: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:56: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:62: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:82: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:84: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:86: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:89: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:98: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:103: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:111: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:121: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/HalfOpenState.java:87: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/HalfOpenState.java:89: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/HalfOpenState.java:98: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/HalfOpenState.java:100: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RateLimiterExecutor.java:64: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RateLimiterExecutor.java:79: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/RateLimiterImpl.java:57: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RateLimiterImpl.java:75: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RateLimiterImpl.java:77: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:21: UnnecessaryImport: Unused import 'dev.failsafe.spi.*' +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:45: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:46: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:48: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:77: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:81: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:85: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:93: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:102: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:110: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:126: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:142: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:164: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:186: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:220: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:237: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:252: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:254: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:275: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:277: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:283: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:289: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:291: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:300: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyImpl.java:62: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyImpl.java:63: EmptyCatchBlock: Avoid empty catch blocks +core/src/main/java/dev/failsafe/internal/RetryPolicyImpl.java:63: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/SmoothRateLimiterStats.java:59: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/TimedCircuitStats.java:35: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/TimedCircuitStats.java:42: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/TimedCircuitStats.java:117: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/TimedCircuitStats.java:189: OneDeclarationPerLine: Use one line for each declaration, it enhances code readability. +core/src/main/java/dev/failsafe/internal/TimeoutExecutor.java:21: UnnecessaryImport: Unused import 'dev.failsafe.spi.*' +core/src/main/java/dev/failsafe/internal/TimeoutExecutor.java:82: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/TimeoutExecutor.java:87: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/TimeoutExecutor.java:94: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/TimeoutExecutor.java:146: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/TimeoutExecutor.java:163: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/TimeoutExecutor.java:169: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/Assert.java:29: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/Assert.java:34: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/Assert.java:40: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:37: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:38: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:51: MissingOverride: The method 'newThread(Runnable)' is missing an @Override annotation. +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:61: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:76: OverrideBothEqualsAndHashCodeOnComparable: When implementing Comparable, both equals() and hashCode() should be overridden +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:77: CompareObjectsWithEquals: Use equals() to compare object references. +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:90: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:92: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:102: CloseResource: Ensure that resources like this ScheduledThreadPoolExecutor object are closed after use +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:113: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:118: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:120: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:131: CloseResource: Ensure that resources like this ExecutorService object are closed after use +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:142: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:155: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:157: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:161: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:48: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:48: AssignmentInOperand: Avoid assignment to tail in operand +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:65: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:72: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:74: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:75: CompareObjectsWithEquals: Use equals() to compare object references. +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:76: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:77: CompareObjectsWithEquals: Use equals() to compare object references. +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:78: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/Maths.java:37: UselessParentheses: Useless parentheses around `input / interval`. +core/src/main/java/dev/failsafe/spi/DefaultScheduledFuture.java:43: OverrideBothEqualsAndHashCodeOnComparable: When implementing Comparable, both equals() and hashCode() should be overridden +core/src/main/java/dev/failsafe/spi/DelayablePolicy.java:53: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/spi/DelayablePolicy.java:54: AvoidInstanceofChecksInCatchClause: An instanceof check is being performed on the caught exception. Create a separate catch clause for RuntimeException. +core/src/main/java/dev/failsafe/spi/DelayablePolicy.java:55: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/DelayablePolicy.java:57: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/ExecutionResult.java:209: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/ExecutionResult.java:211: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:75: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:94: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:99: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:101: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:103: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:130: EmptyCatchBlock: Avoid empty catch blocks +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:153: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:173: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:175: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailurePolicy.java:49: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailurePolicy.java:54: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailurePolicy.java:55: EmptyCatchBlock: Avoid empty catch blocks +core/src/main/java/dev/failsafe/spi/FailurePolicy.java:55: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:107: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:109: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:117: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:183: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:194: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:196: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:198: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:205: UncommentedEmptyMethodBody: Document empty method body +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:224: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:234: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:239: ControlStatementBraces: This statement should have braces From fc844596c82a2c64fe94d73569717f90beb70cc3 Mon Sep 17 00:00:00 2001 From: mitimugdho Date: Tue, 30 Jun 2026 15:49:50 +0600 Subject: [PATCH 2/3] miti --- core/src/main/java/dev/.DS_Store | Bin 6148 -> 6148 bytes .../main/java/dev/failsafe/internal/.DS_Store | Bin 0 -> 6148 bytes .../internal/RetryDelayCalculator.java | 110 ++++++++++++++++++ .../internal/RetryPolicyExecutor.java | 64 ++-------- 4 files changed, 117 insertions(+), 57 deletions(-) create mode 100644 core/src/main/java/dev/failsafe/internal/.DS_Store create mode 100644 core/src/main/java/dev/failsafe/internal/RetryDelayCalculator.java diff --git a/core/src/main/java/dev/.DS_Store b/core/src/main/java/dev/.DS_Store index b6ff5e04794b1b2c42f5090abe1c4a096e8ebf3d..b71c86587f7076b0427fef66c3f7ac94fd6e6ed3 100644 GIT binary patch delta 15 WcmZoMXffE}$Hr97u{nTkiy#0e`~H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 + * Extracted from {@link RetryPolicyExecutor#onFailure}, which previously interleaved this delay-math with + * retry-exhaustion checks and event-listener dispatch in a single method, and held {@code lastDelayNanos} as + * executor-wide mutable state even though only the delay computation ever read or wrote it. + *

+ * The computation is a fixed sequence of independent adjustment steps, applied in order: a user-supplied delay + * function takes precedence if configured; otherwise a fixed-or-random base delay is computed, then adjusted for + * backoff, then jitter, then clamped to any configured max duration. Structuring it this way (each step consuming + * the previous step's output, free to leave it unchanged) gives the pipeline its own seam to test and extend + * independently of retry-decision logic, in the spirit of Chain of Responsibility. + * + * @param result type + */ +class RetryDelayCalculator { + private final RetryPolicyConfig config; + + /** The last fixed, backoff, random or computed delay time in nanoseconds. */ + private volatile long lastDelayNanos; + + RetryDelayCalculator(RetryPolicyConfig config) { + this.config = config; + } + + /** + * Computes the delay to use before the next retry attempt. + * + * @param userComputedDelay the result of any user-supplied delay function, or {@code null} if none is configured + * or it did not apply for this result/exception. Takes precedence over the fixed/random/backoff steps below. + * @param context the current execution context, used for attempt-count-based backoff + * @param elapsedNanos elapsed execution time, used to clamp the result to any configured max duration + */ + long computeDelayNanos(Duration userComputedDelay, ExecutionContext context, long elapsedNanos) { + long delayNanos; + + if (userComputedDelay != null) { + delayNanos = userComputedDelay.toNanos(); + } else { + delayNanos = getFixedOrRandomDelayNanos(lastDelayNanos); + delayNanos = adjustForBackoff(context, delayNanos); + lastDelayNanos = delayNanos; + } + + if (delayNanos != 0) + delayNanos = adjustForJitter(delayNanos); + return adjustForMaxDuration(delayNanos, elapsedNanos); + } + + private long getFixedOrRandomDelayNanos(long delayNanos) { + Duration delay = config.getDelay(); + Duration delayMin = config.getDelayMin(); + Duration delayMax = config.getDelayMax(); + + if (delayNanos == 0 && delay != null && !delay.equals(Duration.ZERO)) + delayNanos = delay.toNanos(); + else if (delayMin != null && delayMax != null) + delayNanos = randomDelayInRange(delayMin.toNanos(), delayMax.toNanos(), Math.random()); + return delayNanos; + } + + private long adjustForBackoff(ExecutionContext context, long delayNanos) { + if (context.getAttemptCount() != 1 && config.getMaxDelay() != null) + delayNanos = (long) Math.min(delayNanos * config.getDelayFactor(), config.getMaxDelay().toNanos()); + return delayNanos; + } + + private long adjustForJitter(long delayNanos) { + if (config.getJitter() != null) + delayNanos = randomDelay(delayNanos, config.getJitter().toNanos(), Math.random()); + else if (config.getJitterFactor() > 0.0) + delayNanos = randomDelay(delayNanos, config.getJitterFactor(), Math.random()); + return delayNanos; + } + + private long adjustForMaxDuration(long delayNanos, long elapsedNanos) { + if (config.getMaxDuration() != null) { + long maxRemainingDelay = config.getMaxDuration().toNanos() - elapsedNanos; + delayNanos = Math.min(delayNanos, maxRemainingDelay < 0 ? 0 : maxRemainingDelay); + if (delayNanos < 0) + delayNanos = 0; + } + return delayNanos; + } +} \ No newline at end of file diff --git a/core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java b/core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java index 60d24005..b3abfd7a 100644 --- a/core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java +++ b/core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java @@ -28,9 +28,6 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; -import static dev.failsafe.internal.util.RandomDelay.randomDelay; -import static dev.failsafe.internal.util.RandomDelay.randomDelayInRange; - /** * A PolicyExecutor that handles failures according to a {@link RetryPolicy}. * @@ -44,8 +41,8 @@ public class RetryPolicyExecutor extends PolicyExecutor { // Mutable state private volatile int failedAttempts; private volatile boolean retriesExceeded; - /** The last fixed, backoff, random or computed delay time in nanoseconds. */ - private volatile long lastDelayNanos; + /** Extracted: owns the delay-computation pipeline and its state (see RetryDelayCalculator). */ + private final RetryDelayCalculator delayCalculator; // Handlers private final EventHandler abortHandler; @@ -63,6 +60,7 @@ public RetryPolicyExecutor(RetryPolicyImpl retryPolicy, int policyIndex) { this.retriesExceededHandler = EventHandler.ofExecutionCompleted(config.getRetriesExceededListener()); this.retryHandler = EventHandler.ofExecutionAttempted(config.getRetryListener()); this.retryScheduledHandler = EventHandler.ofExecutionScheduled(config.getRetryScheduledListener()); + this.delayCalculator = new RetryDelayCalculator<>(config); } @Override @@ -220,23 +218,11 @@ public ExecutionResult onFailure(ExecutionContext context, ExecutionResult failedAttemptHandler.handle(result, context); failedAttempts++; - long delayNanos = lastDelayNanos; - - // Determine the computed delay - Duration computedDelay = retryPolicy.computeDelay(context); - if (computedDelay != null) { - delayNanos = computedDelay.toNanos(); - } else { - // Determine the fixed or random delay - delayNanos = getFixedOrRandomDelayNanos(delayNanos); - delayNanos = adjustForBackoff(context, delayNanos); - lastDelayNanos = delayNanos; - } - if (delayNanos != 0) - delayNanos = adjustForJitter(delayNanos); + // Determine the delay to use before the next attempt + Duration userComputedDelay = retryPolicy.computeDelay(context); long elapsedNanos = context.getElapsedTime().toNanos(); - delayNanos = adjustForMaxDuration(delayNanos, elapsedNanos); + long delayNanos = delayCalculator.computeDelayNanos(userComputedDelay, context, elapsedNanos); // Calculate result boolean maxRetriesExceeded = config.getMaxRetries() != -1 && failedAttempts > config.getMaxRetries(); @@ -265,40 +251,4 @@ public CompletableFuture> onFailureAsync(ExecutionContext Scheduler scheduler, FailsafeFuture future) { return super.onFailureAsync(context, result.withNotComplete(), scheduler, future); } - - private long getFixedOrRandomDelayNanos(long delayNanos) { - Duration delay = config.getDelay(); - Duration delayMin = config.getDelayMin(); - Duration delayMax = config.getDelayMax(); - - if (delayNanos == 0 && delay != null && !delay.equals(Duration.ZERO)) - delayNanos = delay.toNanos(); - else if (delayMin != null && delayMax != null) - delayNanos = randomDelayInRange(delayMin.toNanos(), delayMax.toNanos(), Math.random()); - return delayNanos; - } - - private long adjustForBackoff(ExecutionContext context, long delayNanos) { - if (context.getAttemptCount() != 1 && config.getMaxDelay() != null) - delayNanos = (long) Math.min(delayNanos * config.getDelayFactor(), config.getMaxDelay().toNanos()); - return delayNanos; - } - - private long adjustForJitter(long delayNanos) { - if (config.getJitter() != null) - delayNanos = randomDelay(delayNanos, config.getJitter().toNanos(), Math.random()); - else if (config.getJitterFactor() > 0.0) - delayNanos = randomDelay(delayNanos, config.getJitterFactor(), Math.random()); - return delayNanos; - } - - private long adjustForMaxDuration(long delayNanos, long elapsedNanos) { - if (config.getMaxDuration() != null) { - long maxRemainingDelay = config.getMaxDuration().toNanos() - elapsedNanos; - delayNanos = Math.min(delayNanos, maxRemainingDelay < 0 ? 0 : maxRemainingDelay); - if (delayNanos < 0) - delayNanos = 0; - } - return delayNanos; - } -} +} \ No newline at end of file From f99bfffedad89fb913f3831cf6429d5b63c8601c Mon Sep 17 00:00:00 2001 From: mitimugdho Date: Tue, 30 Jun 2026 16:24:29 +0600 Subject: [PATCH 3/3] miti --- core/src/main/java/dev/.DS_Store | Bin 6148 -> 6148 bytes core/src/main/java/dev/failsafe/.DS_Store | Bin 6148 -> 6148 bytes .../java/dev/failsafe/ExecutorDelegation.java | 66 ++++++++++++ .../java/dev/failsafe/FailsafeExecutor.java | 1 + core/src/main/java/dev/failsafe/Fallback.java | 4 +- .../java/dev/failsafe/FunctionAdapters.java | 74 +++++++++++++ .../src/main/java/dev/failsafe/Functions.java | 102 +++--------------- 7 files changed, 156 insertions(+), 91 deletions(-) create mode 100644 core/src/main/java/dev/failsafe/ExecutorDelegation.java create mode 100644 core/src/main/java/dev/failsafe/FunctionAdapters.java diff --git a/core/src/main/java/dev/.DS_Store b/core/src/main/java/dev/.DS_Store index b71c86587f7076b0427fef66c3f7ac94fd6e6ed3..15dc27ecfd683ba8c3dd2e78d5b619d65bf51fd0 100644 GIT binary patch delta 241 zcmZoMXffEp%*uFnG7GCRhp3pigrtzP%w&C5F`;+?{^E@Ma?j-aynv$Avdq--$$qT6 z^dd5W0>PP8snO|0nJK{qiOHFH>B{yW7{Gv2*+B!s5@1jUGA0MGsnshx1VF@;9lRk7 z1`Y;o21kZqh8TuIh6aY|42v1oGaO_%$MBfpE5m|}jbG0uq0B{yW7{EZ;AppXdY``YMqU=!4G1;C?Esayz!5bpZ zz`>x+;K<;`5X_LlP|ncDFpFUs!w!a{47V8GFnnWVVH9IjV$^0dVYFqmXY^nUWDH_V kX3SwMWGrGVhM2&_2sKF#N<%5en#~v4v>7+EbNuB80K{4>i2wiq diff --git a/core/src/main/java/dev/failsafe/.DS_Store b/core/src/main/java/dev/failsafe/.DS_Store index 6b87c6c2eb8d594a029da88784f05d5f5281e336..f321073eac51a8e3fa3a61630a76c1a6a3d5b178 100644 GIT binary patch delta 148 zcmZoMXffEp%*uFnG7GCRhp3pigrt;|%w&DmJJRt2{KXmh<(|p;c>zVKWtpkv5t%@C zaAsBNWHmOm$)RkDT%5`d0SsU;xq(g5Qj$@LQJc|((U#Gk(Sy;GF^VynF@rIaF$>Pjj0r3bOlmGw# delta 152 zcmZoMXffEp%*uFUG7GCRhnTp8q?ELb^kjY3JJJ!E$@zJ~nN_Lr0{q1p`Q@HKZa`6L zS!QbaWHmN57G;N$gvst~YFx?=0SsWkIk}uo(OQ5}iBX%;gwdAKp3#FbkTHlcnK6g4 gkgOQSc8 + * Extracted from {@link Functions}, which previously combined this executor-delegation concern with + * execution-pipeline wiring and generic function adaptation in a single class with no shared state across the + * three concerns. + * + * @author Jonathan Halterman + */ +final class ExecutorDelegation { + static ContextualSupplier withExecutor(ContextualSupplier supplier, Executor executor) { + return executor == null ? supplier : ctx -> { + executor.execute(() -> { + try { + supplier.get(ctx); + } catch (Throwable e) { + handleExecutorThrowable(e); + } + }); + return null; + }; + } + + static AsyncRunnable withExecutor(AsyncRunnable runnable, Executor executor) { + return executor == null ? runnable : exec -> { + executor.execute(() -> { + try { + runnable.run(exec); + } catch (Throwable e) { + handleExecutorThrowable(e); + } + }); + }; + } + + private static void handleExecutorThrowable(Throwable e) { + if (e instanceof RuntimeException) + throw (RuntimeException) e; + if (e instanceof Error) + throw (Error) e; + throw new FailsafeException(e); + } +} \ No newline at end of file diff --git a/core/src/main/java/dev/failsafe/FailsafeExecutor.java b/core/src/main/java/dev/failsafe/FailsafeExecutor.java index 82b3144e..992f7d68 100644 --- a/core/src/main/java/dev/failsafe/FailsafeExecutor.java +++ b/core/src/main/java/dev/failsafe/FailsafeExecutor.java @@ -32,6 +32,7 @@ import java.util.function.Function; import static dev.failsafe.Functions.*; +import static dev.failsafe.FunctionAdapters.*; /** *

diff --git a/core/src/main/java/dev/failsafe/Fallback.java b/core/src/main/java/dev/failsafe/Fallback.java index ed3de304..01c2dd2f 100644 --- a/core/src/main/java/dev/failsafe/Fallback.java +++ b/core/src/main/java/dev/failsafe/Fallback.java @@ -25,7 +25,7 @@ import java.util.concurrent.CompletionStage; -import static dev.failsafe.Functions.toFn; +import static dev.failsafe.FunctionAdapters.toFn; /** * A Policy that handles failures using a fallback function or result. @@ -224,4 +224,4 @@ static Fallback none() { */ @Override FallbackConfig getConfig(); -} +} \ No newline at end of file diff --git a/core/src/main/java/dev/failsafe/FunctionAdapters.java b/core/src/main/java/dev/failsafe/FunctionAdapters.java new file mode 100644 index 00000000..3437be8f --- /dev/null +++ b/core/src/main/java/dev/failsafe/FunctionAdapters.java @@ -0,0 +1,74 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package dev.failsafe; + +import dev.failsafe.function.*; +import dev.failsafe.internal.util.Assert; + +/** + * Adapts various user-supplied functional interface shapes (runnables, suppliers, consumers, results) into the + * common {@link ContextualSupplier} or {@link CheckedFunction} shape that the rest of Failsafe operates on. + *

+ * Extracted from {@link Functions}, which previously combined this purely-functional adaptation logic with + * execution-pipeline wiring and executor-thread delegation in a single class with no shared state across the three + * concerns. + * + * @author Jonathan Halterman + */ +final class FunctionAdapters { + static ContextualSupplier toCtxSupplier(CheckedRunnable runnable) { + Assert.notNull(runnable, "runnable"); + return ctx -> { + runnable.run(); + return null; + }; + } + + static ContextualSupplier toCtxSupplier(ContextualRunnable runnable) { + Assert.notNull(runnable, "runnable"); + return ctx -> { + runnable.run(ctx); + return null; + }; + } + + static ContextualSupplier toCtxSupplier(CheckedSupplier supplier) { + Assert.notNull(supplier, "supplier"); + return ctx -> supplier.get(); + } + + static CheckedFunction toFn(CheckedConsumer consumer) { + return t -> { + consumer.accept(t); + return null; + }; + } + + static CheckedFunction toFn(CheckedRunnable runnable) { + return t -> { + runnable.run(); + return null; + }; + } + + static CheckedFunction toFn(CheckedSupplier supplier) { + return t -> supplier.get(); + } + + static CheckedFunction toFn(R result) { + return t -> result; + } +} \ No newline at end of file diff --git a/core/src/main/java/dev/failsafe/Functions.java b/core/src/main/java/dev/failsafe/Functions.java index 75a050fa..8ed4737c 100644 --- a/core/src/main/java/dev/failsafe/Functions.java +++ b/core/src/main/java/dev/failsafe/Functions.java @@ -36,14 +36,14 @@ final class Functions { * @param result type */ static Function, ExecutionResult> get(ContextualSupplier supplier, - Executor executor) { + Executor executor) { return execution -> { ExecutionResult result; Throwable throwable = null; try { execution.preExecute(); - result = ExecutionResult.success(withExecutor(supplier, executor).get(execution)); + result = ExecutionResult.success(ExecutorDelegation.withExecutor(supplier, executor).get(execution)); } catch (Throwable t) { throwable = t; result = ExecutionResult.exception(t); @@ -73,14 +73,14 @@ static Function, ExecutionResult> get(ContextualSupp * @param result type */ static Function, CompletableFuture>> getPromise( - ContextualSupplier supplier, Executor executor) { + ContextualSupplier supplier, Executor executor) { Assert.notNull(supplier, "supplier"); return execution -> { ExecutionResult result; try { execution.preExecute(); - result = ExecutionResult.success(withExecutor(supplier, executor).get(execution)); + result = ExecutionResult.success(ExecutorDelegation.withExecutor(supplier, executor).get(execution)); } catch (Throwable t) { result = ExecutionResult.exception(t); } @@ -97,7 +97,7 @@ static Function, CompletableFuture result type */ static Function, CompletableFuture>> getPromiseExecution( - AsyncRunnable runnable, Executor executor) { + AsyncRunnable runnable, Executor executor) { Assert.notNull(runnable, "runnable"); return new Function, CompletableFuture>>() { @@ -105,7 +105,7 @@ static Function, CompletableFuture> apply(AsyncExecutionInternal execution) { try { execution.preExecute(); - withExecutor(runnable, executor).run(execution); + ExecutorDelegation.withExecutor(runnable, executor).run(execution); } catch (Throwable e) { execution.record(null, e); } @@ -125,15 +125,15 @@ public synchronized CompletableFuture> apply(AsyncExecutionIn */ @SuppressWarnings("unchecked") static Function, CompletableFuture>> getPromiseOfStage( - ContextualSupplier> supplier, FailsafeFuture future, - Executor executor) { + ContextualSupplier> supplier, FailsafeFuture future, + Executor executor) { Assert.notNull(supplier, "supplier"); return execution -> { CompletableFuture> promise = new CompletableFuture<>(); try { execution.preExecute(); - CompletionStage stage = withExecutor(supplier, executor).get(execution); + CompletionStage stage = ExecutorDelegation.withExecutor(supplier, executor).get(execution); if (stage == null) { ExecutionResult r = ExecutionResult.success(null); @@ -168,7 +168,7 @@ static Function, CompletableFuture result type */ static Function, CompletableFuture>> toExecutionAware( - Function, CompletableFuture>> innerFn) { + Function, CompletableFuture>> innerFn) { return execution -> { ExecutionResult result = execution.getResult(); if (result == null) { @@ -186,8 +186,8 @@ static Function, CompletableFuture result type */ static Function, CompletableFuture>> toAsync( - Function, CompletableFuture>> innerFn, Scheduler scheduler, - FailsafeFuture future) { + Function, CompletableFuture>> innerFn, Scheduler scheduler, + FailsafeFuture future) { AtomicBoolean scheduled = new AtomicBoolean(); return execution -> { @@ -221,80 +221,4 @@ static Function, CompletableFuture toCtxSupplier(CheckedRunnable runnable) { - Assert.notNull(runnable, "runnable"); - return ctx -> { - runnable.run(); - return null; - }; - } - - static ContextualSupplier toCtxSupplier(ContextualRunnable runnable) { - Assert.notNull(runnable, "runnable"); - return ctx -> { - runnable.run(ctx); - return null; - }; - } - - static ContextualSupplier toCtxSupplier(CheckedSupplier supplier) { - Assert.notNull(supplier, "supplier"); - return ctx -> supplier.get(); - } - - static ContextualSupplier withExecutor(ContextualSupplier supplier, Executor executor) { - return executor == null ? supplier : ctx -> { - executor.execute(() -> { - try { - supplier.get(ctx); - } catch (Throwable e) { - handleExecutorThrowable(e); - } - }); - return null; - }; - } - - static AsyncRunnable withExecutor(AsyncRunnable runnable, Executor executor) { - return executor == null ? runnable : exec -> { - executor.execute(() -> { - try { - runnable.run(exec); - } catch (Throwable e) { - handleExecutorThrowable(e); - } - }); - }; - } - - private static void handleExecutorThrowable(Throwable e) { - if (e instanceof RuntimeException) - throw (RuntimeException) e; - if (e instanceof Error) - throw (Error) e; - throw new FailsafeException(e); - } - - static CheckedFunction toFn(CheckedConsumer consumer) { - return t -> { - consumer.accept(t); - return null; - }; - } - - static CheckedFunction toFn(CheckedRunnable runnable) { - return t -> { - runnable.run(); - return null; - }; - } - - static CheckedFunction toFn(CheckedSupplier supplier) { - return t -> supplier.get(); - } - - static CheckedFunction toFn(R result) { - return t -> result; - } -} +} \ No newline at end of file