#1510 Improvments done in Circuit Breaker
This commit is contained in:
@ -36,17 +36,18 @@ import org.slf4j.LoggerFactory;
|
||||
* operational again, so that we can use it
|
||||
* </p>
|
||||
* <p>
|
||||
* In this example, the circuit breaker pattern is demonstrated by using two services: {@link
|
||||
* MonitoringService} and {@link DelayedService}. The monitoring service is responsible for calling
|
||||
* two services: a local service and a remote service {@link DelayedService} , and by using the
|
||||
* circuit breaker construction we ensure that if the call to remote service is going to fail, we
|
||||
* are going to save our resources and not make the function call at all, by wrapping our call to
|
||||
* the remote service in the circuit breaker object.
|
||||
* In this example, the circuit breaker pattern is demonstrated by using three services: {@link
|
||||
* DelayedRemoteService}, {@link QuickRemoteService} and {@link MonitoringService}. The monitoring
|
||||
* service is responsible for calling three services: a local service, a quick remove service
|
||||
* {@link QuickRemoteService} and a delayed remote service {@link DelayedRemoteService} , and by
|
||||
* using the circuit breaker construction we ensure that if the call to remote service is going to
|
||||
* fail, we are going to save our resources and not make the function call at all, by wrapping our
|
||||
* call to the remote services in the {@link DefaultCircuitBreaker} implementation object.
|
||||
* </p>
|
||||
* <p>
|
||||
* This works as follows: The {@link CircuitBreaker} object can be in one of three states:
|
||||
* <b>Open</b>, <b>Closed</b> and <b>Half-Open</b>, which represents the real world circuits. If the
|
||||
* state is closed (initial), we assume everything is alright and perform the function call.
|
||||
* This works as follows: The {@link DefaultCircuitBreaker} object can be in one of three states:
|
||||
* <b>Open</b>, <b>Closed</b> and <b>Half-Open</b>, which represents the real world circuits. If
|
||||
* the state is closed (initial), we assume everything is alright and perform the function call.
|
||||
* However, every time the call fails, we note it and once it crosses a threshold, we set the state
|
||||
* to Open, preventing any further calls to the remote server. Then, after a certain retry period
|
||||
* (during which we expect thee service to recover), we make another call to the remote server and
|
||||
@ -63,22 +64,51 @@ public class App {
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
@SuppressWarnings("squid:S2189")
|
||||
public static void main(String[] args) {
|
||||
//Create an object of monitoring service which makes both local and remote calls
|
||||
var obj = new MonitoringService();
|
||||
//Set the circuit Breaker parameters
|
||||
var circuitBreaker = new CircuitBreaker(3000, 1, 2000 * 1000 * 1000);
|
||||
|
||||
var serverStartTime = System.nanoTime();
|
||||
while (true) {
|
||||
LOGGER.info(obj.localResourceResponse());
|
||||
LOGGER.info(obj.remoteResourceResponse(circuitBreaker, serverStartTime));
|
||||
LOGGER.info(circuitBreaker.getState());
|
||||
try {
|
||||
Thread.sleep(5 * 1000);
|
||||
} catch (InterruptedException e) {
|
||||
LOGGER.error(e.getMessage());
|
||||
}
|
||||
|
||||
var delayedService = new DelayedRemoteService(serverStartTime, 5);
|
||||
//Set the circuit Breaker parameters
|
||||
var delayedServiceCircuitBreaker = new DefaultCircuitBreaker(delayedService, 3000, 2,
|
||||
2000 * 1000 * 1000);
|
||||
|
||||
var quickService = new QuickRemoteService();
|
||||
//Set the circuit Breaker parameters
|
||||
var quickServiceCircuitBreaker = new DefaultCircuitBreaker(quickService, 3000, 2,
|
||||
2000 * 1000 * 1000);
|
||||
|
||||
//Create an object of monitoring service which makes both local and remote calls
|
||||
var monitoringService = new MonitoringService(delayedServiceCircuitBreaker,
|
||||
quickServiceCircuitBreaker);
|
||||
|
||||
//Fetch response from local resource
|
||||
LOGGER.info(monitoringService.localResourceResponse());
|
||||
|
||||
//Fetch response from delayed service 2 times, to meet the failure threshold
|
||||
LOGGER.info(monitoringService.delayedServiceResponse());
|
||||
LOGGER.info(monitoringService.delayedServiceResponse());
|
||||
|
||||
//Fetch current state of delayed service circuit breaker after crossing failure threshold limit
|
||||
//which is OPEN now
|
||||
LOGGER.info(delayedServiceCircuitBreaker.getState());
|
||||
|
||||
//Meanwhile, the delayed service is down, fetch response from the healthy quick service
|
||||
LOGGER.info(monitoringService.quickServiceResponse());
|
||||
LOGGER.info(quickServiceCircuitBreaker.getState());
|
||||
|
||||
//Wait for the delayed service to become responsive
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//Check the state of delayed circuit breaker, should be HALF_OPEN
|
||||
LOGGER.info(delayedServiceCircuitBreaker.getState());
|
||||
|
||||
//Fetch response from delayed service, which should be healthy by now
|
||||
LOGGER.info(monitoringService.delayedServiceResponse());
|
||||
//As successful response is fetched, it should be CLOSED again.
|
||||
LOGGER.info(delayedServiceCircuitBreaker.getState());
|
||||
}
|
||||
}
|
||||
|
@ -24,114 +24,22 @@
|
||||
package com.iluwatar.circuitbreaker;
|
||||
|
||||
/**
|
||||
* The circuit breaker class with all configurations.
|
||||
* The Circuit breaker interface.
|
||||
*/
|
||||
public class CircuitBreaker {
|
||||
private final long timeout;
|
||||
private final long retryTimePeriod;
|
||||
long lastFailureTime;
|
||||
int failureCount;
|
||||
private final int failureThreshold;
|
||||
private State state;
|
||||
private final long futureTime = 1000 * 1000 * 1000 * 1000;
|
||||
public interface CircuitBreaker {
|
||||
|
||||
/**
|
||||
* Constructor to create an instance of Circuit Breaker.
|
||||
*
|
||||
* @param timeout Timeout for the API request. Not necessary for this simple example
|
||||
* @param failureThreshold Number of failures we receive from the depended service before changing
|
||||
* state to 'OPEN'
|
||||
* @param retryTimePeriod Time period after which a new request is made to remote service for
|
||||
* status check.
|
||||
*/
|
||||
CircuitBreaker(long timeout, int failureThreshold, long retryTimePeriod) {
|
||||
// We start in a closed state hoping that everything is fine
|
||||
this.state = State.CLOSED;
|
||||
this.failureThreshold = failureThreshold;
|
||||
// Timeout for the API request.
|
||||
// Used to break the calls made to remote resource if it exceeds the limit
|
||||
this.timeout = timeout;
|
||||
this.retryTimePeriod = retryTimePeriod;
|
||||
//An absurd amount of time in future which basically indicates the last failure never happened
|
||||
this.lastFailureTime = System.nanoTime() + futureTime;
|
||||
this.failureCount = 0;
|
||||
}
|
||||
//Success response. Reset everything to defaults
|
||||
void recordSuccess();
|
||||
|
||||
//Reset everything to defaults
|
||||
private void reset() {
|
||||
this.failureCount = 0;
|
||||
this.lastFailureTime = System.nanoTime() + futureTime;
|
||||
this.state = State.CLOSED;
|
||||
}
|
||||
//Failure response. Handle accordingly and change state if required.
|
||||
void recordFailure();
|
||||
|
||||
private void recordFailure() {
|
||||
failureCount = failureCount + 1;
|
||||
this.lastFailureTime = System.nanoTime();
|
||||
}
|
||||
//Get the current state of circuit breaker
|
||||
String getState();
|
||||
|
||||
protected void setState() {
|
||||
if (failureCount > failureThreshold) { //Then something is wrong with remote service
|
||||
if ((System.nanoTime() - lastFailureTime) > retryTimePeriod) {
|
||||
//We have waited long enough and should try checking if service is up
|
||||
state = State.HALF_OPEN;
|
||||
} else {
|
||||
//Service would still probably be down
|
||||
state = State.OPEN;
|
||||
}
|
||||
} else {
|
||||
//Everything is working fine
|
||||
state = State.CLOSED;
|
||||
}
|
||||
}
|
||||
//Set the specific state manually.
|
||||
void setState(State state);
|
||||
|
||||
public String getState() {
|
||||
return state.name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Break the circuit beforehand if it is known service is down Or connect the circuit manually if
|
||||
* service comes online before expected.
|
||||
*
|
||||
* @param state State at which circuit is in
|
||||
*/
|
||||
public void setStateForBypass(State state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes service call.
|
||||
*
|
||||
* @param serviceToCall The name of the service in String. Can be changed to data URLs in case
|
||||
* of web applications
|
||||
* @param serverStartTime Time at which actual server was started which makes calls to this
|
||||
* service
|
||||
* @return Value from the remote resource, stale response or a custom exception
|
||||
*/
|
||||
public String call(String serviceToCall, long serverStartTime) throws Exception {
|
||||
setState();
|
||||
if (state == State.OPEN) {
|
||||
// return cached response if no the circuit is in OPEN state
|
||||
return "This is stale response from API";
|
||||
} else {
|
||||
// Make the API request if the circuit is not OPEN
|
||||
if (serviceToCall.equals("delayedService")) {
|
||||
var delayedService = new DelayedService(20);
|
||||
var response = delayedService.response(serverStartTime);
|
||||
//In a real application, this would be run in a thread and the timeout
|
||||
//parameter of the circuit breaker would be utilized to know if service
|
||||
//is working. Here, we simulate that based on server response itself
|
||||
if (response.split(" ")[3].equals("working")) {
|
||||
// Yay!! the API responded fine. Let's reset everything.
|
||||
reset();
|
||||
return response;
|
||||
} else {
|
||||
// Uh-oh!! the call still failed. Let's update that in our records.
|
||||
recordFailure();
|
||||
throw new Exception("Remote service not responding");
|
||||
}
|
||||
} else {
|
||||
throw new Exception("Unknown Service Name");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//Attempt to fetch response from the remote service.
|
||||
String attemptRequest() throws RemoteServiceException;
|
||||
}
|
||||
|
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.circuitbreaker;
|
||||
|
||||
/**
|
||||
* The delay based Circuit breaker implementation that works in a
|
||||
* CLOSED->OPEN-(retry_time_period)->HALF_OPEN->CLOSED flow with some retry time period for failed
|
||||
* services and a failure threshold for service to open
|
||||
* circuit.
|
||||
*/
|
||||
public class DefaultCircuitBreaker implements CircuitBreaker {
|
||||
|
||||
private final long timeout;
|
||||
private final long retryTimePeriod;
|
||||
private final RemoteService service;
|
||||
long lastFailureTime;
|
||||
int failureCount;
|
||||
private final int failureThreshold;
|
||||
private State state;
|
||||
private final long futureTime = 1000 * 1000 * 1000 * 1000;
|
||||
|
||||
/**
|
||||
* Constructor to create an instance of Circuit Breaker.
|
||||
*
|
||||
* @param timeout Timeout for the API request. Not necessary for this simple example
|
||||
* @param failureThreshold Number of failures we receive from the depended service before changing
|
||||
* state to 'OPEN'
|
||||
* @param retryTimePeriod Time period after which a new request is made to remote service for
|
||||
* status check.
|
||||
*/
|
||||
DefaultCircuitBreaker(RemoteService serviceToCall, long timeout, int failureThreshold,
|
||||
long retryTimePeriod) {
|
||||
this.service = serviceToCall;
|
||||
// We start in a closed state hoping that everything is fine
|
||||
this.state = State.CLOSED;
|
||||
this.failureThreshold = failureThreshold;
|
||||
// Timeout for the API request.
|
||||
// Used to break the calls made to remote resource if it exceeds the limit
|
||||
this.timeout = timeout;
|
||||
this.retryTimePeriod = retryTimePeriod;
|
||||
//An absurd amount of time in future which basically indicates the last failure never happened
|
||||
this.lastFailureTime = System.nanoTime() + futureTime;
|
||||
this.failureCount = 0;
|
||||
}
|
||||
|
||||
//Reset everything to defaults
|
||||
@Override
|
||||
public void recordSuccess() {
|
||||
this.failureCount = 0;
|
||||
this.lastFailureTime = System.nanoTime() + futureTime;
|
||||
this.state = State.CLOSED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordFailure() {
|
||||
failureCount = failureCount + 1;
|
||||
this.lastFailureTime = System.nanoTime();
|
||||
}
|
||||
|
||||
//Evaluate the current state based on failureThreshold, failureCount and lastFailureTime.
|
||||
protected void evaluateState() {
|
||||
if (failureCount >= failureThreshold) { //Then something is wrong with remote service
|
||||
if ((System.nanoTime() - lastFailureTime) > retryTimePeriod) {
|
||||
//We have waited long enough and should try checking if service is up
|
||||
state = State.HALF_OPEN;
|
||||
} else {
|
||||
//Service would still probably be down
|
||||
state = State.OPEN;
|
||||
}
|
||||
} else {
|
||||
//Everything is working fine
|
||||
state = State.CLOSED;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getState() {
|
||||
evaluateState();
|
||||
return state.name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Break the circuit beforehand if it is known service is down Or connect the circuit manually if
|
||||
* service comes online before expected.
|
||||
*
|
||||
* @param state State at which circuit is in
|
||||
*/
|
||||
@Override
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
switch (state) {
|
||||
case OPEN:
|
||||
this.failureCount = failureThreshold;
|
||||
this.lastFailureTime = System.nanoTime();
|
||||
break;
|
||||
case HALF_OPEN:
|
||||
this.failureCount = failureThreshold;
|
||||
this.lastFailureTime = System.nanoTime() - retryTimePeriod;
|
||||
break;
|
||||
default:
|
||||
this.failureCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes service call.
|
||||
*
|
||||
* @return Value from the remote resource, stale response or a custom exception
|
||||
*/
|
||||
@Override
|
||||
public String attemptRequest() throws RemoteServiceException {
|
||||
evaluateState();
|
||||
if (state == State.OPEN) {
|
||||
// return cached response if no the circuit is in OPEN state
|
||||
return "This is stale response from API";
|
||||
} else {
|
||||
// Make the API request if the circuit is not OPEN
|
||||
try {
|
||||
//In a real application, this would be run in a thread and the timeout
|
||||
//parameter of the circuit breaker would be utilized to know if service
|
||||
//is working. Here, we simulate that based on server response itself
|
||||
var response = service.call();
|
||||
// Yay!! the API responded fine. Let's reset everything.
|
||||
recordSuccess();
|
||||
return response;
|
||||
} catch (RemoteServiceException ex) {
|
||||
recordFailure();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -27,7 +27,9 @@ package com.iluwatar.circuitbreaker;
|
||||
* This simulates the remote service It responds only after a certain timeout period (default set to
|
||||
* 20 seconds).
|
||||
*/
|
||||
public class DelayedService {
|
||||
public class DelayedRemoteService implements RemoteService {
|
||||
|
||||
private final long serverStartTime;
|
||||
private final int delay;
|
||||
|
||||
/**
|
||||
@ -35,22 +37,23 @@ public class DelayedService {
|
||||
*
|
||||
* @param delay the delay after which service would behave properly, in seconds
|
||||
*/
|
||||
public DelayedService(int delay) {
|
||||
public DelayedRemoteService(long serverStartTime, int delay) {
|
||||
this.serverStartTime = serverStartTime;
|
||||
this.delay = delay;
|
||||
}
|
||||
|
||||
public DelayedService() {
|
||||
this.delay = 60;
|
||||
public DelayedRemoteService() {
|
||||
this.serverStartTime = System.nanoTime();
|
||||
this.delay = 20;
|
||||
}
|
||||
|
||||
/**
|
||||
* Responds based on delay, current time and server start time if the service is down / working.
|
||||
*
|
||||
* @param serverStartTime Time at which actual server was started which makes calls to this
|
||||
* service
|
||||
* @return The state of the service
|
||||
*/
|
||||
public String response(long serverStartTime) {
|
||||
@Override
|
||||
public String call() throws RemoteServiceException {
|
||||
var currentTime = System.nanoTime();
|
||||
//Since currentTime and serverStartTime are both in nanoseconds, we convert it to
|
||||
//seconds by diving by 10e9 and ensure floating point division by multiplying it
|
||||
@ -58,9 +61,8 @@ public class DelayedService {
|
||||
//send the reply
|
||||
if ((currentTime - serverStartTime) * 1.0 / (1000 * 1000 * 1000) < delay) {
|
||||
//Can use Thread.sleep() here to block and simulate a hung server
|
||||
return "Delayed service is down";
|
||||
} else {
|
||||
return "Delayed service is working";
|
||||
throw new RemoteServiceException("Delayed service is down");
|
||||
}
|
||||
return "Delayed service is working";
|
||||
}
|
||||
}
|
@ -24,28 +24,47 @@
|
||||
package com.iluwatar.circuitbreaker;
|
||||
|
||||
/**
|
||||
* The service class which makes local and remote calls Uses {@link CircuitBreaker} object to ensure
|
||||
* remote calls don't use up resources.
|
||||
* The service class which makes local and remote calls Uses {@link DefaultCircuitBreaker} object to
|
||||
* ensure remote calls don't use up resources.
|
||||
*/
|
||||
public class MonitoringService {
|
||||
|
||||
private final CircuitBreaker delayedService;
|
||||
|
||||
private final CircuitBreaker quickService;
|
||||
|
||||
public MonitoringService(CircuitBreaker delayedService, CircuitBreaker quickService) {
|
||||
this.delayedService = delayedService;
|
||||
this.quickService = quickService;
|
||||
}
|
||||
|
||||
//Assumption: Local service won't fail, no need to wrap it in a circuit breaker logic
|
||||
public String localResourceResponse() {
|
||||
return "Local Service is working";
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get result from remote server.
|
||||
* Fetch response from the delayed service (with some simulated startup time).
|
||||
*
|
||||
* @param circuitBreaker The circuitBreaker object with all parameters
|
||||
* @param serverStartTime Time at which actual server was started which makes calls to this
|
||||
* service
|
||||
* @return result from the remote response or exception raised by it.
|
||||
* @return response string
|
||||
*/
|
||||
public String remoteResourceResponse(CircuitBreaker circuitBreaker, long serverStartTime) {
|
||||
public String delayedServiceResponse() {
|
||||
try {
|
||||
return circuitBreaker.call("delayedService", serverStartTime);
|
||||
} catch (Exception e) {
|
||||
return this.delayedService.attemptRequest();
|
||||
} catch (RemoteServiceException e) {
|
||||
return e.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches response from a healthy service without any failure.
|
||||
*
|
||||
* @return response string
|
||||
*/
|
||||
public String quickServiceResponse() {
|
||||
try {
|
||||
return this.quickService.attemptRequest();
|
||||
} catch (RemoteServiceException e) {
|
||||
return e.getMessage();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.circuitbreaker;
|
||||
|
||||
/**
|
||||
* A quick response remote service, that responds healthy without any delay or failure.
|
||||
*/
|
||||
public class QuickRemoteService implements RemoteService {
|
||||
|
||||
@Override
|
||||
public String call() throws RemoteServiceException {
|
||||
return "Quick Service is working";
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.circuitbreaker;
|
||||
|
||||
/**
|
||||
* The Remote service interface, used by {@link CircuitBreaker} for fetching response from remote
|
||||
* services.
|
||||
*/
|
||||
public interface RemoteService {
|
||||
|
||||
//Fetch response from remote service.
|
||||
String call() throws RemoteServiceException;
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.iluwatar.circuitbreaker;
|
||||
|
||||
/**
|
||||
* Exception thrown when {@link RemoteService} does not respond successfully.
|
||||
*/
|
||||
public class RemoteServiceException extends Exception {
|
||||
|
||||
public RemoteServiceException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user