Skip to content

Commit

Permalink
review retry
Browse files Browse the repository at this point in the history
  • Loading branch information
hexiaofeng committed May 8, 2024
1 parent b258923 commit 989a3d0
Show file tree
Hide file tree
Showing 25 changed files with 184 additions and 154 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
*/
package com.jd.live.agent.bootstrap.bytekit.context;

import com.jd.live.agent.bootstrap.util.AttributeAccessorSupport;
import com.jd.live.agent.bootstrap.util.AbstractAttributes;
import lombok.Getter;
import lombok.Setter;

/**
* An abstract class representing an executable context.
* This class provides a structure to hold information related to an executable task or operation.
*/
public abstract class ExecutableContext extends AttributeAccessorSupport {
public abstract class ExecutableContext extends AbstractAttributes {

/**
* The type of the executable.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,27 @@
*/
package com.jd.live.agent.bootstrap.util;

import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.BiConsumer;

public abstract class AttributeAccessorSupport implements AttributeAccessor, Serializable {
/**
* Provides a skeletal implementation of the {@link Attributes} interface to minimize the effort required to implement this interface.
* <p>
* This abstract class implements the {@code copy} and {@code forEach} methods of the {@code Attributes} interface, relying on the concrete
* class to implement the methods for accessing and modifying the attributes. The {@code copy} method uses the {@code forEach} method
* from the provided {@code Attributes} instance to copy all attributes to the current instance. Concrete implementations of this class
* must implement the {@code getAttribute}, {@code setAttribute}, {@code removeAttribute}, and {@code hasAttribute} methods.
* </p>
*/
public abstract class AbstractAttributes implements Attributes {

private Map<String, Object> attributes;

public AttributeAccessorSupport() {
public AbstractAttributes() {
}

@Override
public void setAttribute(String key, Object value) {
if (key != null && value != null) {
if (attributes == null) {
Expand All @@ -35,44 +45,30 @@ public void setAttribute(String key, Object value) {
}
}

@Override
@SuppressWarnings("unchecked")
public <T> T getAttribute(String key) {
return key == null || attributes == null ? null : (T) attributes.get(key);
}

@Override
@SuppressWarnings("unchecked")
public <T> T removeAttribute(String key) {
if (key != null && attributes != null) {
return (T) attributes.remove(key);
}
return null;
}

@Override
public boolean hasAttribute(String key) {
return this.attributes.containsKey(key);
}

public String[] attributeNames() {
return this.attributes.keySet().toArray(new String[0]);
}

public void copyAttributesFrom(AttributeAccessor source) {
String[] attributeNames = source.attributeNames();
for (String name : attributeNames) {
this.setAttribute(name, source.getAttribute(name));
}
return key != null && attributes.containsKey(key);
}

public boolean equals(Object other) {
if (this == other) {
return true;
} else if (!(other instanceof AttributeAccessorSupport)) {
return false;
} else {
AttributeAccessorSupport that = (AttributeAccessorSupport) other;
return this.attributes.equals(that.attributes);
@Override
public void attributes(BiConsumer<String, Object> consumer) {
if (attributes != null && consumer != null) {
attributes.forEach(consumer);
}
}

public int hashCode() {
return this.attributes.hashCode();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* 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.bootstrap.util;

import java.util.function.BiConsumer;

/**
* Provides a contract for setting and getting attributes generically.
* This interface allows for the storage and retrieval of attributes.
*/
public interface Attributes {

/**
* Retrieves an attribute by key.
*
* @param key The key of the attribute to retrieve.
* @return The value of the attribute, or null if not found.
*/
<T> T getAttribute(String key);

/**
* Sets or replaces an attribute with the specified key and value.
*
* @param key The key of the attribute.
* @param value The value of the attribute.
*/
void setAttribute(String key, Object value);

/**
* Removes an attribute by its key.
*
* @param key The key of the attribute to remove.
* @return The removed attribute, or null if the attribute was not found.
*/
<T> T removeAttribute(String key);

/**
* Checks if an attribute with the specified key exists.
* <p>This method is used to determine whether an attribute is associated with the given key.</p>
*
* @param key The key of the attribute to check. Cannot be {@code null}.
* @return {@code true} if an attribute with the specified key exists; {@code false} otherwise.
*/
boolean hasAttribute(String key);

/**
* Performs the given action for each attribute in this instance until all attributes
* have been processed or the action throws an exception. Actions are performed in
* the order of attribute insertion when possible.
*
* @param consumer The action to be performed for each attribute
*/
void attributes(BiConsumer<String, Object> consumer);

/**
* Copies all source from the provided Attributes instance into this one.
* If an attribute with the same key already exists in this instance, its value
* is replaced with the value from the provided Attributes instance.
*
* @param source the Attributes instance from which to copy source
*/
default void copyAttribute(Attributes source) {
if (source != null) {
source.attributes(this::setAttribute);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -170,5 +170,13 @@ public static boolean hasCargo() {
Carrier carrier = CARRIER.get();
return carrier != null && carrier.getCargos() != null && !carrier.getCargos().isEmpty();
}

/**
* Determines if the current time has exceeded a specified deadline.
*/
public static boolean isTimeout() {
Long deadline = getAttribute(Carrier.ATTRIBUTE_DEADLINE);
return deadline != null && System.currentTimeMillis() > deadline;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
package com.jd.live.agent.governance.context.bag;

import com.jd.live.agent.bootstrap.util.AttributeAccessor;
import com.jd.live.agent.bootstrap.util.Attributes;

import java.util.*;
import java.util.function.BiConsumer;
Expand All @@ -30,7 +30,7 @@
* iterating over cargos and attributes in various ways to suit different use cases.
* </p>
*/
public interface Carrier extends AttributeAccessor {
public interface Carrier extends Attributes {

String ATTRIBUTE_FAILOVER_UNIT = "x-live-failover-unit";

Expand All @@ -40,6 +40,8 @@ public interface Carrier extends AttributeAccessor {

String ATTRIBUTE_GATEWAY = "x-live-gateway";

String ATTRIBUTE_DEADLINE = "deadline";

/**
* Retrieves all cargos carried by this carrier.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,35 @@
*/
package com.jd.live.agent.governance.context.bag;

import com.jd.live.agent.bootstrap.util.AttributeAccessorSupport;
import com.jd.live.agent.bootstrap.util.AbstractAttributes;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class Courier extends AttributeAccessorSupport implements Carrier {
public class Courier extends AbstractAttributes implements Carrier {

protected Map<String, Cargo> tags;
protected Map<String, Cargo> cargos;

@Override
public Collection<Cargo> getCargos() {
return tags == null ? null : tags.values();
return cargos == null ? null : cargos.values();
}

@Override
public Cargo getCargo(String key) {
return tags == null ? null : tags.get(key);
return cargos == null ? null : cargos.get(key);
}

@Override
public void addCargo(Cargo cargo) {
if (cargo != null) {
String name = cargo.getKey();
if (name != null && !name.isEmpty()) {
if (tags == null) {
tags = new HashMap<>();
if (cargos == null) {
cargos = new HashMap<>();
}
Cargo old = tags.putIfAbsent(cargo.getKey(), cargo);
Cargo old = cargos.putIfAbsent(cargo.getKey(), cargo);
if (old != null && old != cargo) {
cargo.add(cargo.getValues());
}
Expand All @@ -54,27 +54,27 @@ public void addCargo(Cargo cargo) {
@Override
public void addCargo(String key, String value) {
if (key != null && !key.isEmpty()) {
if (tags == null) {
tags = new HashMap<>();
if (cargos == null) {
cargos = new HashMap<>();
}
tags.computeIfAbsent(key, Cargo::new).add(value);
cargos.computeIfAbsent(key, Cargo::new).add(value);
}
}

@Override
public void setCargo(String key, String value) {
if (key != null && !key.isEmpty()) {
if (tags == null) {
tags = new HashMap<>();
if (cargos == null) {
cargos = new HashMap<>();
}
tags.put(key, new Cargo(key, value));
cargos.put(key, new Cargo(key, value));
}
}

@Override
public void removeCargo(String key) {
if (key != null && !key.isEmpty() && tags != null) {
tags.remove(key);
if (key != null && !key.isEmpty() && cargos != null) {
cargos.remove(key);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
package com.jd.live.agent.governance.interceptor;

import com.jd.live.agent.bootstrap.bytekit.context.MethodContext;
import com.jd.live.agent.bootstrap.util.AttributeAccessorSupport;
import com.jd.live.agent.core.plugin.definition.InterceptorAdaptor;
import com.jd.live.agent.governance.context.RequestContext;
import com.jd.live.agent.governance.instance.Endpoint;
import com.jd.live.agent.governance.invoke.InboundInvocation;
import com.jd.live.agent.governance.invoke.InboundInvocation.GatewayInboundInvocation;
Expand All @@ -39,6 +39,8 @@
import java.util.List;
import java.util.function.Supplier;

import static com.jd.live.agent.governance.invoke.retry.Retrier.DEADLINE_KEY;

/**
* AbstractInterceptor is the base class for all interceptors within the framework.
* It provides a common context for the interception process and defines the structure
Expand Down Expand Up @@ -184,8 +186,8 @@ protected Supplier<Response> createRetrySupplier(MethodContext ctx) {
} catch (Throwable throwable) {
response = createResponse(ctx.getResult(), throwable);
} finally {
if (response instanceof AttributeAccessorSupport) {
((AttributeAccessorSupport) response).copyAttributesFrom(ctx);
if (response != null) {
response.copyAttribute(ctx);
}
}
return response;
Expand Down Expand Up @@ -214,7 +216,10 @@ protected Object invokeWithRetry(O invocation, MethodContext ctx) {
RetrierFactory retrierFactory = context.getOrDefaultRetrierFactory(retryPolicy.getType());
Retrier retrier = retrierFactory == null ? null : retrierFactory.get(retryPolicy);
if (retrier != null) {
ctx.setAttribute(Retrier.DEADLINE_KEY, System.currentTimeMillis() + retryPolicy.getTimeout());
Long timeout = retryPolicy.getTimeout();
if (timeout != null && timeout > 0) {
RequestContext.getOrCreate().setAttribute(DEADLINE_KEY, System.currentTimeMillis() + timeout);
}
return retrier.execute(retrySupplier);
}
}
Expand Down
Loading

0 comments on commit 989a3d0

Please sign in to comment.