Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclarePrecedence;
import org.fishwife.jrugged.CircuitBreakerConfig;
import org.fishwife.jrugged.CircuitBreakerFactory;
import org.fishwife.jrugged.BreakerFactory;
import org.fishwife.jrugged.DefaultFailureInterpreter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -39,30 +39,30 @@ public class CircuitBreakerAspect {
/**
* Maps names to CircuitBreakers.
*/
private CircuitBreakerFactory circuitBreakerFactory;
private BreakerFactory circuitBreakerFactory;

/** Default constructor. */
public CircuitBreakerAspect() {
circuitBreakerFactory = new CircuitBreakerFactory();
circuitBreakerFactory = new BreakerFactory();
}

/**
* Sets the {@link org.fishwife.jrugged.CircuitBreakerFactory} to use when creating new
* Sets the {@link org.fishwife.jrugged.BreakerFactory} to use when creating new
* {@link org.fishwife.jrugged.CircuitBreaker} instances.
* @param circuitBreakerFactory the {@link org.fishwife.jrugged.CircuitBreakerFactory} to
* @param circuitBreakerFactory the {@link org.fishwife.jrugged.BreakerFactory} to
* use.
*/
public void setCircuitBreakerFactory(
CircuitBreakerFactory circuitBreakerFactory) {
BreakerFactory circuitBreakerFactory) {
this.circuitBreakerFactory = circuitBreakerFactory;
}

/**
* Get the {@link org.fishwife.jrugged.CircuitBreakerFactory} that is being used to create
* Get the {@link org.fishwife.jrugged.BreakerFactory} that is being used to create
* new {@link org.fishwife.jrugged.CircuitBreaker} instances.
* @return the {@link org.fishwife.jrugged.CircuitBreakerFactory}.
* @return the {@link org.fishwife.jrugged.BreakerFactory}.
*/
public CircuitBreakerFactory getCircuitBreakerFactory() {
public BreakerFactory getCircuitBreakerFactory() {
return circuitBreakerFactory;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/* Copyright 2009-2015 Comcast Interactive Media, LLC.

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 org.fishwife.jrugged.aspects;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.atomic.AtomicLong;

/**
* Marks a method as one to be wrapped with a
* {@link org.fishwife.jrugged.SkepticBreaker}.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SkepticBreaker {

/**
* Name of the skeptic. Each annotation with a shared value shares
* the same SkepticBreaker.
* @return the value
*/
String name();

/**
* Exception types that the {@link
* org.fishwife.jrugged.SkepticBreaker} will ignore (pass through
* transparently without tripping).
* @return the Exception types.
*/
Class<? extends Throwable>[] ignore() default {};

/**
* Specifies the length of the measurement window for failure
* tolerances in milliseconds. i.e. if <code>limit</code>
* failures occur within <code>windowMillis</code> milliseconds,
* the breaker will trip.
* @return the length of the measurement window.
*/
long windowMillis() default -1;

/**
* Specifies the number of failures that must occur within a
* configured time window in order to trip the skeptic breaker.
* @return the number of failures.
*/
int limit() default -1;


/**
* Input parameters used to determine length of timers during the
* OPEN (wait) and CLOSED (good) status of the
* {@link org.fishwife.jrugged.SkepticBreaker}
*/
long waitBase() default -1;
long waitMult() default -1;
long goodBase() default -1;
long goodMult() default -1;

/**
* Specifies the current level of skepticism of the
* {@link org.fishwife.jrugged.SkepticBreaker} given past
* performance.
* @return the Skeptic Level.
*/
long skepticLevel() default -1;

/**
* Specifies the maximum level of skepticism of the
* {@link org.fishwife.jrugged.SkepticBreaker} admissible.
* @return the maximum skeptic level.
*/
long maxLevel() default -1;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/* Copyright 2009-2014 Comcast Interactive Media, LLC.

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 org.fishwife.jrugged.aspects;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclarePrecedence;
import org.fishwife.jrugged.FailureInterpreter;
import org.fishwife.jrugged.SkepticBreakerConfig;
import org.fishwife.jrugged.BreakerFactory;
import org.fishwife.jrugged.DefaultFailureInterpreter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.Callable;

/**
* Surrounds methods decorated with the SkepticBreaker annotation with a named
* {@link org.fishwife.jrugged.SkepticBreaker}.
*/
@Aspect
public class SkepticBreakerAspect {

private static final Logger logger =
LoggerFactory.getLogger(SkepticBreakerAspect.class);

/**
* Maps names to SkepticBreakers.
*/
private BreakerFactory skepticBreakerFactory;

/** Default constructor. */
public SkepticBreakerAspect() {
skepticBreakerFactory = new BreakerFactory();
}

/**
* Sets the {@link org.fishwife.jrugged.BreakerFactory} to use when creating new
* {@link org.fishwife.jrugged.SkepticBreaker} instances.
* @param skepticBreakerFactory the {@link org.fishwife.jrugged.BreakerFactory} to
* use.
*/
public void setSkepticBreakerFactory(
BreakerFactory skepticBreakerFactory) {
this.skepticBreakerFactory = skepticBreakerFactory;
}

/**
* Get the {@link org.fishwife.jrugged.BreakerFactory} that is being used to create
* new {@link org.fishwife.jrugged.SkepticBreaker} instances.
* @return the {@link org.fishwife.jrugged.BreakerFactory}.
*/
public BreakerFactory getSkepticBreakerFactory() {
return skepticBreakerFactory;
}

/** Runs a method call through the configured
* {@link org.fishwife.jrugged.SkepticBreaker}.
* @param pjp a {@link ProceedingJoinPoint} representing an annotated
* method call.
* @param skepticBreakerAnnotation the {@link org.fishwife.jrugged.SkepticBreaker} annotation
* that wrapped the method.
* @throws Throwable if the method invocation itself or the wrapping
* {@link org.fishwife.jrugged.SkepticBreaker} throws one during execution.
* @return The return value from the method call.
*/
@Around("@annotation(skepticBreakerAnnotation)")
public Object monitor(final ProceedingJoinPoint pjp,
SkepticBreaker skepticBreakerAnnotation) throws Throwable {
final String name = skepticBreakerAnnotation.name();

org.fishwife.jrugged.SkepticBreaker skepticBreaker =
skepticBreakerFactory.findSkepticBreaker(name);

if (skepticBreaker == null) {
DefaultFailureInterpreter dfi =
new DefaultFailureInterpreter(
skepticBreakerAnnotation.ignore(),
skepticBreakerAnnotation.limit(),
skepticBreakerAnnotation.windowMillis());

SkepticBreakerConfig config = new SkepticBreakerConfig(skepticBreakerAnnotation.goodBase(),
skepticBreakerAnnotation.goodMult(), skepticBreakerAnnotation.waitBase(),
skepticBreakerAnnotation.waitMult(), skepticBreakerAnnotation.maxLevel(), dfi);

skepticBreaker =
skepticBreakerFactory.createSkepticBreaker(name, config);
}

if (logger.isDebugEnabled()) {
logger.debug("Have @SkepticBreaker method with breaker name {}, " +
"wrapping call on method {} of target object {} with status {}",
new Object[]{
name,
pjp.getSignature().getName(),
pjp.getTarget(),
skepticBreaker.getStatus()});
}

return skepticBreaker.invoke(new Callable<Object>() {
public Object call() throws Exception {
try {
return pjp.proceed();
} catch (Throwable e) {
if (e instanceof Exception) {
throw (Exception) e;
} else if (e instanceof Error) {
throw (Error) e;
} else {
throw new RuntimeException(e);
}
}
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.fishwife.jrugged.CircuitBreakerException;
import org.fishwife.jrugged.CircuitBreakerFactory;
import org.fishwife.jrugged.BreakerException;
import org.fishwife.jrugged.BreakerFactory;
import org.junit.Before;
import org.junit.Test;

Expand Down Expand Up @@ -104,7 +104,7 @@ public void testSetCircuitBreakerFactory() throws Throwable {
expect(mockPjp.proceed()).andReturn(null);
replay(mockPjp);

CircuitBreakerFactory factory = new CircuitBreakerFactory();
BreakerFactory factory = new BreakerFactory();
aspect.setCircuitBreakerFactory(factory);

aspect.monitor(mockPjp, mockAnnotation);
Expand Down Expand Up @@ -169,7 +169,7 @@ public void testGetCircuitBreakerFactory() throws Throwable {
replay(mockPjp);

aspect.monitor(mockPjp, mockAnnotation);
CircuitBreakerFactory circuitBreakerFactory =
BreakerFactory circuitBreakerFactory =
aspect.getCircuitBreakerFactory();

assertNotNull(circuitBreakerFactory);
Expand All @@ -196,7 +196,7 @@ public void testTripBreaker() throws Throwable {
callMonitorCatchThrowable(mockPjp, e);
}

CircuitBreakerException cbe = new CircuitBreakerException();
BreakerException cbe = new BreakerException();
callMonitorCatchThrowable(mockPjp, cbe);
verifyBreakerExists(TEST_CIRCUIT_BREAKER);

Expand Down
8 changes: 8 additions & 0 deletions jrugged-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,12 @@
<packaging>jar</packaging>
<name>jrugged-core</name>
<url>https://github.com/Comcast/jrugged</url>

<dependencies>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>3.4</version>
</dependency>
</dependencies>
</project>
Loading