/[projects]/miscJava/CircuitBreaker/src/main/java/dk/thoerup/circuitbreaker/CircuitBreaker.java
ViewVC logotype

Contents of /miscJava/CircuitBreaker/src/main/java/dk/thoerup/circuitbreaker/CircuitBreaker.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3212 - (show annotations) (download)
Thu Dec 28 09:34:47 2017 UTC (6 years, 4 months ago) by torben
File size: 5631 byte(s)
Use generics to encapsulate returned value
1 package dk.thoerup.circuitbreaker;
2
3
4 import java.util.concurrent.ExecutorService;
5 import java.util.concurrent.Executors;
6
7 import dk.thoerup.circuitbreaker.config.BreakerConfig;
8 import dk.thoerup.circuitbreaker.notification.NotiferHelper;
9 import dk.thoerup.circuitbreaker.notification.Notifier;
10 import dk.thoerup.circuitbreaker.notification.NullNotifier;
11 import dk.thoerup.circuitbreaker.statistics.NullStatistics;
12 import dk.thoerup.circuitbreaker.statistics.Statistics;
13
14 /* Simple CircuitBreaker implementation - snipped from http://www.jroller.com/kenwdelong/entry/circuit_breaker_in_java
15 *
16 * example of how it can be used
17
18 private CircuitBreaker<String> cb = new CircuitBreaker<>("test", 5, 10000);
19 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
20 class TestInvocation implements CircuitInvocation<String> {
21 String url;
22 public TestInvocation(String url) {
23 this.url = url;
24 }
25 public String proceed() throws Exception{
26
27 URL u = new URL(url);
28 URLConnection c = u.openConnection();
29 c.connect();
30 InputStream in = c.getInputStream();
31 in.close();
32
33
34 return "hello";
35 }
36
37 }
38 try {
39 String s = cb.invoke(new TestInvocation("http://rafiki/test"));
40 response.getWriter().print(s);
41 } catch (Exception e) {
42 logger.warning( e.getMessage() );
43 response.sendError(500);
44 return;
45 }
46
47 }
48 */
49
50
51 public class CircuitBreaker<T>{
52
53 private volatile CircuitBreakerState currentState;
54
55 private final OpenState open = new OpenState();
56 private final HalfOpenState halfOpen = new HalfOpenState();
57 private final ClosedState closed = new ClosedState();
58
59 private String name;
60
61 private ExecutorService executor = null;
62 private Notifier notifier = new NullNotifier();
63 private Statistics stats = new NullStatistics();
64
65
66 public CircuitBreaker(String name, BreakerConfig config) {
67 closed.setThreshold(config);
68 open.setTimeout(config);
69
70 this.name = name;
71
72 //set correct intial state
73 internalReset();
74 }
75
76 public synchronized void shutdown() {
77 if (executor != null) {
78 executor.shutdown();
79 }
80 }
81
82
83 public T invoke(CircuitInvocation<T> invocation) throws Exception
84 {
85 stats.addStatistics(Event.Invocation);
86
87 T result = null;
88 try
89 {
90 getState().preInvoke(this);
91 result = invocation.proceed();
92 getState().postInvoke(this);
93 }
94 catch(Exception e)
95 {
96 if (e instanceof CircuitBreakerException) {
97 stats.addStatistics(Event.InvocationBlocked);
98 } else {
99 stats.addStatistics(Event.InvocationFailure);
100 }
101
102 getState().onError(this, e);
103 throw e;
104 }
105 return result;
106 }
107
108 public void tripBreaker() {
109 commonTripBreaker(Event.BreakerTripped);
110 }
111
112 //a re-trip should basically do the same as a normal trip, but it is here just to differentiate the two different events
113 public void retripBreaker() {
114 commonTripBreaker(Event.BreakerRetripped);
115 }
116
117 private void commonTripBreaker(Event event) {
118 synchronized(this) {
119 if (currentState != open) { // TODO:Is this conditional necessary ??
120 open.trip();
121 currentState = open;
122
123 notifier.sendNotification(this, event);
124 stats.addStatistics(event);
125 }
126 }
127 }
128
129 public void attemptReset() {
130 synchronized(this) {
131 if (currentState != halfOpen) { // TODO:Is this conditional necessary ??
132 currentState = halfOpen;
133 notifier.sendNotification(this, Event.BreakerAttemptReset);
134 stats.addStatistics(Event.BreakerAttemptReset);
135 }
136 }
137
138 }
139
140 public void reset() {
141 synchronized(this) {
142 if (currentState != closed) { // TODO: Is this conditional necessary ??
143 internalReset();
144 notifier.sendNotification(this, Event.BreakerReset);
145 stats.addStatistics(Event.BreakerReset);
146 }
147 }
148 }
149
150 //This one actually sets the correct closed/reset state
151 private void internalReset() {
152 closed.resetFailureCount();
153 currentState = closed;
154 }
155
156
157 private CircuitBreakerState getState() {
158 synchronized(this) {
159 return currentState;
160 }
161 }
162
163 public boolean isClosed() {
164 return (getState() == closed);
165 }
166
167 public boolean isOpen() {
168 return (getState() == open);
169 }
170
171 public String getName() {
172 return name;
173 }
174
175 public String getStateName() {
176 return getState().getName();
177 }
178
179 public int getThreshold() {
180 return closed.getThreshold();
181 }
182
183 public int getTimeout() {
184 return (int)open.getTimeout();
185 }
186
187 public int getFailureCount() {
188 if (getState() == closed) {
189 return closed.getFailureCount();
190 } else {
191 return -1;
192 }
193 }
194
195 public long getElapsed() {
196 if (getState() == open) {
197 return open.getElapsed();
198 } else {
199 return -1;
200 }
201 }
202
203 public void setNotifier(Notifier notifier) {
204 synchronized(this) {
205 this.notifier = notifier;
206 }
207 }
208
209 public String getNotifierName() {
210 return NotiferHelper.getName(notifier);
211 }
212
213 public void setStatistics(Statistics newStats) {
214 this.stats = newStats;
215 }
216
217 public Statistics getStatistics() {
218 return this.stats;
219 }
220
221 public synchronized ExecutorService getExecutor() {
222
223 if (executor == null) {
224 executor = Executors.newFixedThreadPool(1);
225 }
226
227 return executor;
228
229 }
230
231 }

Properties

Name Value
svn:mergeinfo

  ViewVC Help
Powered by ViewVC 1.1.20