Skip to content

Commit

Permalink
Issue ReactiveX#531: Added events to TimeLimiter (ReactiveX#583)
Browse files Browse the repository at this point in the history
  • Loading branch information
hexmind authored and RobWin committed Aug 23, 2019
1 parent 93b0819 commit 6be60e8
Show file tree
Hide file tree
Showing 13 changed files with 487 additions and 33 deletions.
2 changes: 1 addition & 1 deletion resilience4j-timelimiter/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
dependencies {

compile project(':resilience4j-core')
}
ext.moduleName='io.github.resilience4j.timelimiter'
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
package io.github.resilience4j.timelimiter;

import io.github.resilience4j.core.EventConsumer;
import io.github.resilience4j.timelimiter.event.TimeLimiterEvent;
import io.github.resilience4j.timelimiter.event.TimeLimiterOnFailureEvent;
import io.github.resilience4j.timelimiter.event.TimeLimiterOnSuccessEvent;
import io.github.resilience4j.timelimiter.event.TimeLimiterOnTimeoutEvent;
import io.github.resilience4j.timelimiter.internal.TimeLimiterImpl;

import java.time.Duration;
import java.util.concurrent.*;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.function.Supplier;

/**
* A TimeLimiter decorator stops execution after a configurable duration.
*/
public interface TimeLimiter {

String DEFAULT_NAME = "UNDEFINED";

/**
* Creates a TimeLimiter decorator with a default TimeLimiterConfig configuration.
*
* @return The {@link TimeLimiter}
*/
static TimeLimiter ofDefaults() {
return new TimeLimiterImpl(TimeLimiterConfig.ofDefaults());
return new TimeLimiterImpl(DEFAULT_NAME, TimeLimiterConfig.ofDefaults());
}

/**
Expand All @@ -27,7 +35,18 @@ static TimeLimiter ofDefaults() {
* @return The {@link TimeLimiter}
*/
static TimeLimiter of(TimeLimiterConfig timeLimiterConfig) {
return new TimeLimiterImpl(timeLimiterConfig);
return of(DEFAULT_NAME, timeLimiterConfig);
}

/**
* Creates a TimeLimiter decorator with a TimeLimiterConfig configuration.
*
* @param name the name of the TimeLimiter
* @param timeLimiterConfig the TimeLimiterConfig
* @return The {@link TimeLimiter}
*/
static TimeLimiter of(String name, TimeLimiterConfig timeLimiterConfig) {
return new TimeLimiterImpl(name, timeLimiterConfig);
}

/**
Expand All @@ -40,8 +59,7 @@ static TimeLimiter of(Duration timeoutDuration) {
TimeLimiterConfig timeLimiterConfig = TimeLimiterConfig.custom()
.timeoutDuration(timeoutDuration)
.build();

return new TimeLimiterImpl(timeLimiterConfig);
return new TimeLimiterImpl(DEFAULT_NAME, timeLimiterConfig);
}

/**
Expand All @@ -54,26 +72,7 @@ static TimeLimiter of(Duration timeoutDuration) {
* @return a future supplier which is restricted by a {@link TimeLimiter}.
*/
static <T, F extends Future<T>> Callable<T> decorateFutureSupplier(TimeLimiter timeLimiter, Supplier<F> futureSupplier) {
return () -> {
Future<T> future = futureSupplier.get();
try {
return future.get(timeLimiter.getTimeLimiterConfig().getTimeoutDuration().toMillis(), TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
if(timeLimiter.getTimeLimiterConfig().shouldCancelRunningFuture()){
future.cancel(true);
}
throw e;
} catch (ExecutionException e){
Throwable t = e.getCause();
if (t == null){
throw e;
}
if (t instanceof Error){
throw (Error) t;
}
throw (Exception) t;
}
};
return timeLimiter.decorateFutureSupplier(futureSupplier);
}

/**
Expand Down Expand Up @@ -104,7 +103,24 @@ default <T, F extends Future<T>> T executeFutureSupplier(Supplier<F> futureSuppl
* @param <F> the future type supplied
* @return a future supplier which is restricted by a {@link TimeLimiter}.
*/
default <T, F extends Future<T>> Callable<T> decorateFutureSupplier(Supplier<F> futureSupplier) {
return decorateFutureSupplier(this, futureSupplier);
<T, F extends Future<T>> Callable<T> decorateFutureSupplier(Supplier<F> futureSupplier);

EventPublisher getEventPublisher();

void onSuccess();

void onError(Exception exception);

/**
* An EventPublisher which can be used to register event consumers.
*/
interface EventPublisher extends io.github.resilience4j.core.EventPublisher<TimeLimiterEvent> {

EventPublisher onSuccess(EventConsumer<TimeLimiterOnSuccessEvent> eventConsumer);

EventPublisher onFailure(EventConsumer<TimeLimiterOnFailureEvent> eventConsumer);

EventPublisher onTimeout(EventConsumer<TimeLimiterOnTimeoutEvent> eventConsumer);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
public class TimeLimiterConfig {
private static final String TIMEOUT_DURATION_MUST_NOT_BE_NULL = "TimeoutDuration must not be null";

private Duration timeoutDuration = Duration.ofSeconds(1);
private Duration timeoutDuration = Duration.ofSeconds(1);
private boolean cancelRunningFuture = true;

private TimeLimiterConfig() {
Expand All @@ -27,7 +27,7 @@ public static Builder custom() {
*
* @return a default TimeLimiter configuration.
*/
public static TimeLimiterConfig ofDefaults(){
public static TimeLimiterConfig ofDefaults() {
return new Builder().build();
}

Expand All @@ -39,7 +39,8 @@ public boolean shouldCancelRunningFuture() {
return cancelRunningFuture;
}

@Override public String toString() {
@Override
public String toString() {
return "TimeLimiterConfig{" +
"timeoutDuration=" + timeoutDuration +
"cancelRunningFuture=" + cancelRunningFuture +
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
*
* Copyright 2019 authors
*
* 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 io.github.resilience4j.timelimiter.event;

import java.time.ZonedDateTime;

public abstract class AbstractTimeLimiterEvent implements TimeLimiterEvent {

private final String timeLimiterName;
private Type eventType;
private final ZonedDateTime creationTime;

AbstractTimeLimiterEvent(String timeLimiterName, Type eventType) {
this.timeLimiterName = timeLimiterName;
this.eventType = eventType;
this.creationTime = ZonedDateTime.now();
}

@Override
public String getTimeLimiterName() {
return timeLimiterName;
}

@Override
public ZonedDateTime getCreationTime() {
return creationTime;
}

@Override
public Type getEventType() {
return eventType;
}

@Override
public String toString() {
return "TimeLimiterEvent{" +
"type=" + getEventType() +
", timeLimiterName='" + getTimeLimiterName() + '\'' +
", creationTime=" + getCreationTime() +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
*
* Copyright 2019 authors
*
* 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 io.github.resilience4j.timelimiter.event;

import java.time.ZonedDateTime;

/**
* An event which is created by a {@link io.github.resilience4j.timelimiter.TimeLimiter}.
*/
public interface TimeLimiterEvent {

static TimeLimiterEvent of(String name, Type eventType) {
switch (eventType) {
case SUCCESS:
return new TimeLimiterOnSuccessEvent(name);
case TIMEOUT:
return new TimeLimiterOnTimeoutEvent(name);
default:
return new TimeLimiterOnFailureEvent(name);
}
}

String getTimeLimiterName();

Type getEventType();

ZonedDateTime getCreationTime();

enum Type {
SUCCESS,
TIMEOUT,
FAILURE
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
*
* Copyright 2019 authors
*
* 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 io.github.resilience4j.timelimiter.event;

public class TimeLimiterOnFailureEvent extends AbstractTimeLimiterEvent {

public TimeLimiterOnFailureEvent(String timeLimiterName) {
super(timeLimiterName, Type.FAILURE);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
*
* Copyright 2019 authors
*
* 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 io.github.resilience4j.timelimiter.event;

public class TimeLimiterOnSuccessEvent extends AbstractTimeLimiterEvent {

public TimeLimiterOnSuccessEvent(String timeLimiterName) {
super(timeLimiterName, Type.SUCCESS);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
*
* Copyright 2019 authors
*
* 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 io.github.resilience4j.timelimiter.event;

public class TimeLimiterOnTimeoutEvent extends AbstractTimeLimiterEvent {

public TimeLimiterOnTimeoutEvent(String timeLimiterName) {
super(timeLimiterName, Type.TIMEOUT);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
*
* Copyright 2019 authors
*
* 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.
*
*
*/
@NonNullApi
@NonNullFields
package io.github.resilience4j.timelimiter.event;

import io.github.resilience4j.core.lang.NonNullApi;
import io.github.resilience4j.core.lang.NonNullFields;
Loading

0 comments on commit 6be60e8

Please sign in to comment.