All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zalando.riptide.failsafe.FailsafePlugin Maven / Gradle / Ivy

package org.zalando.riptide.failsafe;

import lombok.AllArgsConstructor;
import net.jodah.failsafe.Failsafe;
import net.jodah.failsafe.Policy;
import net.jodah.failsafe.RetryPolicy;
import org.apiguardian.api.API;
import org.organicdesign.fp.collections.ImList;
import org.springframework.http.client.ClientHttpResponse;
import org.zalando.riptide.Plugin;
import org.zalando.riptide.RequestArguments;
import org.zalando.riptide.RequestExecution;
import org.zalando.riptide.idempotency.IdempotencyPredicate;

import java.util.List;
import java.util.function.Predicate;

import static java.util.stream.Collectors.toList;
import static lombok.AccessLevel.PRIVATE;
import static org.apiguardian.api.API.Status.MAINTAINED;
import static org.organicdesign.fp.StaticImports.vec;
import static org.zalando.riptide.Attributes.RETRIES;
import static org.zalando.riptide.failsafe.TaskDecorator.identity;

@API(status = MAINTAINED)
@AllArgsConstructor(access = PRIVATE)
public final class FailsafePlugin implements Plugin {

    private final ImList policies;
    private final TaskDecorator decorator;

    public FailsafePlugin() {
        this(vec(), identity());
    }

    public FailsafePlugin withPolicy(final BackupRequest policy) {
        return withPolicy(policy, new IdempotencyPredicate());
    }

    public FailsafePlugin withPolicy(final RetryPolicy policy) {
        return withPolicy(new RetryRequestPolicy(policy));
    }

    public FailsafePlugin withPolicy(final Policy policy) {
        return withPolicy(RequestPolicy.of(policy));
    }

    public FailsafePlugin withPolicy(
            final Policy policy,
            final Predicate predicate) {
        return withPolicy(RequestPolicy.of(policy, predicate));
    }

    public FailsafePlugin withPolicy(final RequestPolicy policy) {
        return new FailsafePlugin(policies.append(policy), decorator);
    }

    public FailsafePlugin withDecorator(final TaskDecorator decorator) {
        return new FailsafePlugin(policies, decorator);
    }

    @Override
    public RequestExecution aroundAsync(final RequestExecution execution) {
        return arguments -> {
            final List> policies = select(arguments);

            if (policies.isEmpty()) {
                return execution.execute(arguments);
            }

            return Failsafe.with(select(arguments))
                    .getStageAsync(decorator.decorate(context -> execution
                            .execute(withAttempts(arguments, context.getAttemptCount()))));
        };
    }

    private List> select(final RequestArguments arguments) {
        return policies.stream()
                .filter(policy -> policy.applies(arguments))
                .map(policy -> policy.prepare(arguments))
                .collect(toList());
    }

    private RequestArguments withAttempts(
            final RequestArguments arguments,
            final int attempts) {

        if (attempts == 0) {
            return arguments;
        }

        return arguments.withAttribute(RETRIES, attempts);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy