Skip to content

Commit

Permalink
Fix #79
Browse files Browse the repository at this point in the history
  • Loading branch information
hexiaofeng authored Oct 12, 2024
1 parent c7550de commit 0d0958d
Show file tree
Hide file tree
Showing 92 changed files with 940 additions and 722 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,14 @@
public class TypeScanner {

public static final Predicate<Class<?>> UNTIL_OBJECT = t ->
!t.isPrimitive() && !t.isAnnotation() && !t.isEnum() && !t.isInterface() && !t.isArray() &&
!t.equals(Object.class) &&
!t.getName().startsWith("java.") && !t.getName().startsWith("javax.");
!t.isPrimitive()
&& !t.isAnnotation()
&& !t.isEnum()
&& !t.isInterface()
&& !t.isArray()
&& !t.equals(Object.class)
&& !t.getName().startsWith("java.")
&& !t.getName().startsWith("javax.");

private final Class<?> type;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,48 +13,85 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jd.live.agent.governance.invoke.exception;
package com.jd.live.agent.governance.exception;

import com.jd.live.agent.governance.policy.service.circuitbreak.CircuitBreakPolicy;
import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.HashSet;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;

@Getter
@AllArgsConstructor
public class ErrorCause {

@Getter
private Throwable cause;

private String errorCode;

private Set<String> exceptions;

private Set<String> targets;

private boolean matched;

/**
* Checks if the given circuit breaker policy matches the error code or exceptions.
*
* @param policy the circuit breaker policy to match against
* @return true if the policy matches the error code or exceptions, false otherwise
*/
public boolean match(ErrorPolicy policy) {
return matched
|| policy != null && (policy.containsError(errorCode) || policy.containsException(exceptions))
|| ErrorPolicy.containsException(exceptions, targets);
}

/**
* Builds an ErrorCause object from the given throwable object and error name function.
*
* @param throwable The throwable object to build the ErrorCause from.
* @param nameFunc The function to extract the error name and code from each cause of the throwable.
* @return An ErrorCause object containing the root cause, error code, and set of exception names.
*/
public static ErrorCause cause(Throwable throwable, Function<Throwable, ErrorName> nameFunc) {
public static ErrorCause cause(Throwable throwable,
Function<Throwable, ErrorName> nameFunc,
ErrorPredicate retryPredicate) {
boolean matched = false;
String errorCode = null;
Set<String> exceptions = new HashSet<>(4);
Set<String> targets = retryPredicate == null ? null : retryPredicate.getExceptions();
Set<String> exceptions = new HashSet<>(8);
Throwable cause = null;
Throwable candiate = null;
Throwable t = throwable;
ErrorName errorName;
Predicate<Throwable> predicate = retryPredicate == null ? null : retryPredicate.getPredicate();
while (t != null) {
if (predicate != null && predicate.test(t)) {
matched = true;
break;
}
errorName = nameFunc.apply(t);
if (errorName != null) {
if (errorName.getName() != null) {
exceptions.add(errorName.getName());
if (cause == null) {
cause = t;
}
// add exception name
exceptions.add(errorName.getName());
// add super class
Class<?> p = t.getClass();
// generic exception such as org.apache.dubbo.rpc.service.GenericException
p = p.getName().equals(errorName.getName()) ? p.getSuperclass() : null;
while (p != null && p != Object.class) {
if (exceptions.add(p.getName())) {
p = p.getSuperclass();
} else {
break;
}
}
}
if (errorCode == null && errorName.getCode() != null) {
errorCode = errorName.getCode();
Expand All @@ -66,16 +103,6 @@ public static ErrorCause cause(Throwable throwable, Function<Throwable, ErrorNam
t = t.getCause() != t ? t.getCause() : null;
}
cause = cause == null ? (candiate == null ? throwable : candiate) : cause;
return new ErrorCause(cause, errorCode, exceptions);
}

/**
* Checks if the given circuit breaker policy matches the error code or exceptions.
*
* @param policy the circuit breaker policy to match against
* @return true if the policy matches the error code or exceptions, false otherwise
*/
public boolean match(CircuitBreakPolicy policy) {
return policy != null && (policy.containsError(errorCode) || policy.containsException(exceptions));
return new ErrorCause(cause, errorCode, exceptions, targets, matched);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jd.live.agent.governance.invoke.exception;
package com.jd.live.agent.governance.exception;

import lombok.AllArgsConstructor;
import lombok.Getter;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright © ${year} ${owner} (${email})
*
* 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 com.jd.live.agent.governance.exception;

import java.util.Set;

/**
* An interface representing an error policy.
*/
public interface ErrorPolicy {

/**
* Checks if the feature or functionality is enabled.
*
* @return true if the feature or functionality is enabled, false otherwise.
*/
boolean isEnabled();

/**
* Checks if the specified error code is present in the list of error codes.
*
* @param errorCode the error code to check.
* @return {@code true} if the error code is present, {@code false} otherwise.
*/
boolean containsError(String errorCode);

/**
* Checks if the given class name is present in the list of exceptions.
*
* @param className The class name to check.
* @return true if the class name is found in the list of exceptions, false otherwise.
*/
boolean containsException(String className);

/**
* Checks if any of the given class names are present in the list of exceptions.
*
* @param classNames The set of class names to check.
* @return true if any of the class names are found in the list of exceptions, false otherwise.
*/
boolean containsException(Set<String> classNames);

/**
* Checks if any of the exception sources are present in the set of target exceptions.
*
* @param sources the set of exception sources to check.
* @param targets the set of target exceptions to check against.
* @return true if any of the exception sources are found in the set of target exceptions, false otherwise.
*/
static boolean containsException(Set<String> sources, Set<String> targets) {
if (targets == null || targets.isEmpty() || sources == null || sources.isEmpty()) {
return false;
}
Set<String> lows = sources.size() < targets.size() ? sources : targets;
Set<String> mores = sources.size() < targets.size() ? targets : sources;
for (String low : lows) {
if (mores.contains(low)) {
return true;
}
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright © ${year} ${owner} (${email})
*
* 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 com.jd.live.agent.governance.exception;

import lombok.Getter;

import java.util.Set;
import java.util.function.Predicate;

/**
* An interface that defines a retry predicate used to determine if a failed operation should be retried.
*/
public interface ErrorPredicate {

/**
* Returns the predicate used to determine if a failed operation should be retried.
*
* @return the retry predicate.
*/
Predicate<Throwable> getPredicate();

/**
* Returns the set of exception names that should be retried.
*
* @return the set of exception names.
*/
Set<String> getExceptions();

/**
* A default implementation of the ErrorPredicate interface.
*/
@Getter
class DefaultErrorPredicate implements ErrorPredicate {

private final Predicate<Throwable> predicate;

private final Set<String> exceptions;

/**
* Creates a new instance of the DefaultErrorPredicate class.
*
* @param predicate the predicate used to determine if a failed operation should be retried.
* @param exceptions the set of exception names that should be retried.
*/
public DefaultErrorPredicate(Predicate<Throwable> predicate, Set<String> exceptions) {
this.predicate = predicate;
this.exceptions = exceptions;
}

@Override
public Predicate<Throwable> getPredicate() {
return predicate;
}

@Override
public Set<String> getExceptions() {
return exceptions;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jd.live.agent.governance.response;
package com.jd.live.agent.governance.exception;

import lombok.Getter;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,6 @@ E extends Endpoint> E route(OutboundInvocation<R> invocation,
* @param <R> The type of the outbound request, which must extend {@link OutboundRequest}.
* @param <O> The type of the outbound response.
* @param <E> The type of the endpoint to which requests are routed.
* @param <T> The type of the exception that can be thrown during invocation.
* @param cluster The live cluster of the service.
* @param invocation The outbound service request invocation to be processed.
* @param endpoint The endpoint through which the request will be sent.
Expand All @@ -402,8 +401,7 @@ E extends Endpoint> E route(OutboundInvocation<R> invocation,
*/
default <R extends OutboundRequest,
O extends OutboundResponse,
E extends Endpoint,
T extends Throwable> CompletionStage<O> outbound(LiveCluster<R, O, E, T> cluster,
E extends Endpoint> CompletionStage<O> outbound(LiveCluster<R, O, E> cluster,
OutboundInvocation<R> invocation,
E endpoint) {
try {
Expand Down
Loading

0 comments on commit 0d0958d

Please sign in to comment.