Adds RouteDeletedEvent used in WeightCalculatorWebFilter

Fixes gh-922
This commit is contained in:
sgibb
2024-03-20 12:32:36 -04:00
parent f0ad75a22f
commit c79e9ad2b3
4 changed files with 63 additions and 3 deletions

View File

@@ -34,6 +34,7 @@ import reactor.core.publisher.Mono;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.event.RouteDeletedEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory;
@@ -307,9 +308,10 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
@DeleteMapping("/routes/{id}")
public Mono<ResponseEntity<Object>> delete(@PathVariable String id) {
return this.routeDefinitionWriter.delete(Mono.just(id))
.then(Mono.defer(() -> Mono.just(ResponseEntity.ok().build())))
.onErrorResume(t -> t instanceof NotFoundException, t -> Mono.just(ResponseEntity.notFound().build()));
return this.routeDefinitionWriter.delete(Mono.just(id)).then(Mono.defer(() -> {
publisher.publishEvent(new RouteDeletedEvent(this, id));
return Mono.just(ResponseEntity.ok().build());
})).onErrorResume(t -> t instanceof NotFoundException, t -> Mono.just(ResponseEntity.notFound().build()));
}
@GetMapping("/routes/{id}/combinedfilters")

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2024 the original author or 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
*
* https://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 org.springframework.cloud.gateway.event;
import org.springframework.context.ApplicationEvent;
public class RouteDeletedEvent extends ApplicationEvent {
private final String routeId;
public RouteDeletedEvent(Object source, String routeId) {
super(source);
this.routeId = routeId;
}
public String getRouteId() {
return routeId;
}
}

View File

@@ -35,6 +35,7 @@ import reactor.core.publisher.Mono;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.event.PredicateArgsEvent;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.event.RouteDeletedEvent;
import org.springframework.cloud.gateway.event.WeightDefinedEvent;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.ConfigurationService;
@@ -42,6 +43,7 @@ import org.springframework.cloud.gateway.support.WeightConfig;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.SmartApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.log.LogMessage;
import org.springframework.core.style.ToStringCreator;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
@@ -123,6 +125,8 @@ public class WeightCalculatorWebFilter implements WebFilter, Ordered, SmartAppli
return PredicateArgsEvent.class.isAssignableFrom(eventType) ||
// from java dsl
WeightDefinedEvent.class.isAssignableFrom(eventType) ||
// from actuator or custom call
RouteDeletedEvent.class.isAssignableFrom(eventType) ||
// force initialization
RefreshRoutesEvent.class.isAssignableFrom(eventType);
}
@@ -140,6 +144,9 @@ public class WeightCalculatorWebFilter implements WebFilter, Ordered, SmartAppli
else if (event instanceof WeightDefinedEvent) {
addWeightConfig(((WeightDefinedEvent) event).getWeightConfig());
}
else if (event instanceof RouteDeletedEvent) {
removeWeightConfig(((RouteDeletedEvent) event).getRouteId());
}
else if (event instanceof RefreshRoutesEvent && routeLocator != null) {
// forces initialization
if (routeLocatorInitialized.compareAndSet(false, true)) {
@@ -229,6 +236,16 @@ public class WeightCalculatorWebFilter implements WebFilter, Ordered, SmartAppli
groupWeights.put(group, config);
}
private void removeWeightConfig(String routeId) {
log.trace(LogMessage.format("Removing weight config for route %s", routeId));
groupWeights.forEach((group, weightConfig) -> {
if (weightConfig.normalizedWeights.containsKey(routeId)) {
weightConfig.normalizedWeights.remove(routeId);
weightConfig.weights.remove(routeId);
}
});
}
/* for testing */ Map<String, GroupWeightConfig> getGroupWeights() {
return groupWeights;
}

View File

@@ -24,6 +24,7 @@ import java.util.function.Supplier;
import org.junit.jupiter.api.Test;
import org.springframework.cloud.gateway.event.PredicateArgsEvent;
import org.springframework.cloud.gateway.event.RouteDeletedEvent;
import org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter.GroupWeightConfig;
import org.springframework.cloud.gateway.support.ConfigurationService;
import org.springframework.cloud.gateway.support.WeightConfig;
@@ -121,6 +122,12 @@ public class WeightCalculatorWebFilterTests {
filter.filter(exchange, filterChain);
weights = WeightCalculatorWebFilter.getWeights(exchange);
assertThat(weights).containsEntry("groupa", "route3");
filter.onApplicationEvent(new RouteDeletedEvent(this, "route3"));
assertThat(filter.getGroupWeights()).containsKey("groupa");
GroupWeightConfig groupa = filter.getGroupWeights().get("groupa");
assertThat(groupa.normalizedWeights).doesNotContainKey("route3");
assertThat(groupa.weights).doesNotContainKey("route3");
}
@Test