Skip to content

Commit

Permalink
Merge branch 'master' into query-map-encoder-choice
Browse files Browse the repository at this point in the history
  • Loading branch information
velo authored Oct 2, 2023
2 parents 8a2c298 + e9b0765 commit f9a898d
Show file tree
Hide file tree
Showing 55 changed files with 1,415 additions and 380 deletions.
14 changes: 7 additions & 7 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
executors:
java:
docker:
- image: velo/toolchains-4-ci-builds
- image: velo/toolchains-4-ci-builds:with-21

# common commands
commands:
Expand Down Expand Up @@ -81,13 +81,13 @@ jobs:
- checkout
- restore_cache:
keys:
- feign-dependencies-{{ checksum "pom.xml" }}
- feign-dependencies-
- feign-dependencies-v2-{{ checksum "pom.xml" }}
- feign-dependencies-v2-
- resolve-dependencies
- save_cache:
paths:
- ~/.m2
key: feign-dependencies-{{ checksum "pom.xml" }}
- ~/.m2/repository
key: feign-dependencies-v2-{{ checksum "pom.xml" }}
- run:
name: 'Test'
command: |
Expand All @@ -102,8 +102,8 @@ jobs:
- checkout
- restore_cache:
keys:
- feign-dependencies-{{ checksum "pom.xml" }}
- feign-dependencies-
- feign-dependencies-v2-{{ checksum "pom.xml" }}
- feign-dependencies-v2-
- resolve-dependencies
- configure-gpg
- nexus-deploy
Expand Down
Binary file modified .mvn/wrapper/maven-wrapper.jar
Binary file not shown.
20 changes: 18 additions & 2 deletions .mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,18 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,17 @@ public class Example {
For the lighter weight Jackson Jr, use `JacksonJrEncoder` and `JacksonJrDecoder` from
the [Jackson Jr Module](./jackson-jr).
#### Moshi
[Moshi](./moshi) includes an encoder and decoder you can use with a JSON API.
Add `MoshiEncoder` and/or `MoshiDecoder` to your `Feign.Builder` like so:
```java
GitHub github = Feign.builder()
.encoder(new MoshiEncoder())
.decoder(new MoshiDecoder())
.target(GitHub.class, "https://api.github.com");
```
#### Sax
[SaxDecoder](./sax) allows you to decode XML in a way that is compatible with normal JVM and also Android environments.
Expand Down
2 changes: 1 addition & 1 deletion apt-test-generator/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
<version>3.5.1</version>
<executions>
<execution>
<phase>package</phase>
Expand Down
15 changes: 8 additions & 7 deletions benchmark/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<jmh.version>1.37</jmh.version>
<rx.netty.version>0.5.3</rx.netty.version>
<rx.java.version>1.3.8</rx.java.version>
<netty.version>4.1.97.Final</netty.version>
<netty.version>4.1.99.Final</netty.version>
<main.basedir>${project.basedir}/..</main.basedir>

<moditect.skip>true</moditect.skip>
Expand Down Expand Up @@ -68,11 +68,6 @@
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>${bouncy.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
Expand Down Expand Up @@ -124,9 +119,15 @@
<version>${jmh.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>${slf4j.version}</version>
</dependency>
</dependencies>

Expand All @@ -136,7 +137,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
<version>3.5.1</version>
<executions>
<execution>
<phase>package</phase>
Expand Down
2 changes: 1 addition & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.11</version>
<version>6.0.12</version>
<scope>test</scope>
</dependency>

Expand Down
3 changes: 2 additions & 1 deletion core/src/main/java/feign/FeignException.java
Original file line number Diff line number Diff line change
Expand Up @@ -271,12 +271,13 @@ private static FeignServerException serverErrorStatus(int status,
}

static FeignException errorExecuting(Request request, IOException cause) {
final Long nonRetryable = null;
return new RetryableException(
-1,
format("%s executing %s %s", cause.getMessage(), request.httpMethod(), request.url()),
request.httpMethod(),
cause,
null, request);
nonRetryable, request);
}

public static class FeignClientException extends FeignException {
Expand Down
31 changes: 28 additions & 3 deletions core/src/main/java/feign/RetryableException.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,22 @@
*/
public class RetryableException extends FeignException {

private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 2L;

private final Long retryAfter;
private final HttpMethod httpMethod;

/**
* @param retryAfter usually corresponds to the {@link feign.Util#RETRY_AFTER} header.
*/
public RetryableException(int status, String message, HttpMethod httpMethod, Throwable cause,
Long retryAfter, Request request) {
super(status, message, request, cause);
this.httpMethod = httpMethod;
this.retryAfter = retryAfter;
}

@Deprecated
public RetryableException(int status, String message, HttpMethod httpMethod, Throwable cause,
Date retryAfter, Request request) {
super(status, message, request, cause);
Expand All @@ -42,6 +50,14 @@ public RetryableException(int status, String message, HttpMethod httpMethod, Thr
/**
* @param retryAfter usually corresponds to the {@link feign.Util#RETRY_AFTER} header.
*/
public RetryableException(int status, String message, HttpMethod httpMethod, Long retryAfter,
Request request) {
super(status, message, request);
this.httpMethod = httpMethod;
this.retryAfter = retryAfter;
}

@Deprecated
public RetryableException(int status, String message, HttpMethod httpMethod, Date retryAfter,
Request request) {
super(status, message, request);
Expand All @@ -52,6 +68,15 @@ public RetryableException(int status, String message, HttpMethod httpMethod, Dat
/**
* @param retryAfter usually corresponds to the {@link feign.Util#RETRY_AFTER} header.
*/
public RetryableException(int status, String message, HttpMethod httpMethod, Long retryAfter,
Request request, byte[] responseBody,
Map<String, Collection<String>> responseHeaders) {
super(status, message, request, responseBody, responseHeaders);
this.httpMethod = httpMethod;
this.retryAfter = retryAfter;
}

@Deprecated
public RetryableException(int status, String message, HttpMethod httpMethod, Date retryAfter,
Request request, byte[] responseBody, Map<String, Collection<String>> responseHeaders) {
super(status, message, request, responseBody, responseHeaders);
Expand All @@ -63,8 +88,8 @@ public RetryableException(int status, String message, HttpMethod httpMethod, Dat
* Sometimes corresponds to the {@link feign.Util#RETRY_AFTER} header present in {@code 503}
* status. Other times parsed from an application-specific response. Null if unknown.
*/
public Date retryAfter() {
return retryAfter != null ? new Date(retryAfter) : null;
public Long retryAfter() {
return retryAfter;
}

public HttpMethod method() {
Expand Down
8 changes: 4 additions & 4 deletions core/src/main/java/feign/Retryer.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
public interface Retryer extends Cloneable {

/**
* if retry is permitted, return (possibly after sleeping). Otherwise propagate the exception.
* if retry is permitted, return (possibly after sleeping). Otherwise, propagate the exception.
*/
void continueOrPropagate(RetryableException e);

Expand Down Expand Up @@ -59,7 +59,7 @@ public void continueOrPropagate(RetryableException e) {

long interval;
if (e.retryAfter() != null) {
interval = e.retryAfter().getTime() - currentTimeMillis();
interval = e.retryAfter() - currentTimeMillis();
if (interval > maxPeriod) {
interval = maxPeriod;
}
Expand All @@ -79,15 +79,15 @@ public void continueOrPropagate(RetryableException e) {
}

/**
* Calculates the time interval to a retry attempt. <br>
* Calculates the time interval to a retry attempt.<br>
* The interval increases exponentially with each attempt, at a rate of nextInterval *= 1.5
* (where 1.5 is the backoff factor), to the maximum interval.
*
* @return time in milliseconds from now until the next attempt.
*/
long nextMaxInterval() {
long interval = (long) (period * Math.pow(1.5, attempt - 1));
return interval > maxPeriod ? maxPeriod : interval;
return Math.min(interval, maxPeriod);
}

@Override
Expand Down
39 changes: 17 additions & 22 deletions core/src/main/java/feign/codec/ErrorDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,15 @@
import static feign.FeignException.errorStatus;
import static feign.Util.RETRY_AFTER;
import static feign.Util.checkNotNull;
import static java.util.Locale.US;
import static java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME;
import static java.util.concurrent.TimeUnit.SECONDS;
import feign.FeignException;
import feign.Response;
import feign.RetryableException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Collection;
import java.util.Date;
import java.util.Map;

/**
Expand Down Expand Up @@ -103,7 +102,7 @@ public Default(Integer maxBodyBytesLength, Integer maxBodyCharsLength) {
public Exception decode(String methodKey, Response response) {
FeignException exception = errorStatus(methodKey, response, maxBodyBytesLength,
maxBodyCharsLength);
Date retryAfter = retryAfterDecoder.apply(firstOrNull(response.headers(), RETRY_AFTER));
Long retryAfter = retryAfterDecoder.apply(firstOrNull(response.headers(), RETRY_AFTER));
if (retryAfter != null) {
return new RetryableException(
response.status(),
Expand All @@ -125,48 +124,44 @@ private <T> T firstOrNull(Map<String, Collection<T>> map, String key) {
}

/**
* Decodes a {@link feign.Util#RETRY_AFTER} header into an absolute date, if possible. <br>
* Decodes a {@link feign.Util#RETRY_AFTER} header into an epoch millisecond, if possible.<br>
* See <a href="https://tools.ietf.org/html/rfc2616#section-14.37">Retry-After format</a>
*/
static class RetryAfterDecoder {

static final DateFormat RFC822_FORMAT =
new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", US);
private final DateFormat rfc822Format;
private final DateTimeFormatter dateTimeFormatter;

RetryAfterDecoder() {
this(RFC822_FORMAT);
this(RFC_1123_DATE_TIME);
}

RetryAfterDecoder(DateFormat rfc822Format) {
this.rfc822Format = checkNotNull(rfc822Format, "rfc822Format");
RetryAfterDecoder(DateTimeFormatter dateTimeFormatter) {
this.dateTimeFormatter = checkNotNull(dateTimeFormatter, "dateTimeFormatter");
}

protected long currentTimeMillis() {
return System.currentTimeMillis();
}

/**
* returns a date that corresponds to the first time a request can be retried.
* returns an epoch millisecond that corresponds to the first time a request can be retried.
*
* @param retryAfter String in
* <a href="https://tools.ietf.org/html/rfc2616#section-14.37" >Retry-After format</a>
*/
public Date apply(String retryAfter) {
public Long apply(String retryAfter) {
if (retryAfter == null) {
return null;
}
if (retryAfter.matches("^[0-9]+\\.?0*$")) {
retryAfter = retryAfter.replaceAll("\\.0*$", "");
long deltaMillis = SECONDS.toMillis(Long.parseLong(retryAfter));
return new Date(currentTimeMillis() + deltaMillis);
return currentTimeMillis() + deltaMillis;
}
synchronized (rfc822Format) {
try {
return rfc822Format.parse(retryAfter);
} catch (ParseException ignored) {
return null;
}
try {
return ZonedDateTime.parse(retryAfter, dateTimeFormatter).toInstant().toEpochMilli();
} catch (NullPointerException | DateTimeParseException ignored) {
return null;
}
}
}
Expand Down
Loading

0 comments on commit f9a898d

Please sign in to comment.