Merge branch 'tenants-client-retry' into 'main'
tenants client retry logic See merge request fforesight/tenant-commons!18
This commit is contained in:
commit
4493aff8ee
@ -2,7 +2,6 @@ package com.knecon.fforesight.tenantcommons;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@ -16,7 +15,7 @@ import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import com.knecon.fforesight.tenantcommons.model.TenantResponse;
|
||||
import com.knecon.fforesight.tenantcommons.model.UpdateDetailsRequest;
|
||||
|
||||
@FeignClient(name = "TenantsResource", url = "${tenant-user-management-service.url}")
|
||||
@FeignClient(name = "TenantsResource", url = "${tenant-user-management-service.url}", configuration = TenantsClientConfiguration.class)
|
||||
@ResponseStatus(value = HttpStatus.OK)
|
||||
@ConditionalOnProperty(prefix = "fforesight.tenants", value = "remote", havingValue = "true")
|
||||
public interface TenantsClient extends TenantProvider {
|
||||
|
||||
@ -0,0 +1,94 @@
|
||||
package com.knecon.fforesight.tenantcommons;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import feign.RetryableException;
|
||||
import feign.Retryer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Configuration
|
||||
public class TenantsClientConfiguration {
|
||||
|
||||
public static final int INITIAL_BACKOFF_SECONDS = 15;
|
||||
public static final int MAX_BACKOFF_MINUTES = 8;
|
||||
public static final int RETRY_ATTEMPTS = 4;
|
||||
|
||||
|
||||
@Bean
|
||||
public Retryer feignRetryer() {
|
||||
|
||||
return new ExponentialRetryer(TimeUnit.SECONDS.toMillis(INITIAL_BACKOFF_SECONDS), TimeUnit.MINUTES.toMillis(MAX_BACKOFF_MINUTES), RETRY_ATTEMPTS);
|
||||
}
|
||||
|
||||
|
||||
@Slf4j
|
||||
@SuppressWarnings("PMD.ProperCloneImplementation")
|
||||
public static class ExponentialRetryer extends Retryer.Default {
|
||||
|
||||
private final long initialPeriod;
|
||||
private final long maxPeriod;
|
||||
private final int maxAttempts;
|
||||
private int attempt = 1;
|
||||
private long currentPeriod;
|
||||
|
||||
|
||||
public ExponentialRetryer(long initialPeriod, long maxPeriod, int maxAttempts) {
|
||||
|
||||
this.initialPeriod = initialPeriod;
|
||||
this.maxPeriod = maxPeriod;
|
||||
this.maxAttempts = maxAttempts;
|
||||
this.currentPeriod = initialPeriod;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void continueOrPropagate(RetryableException e) {
|
||||
|
||||
if (attempt > maxAttempts) {
|
||||
log.error("Max retry attempts reached. Giving up after {} attempts.", maxAttempts);
|
||||
throw e;
|
||||
}
|
||||
|
||||
log.info("Attempt {} - Retrying due to exception: {}", attempt, e.getMessage());
|
||||
|
||||
long interval;
|
||||
|
||||
if (e.retryAfter() != null) {
|
||||
interval = e.retryAfter().getTime() - System.currentTimeMillis();
|
||||
|
||||
if (interval > maxPeriod) {
|
||||
interval = maxPeriod;
|
||||
}
|
||||
|
||||
if (interval < 0L) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
interval = currentPeriod;
|
||||
currentPeriod = Math.min(currentPeriod * 2, maxPeriod);
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(interval);
|
||||
} catch (InterruptedException ignored) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw e; // Rethrow the exception if interrupted
|
||||
}
|
||||
|
||||
attempt++;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ExponentialRetryer clone() {
|
||||
|
||||
return new ExponentialRetryer(initialPeriod, maxPeriod, maxAttempts);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -17,9 +17,9 @@ public abstract class TenantMessagingConfiguration {
|
||||
@Value("${POD_NAME:}")
|
||||
private String podName;
|
||||
|
||||
private static final String TENANT_EVENTS_DLQ_SUFFIX = "_tenant_events_dlq";
|
||||
private static final String TENANT_CREATED_QUEUE_SUFFIX = "_tenant_created_queue";
|
||||
private static final String TENANT_DELETED_QUEUE_SUFFIX = "_tenant_deleted_queue";
|
||||
private static final String TENANT_EVENTS_DLQ_SUFFIX = "_tenant_events_error";
|
||||
private static final String TENANT_CREATED_QUEUE_SUFFIX = "_tenant_created";
|
||||
private static final String TENANT_DELETED_QUEUE_SUFFIX = "_tenant_deleted";
|
||||
|
||||
// time in ms after which a deletion will be executed when no consumer is present
|
||||
// see: https://www.rabbitmq.com/docs/ttl#queue-ttl
|
||||
|
||||
@ -17,7 +17,7 @@ public class ApplicationTaskExecutorBeanConfig {
|
||||
|
||||
@Lazy
|
||||
@Bean(name = {APPLICATION_TASK_EXECUTOR_BEAN_NAME, DEFAULT_TASK_EXECUTOR_BEAN_NAME})
|
||||
@ConditionalOnMissingBean({ThreadPoolTaskExecutor.class})
|
||||
@ConditionalOnMissingBean(name = {APPLICATION_TASK_EXECUTOR_BEAN_NAME, DEFAULT_TASK_EXECUTOR_BEAN_NAME})
|
||||
public ThreadPoolTaskExecutor applicationTaskExecutor(TaskExecutorBuilder builder) {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user