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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:mergeinfo

  ViewVC Help
Powered by ViewVC 1.1.20