Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.yashdotdev.distributed_traffic_control.allocation;

import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

@AutoConfiguration
@EnableConfigurationProperties(AllocationProperties.class)
public class AllocationStrategyConfiguration {

@Bean
@ConditionalOnMissingBean(AllocationStrategy.class)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep the missing-bean condition behind user configurations

If a consumer declares its custom strategy in a separate @Configuration class that is processed after this imported configuration, @ConditionalOnMissingBean can register the default first, leaving two AllocationStrategy beans and making injection into capacityAllocator ambiguous. TrafficControlConfiguration imports this class directly rather than loading it through Boot’s auto-configuration ordering; the new test uses AutoConfigurations.of(...) and does not cover that import path. Ensure user bean definitions are considered before registering the default.

Useful? React with 👍 / 👎.

public AllocationStrategy allocationStrategy(
AllocationProperties allocationProperties) {
return new FixedAllocationStrategy(allocationProperties);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,22 @@

import com.yashdotdev.distributed_traffic_control.allocation.AllocationProperties;
import com.yashdotdev.distributed_traffic_control.allocation.AllocationStrategy;
import com.yashdotdev.distributed_traffic_control.allocation.AllocationStrategyConfiguration;
import com.yashdotdev.distributed_traffic_control.allocation.CapacityAllocator;
import com.yashdotdev.distributed_traffic_control.allocation.FixedAllocationStrategy;
import com.yashdotdev.distributed_traffic_control.allocation.InMemoryCapacityAllocator;
import com.yashdotdev.distributed_traffic_control.lease.*;
import com.yashdotdev.distributed_traffic_control.lease.DistributedTokenBucket;
import com.yashdotdev.distributed_traffic_control.lease.InMemoryLeaseStore;
import com.yashdotdev.distributed_traffic_control.lease.LeaseCoordinator;
import com.yashdotdev.distributed_traffic_control.lease.LeaseStore;
import com.yashdotdev.distributed_traffic_control.lease.RedisLeaseCoordinator;
import com.yashdotdev.distributed_traffic_control.monitoring.TrafficControlMetrics;
import com.yashdotdev.distributed_traffic_control.policy.*;
import com.yashdotdev.distributed_traffic_control.policy.DefaultPolicyManagementService;
import com.yashdotdev.distributed_traffic_control.policy.InMemoryPolicyProvider;
import com.yashdotdev.distributed_traffic_control.policy.PolicyManagementService;
import com.yashdotdev.distributed_traffic_control.policy.PolicyProvider;
import com.yashdotdev.distributed_traffic_control.policy.TrafficPolicy;
import com.yashdotdev.distributed_traffic_control.policy.TrafficPolicyType;
import com.yashdotdev.distributed_traffic_control.policy.PolicyStatus;
import com.yashdotdev.distributed_traffic_control.quota.InMemoryQuotaCoordinator;
import com.yashdotdev.distributed_traffic_control.quota.QuotaCoordinator;
import com.yashdotdev.distributed_traffic_control.traffic.DefaultTrafficControlService;
Expand All @@ -18,14 +27,13 @@
import io.micrometer.observation.ObservationRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.time.Clock;

import org.springframework.boot.context.properties.EnableConfigurationProperties;

@Configuration
@EnableConfigurationProperties(AllocationProperties.class)
@Import(AllocationStrategyConfiguration.class)
public class TrafficControlConfiguration {

@Bean
Expand Down Expand Up @@ -70,11 +78,6 @@ public LeaseStore leaseStore() {
return new InMemoryLeaseStore();
}

@Bean
public FixedAllocationStrategy allocationStrategy(AllocationProperties allocationProperties) {
return new FixedAllocationStrategy(allocationProperties);
}

@Bean
public CapacityAllocator capacityAllocator(LeaseCoordinator leaseCoordinator, AllocationStrategy allocationStrategy, AllocationProperties allocationProperties, LeaseStore leaseStore, Clock clock) {
return new InMemoryCapacityAllocator(leaseCoordinator, allocationStrategy, allocationProperties, leaseStore, clock);
Expand All @@ -85,19 +88,17 @@ public TrafficDecisionEngine trafficDecisionEngine(
PolicyProvider policyProvider,
QuotaCoordinator quotaCoordinator,
CapacityAllocator capacityAllocator,
TrafficControlMetrics metrics,
TrafficControlMetrics trafficControlMetrics,
ObservationRegistry observationRegistry,
DistributedTokenBucket distributedTokenBucket) {

return new TrafficDecisionEngine(
policyProvider,
quotaCoordinator,
capacityAllocator,
metrics,
trafficControlMetrics,
observationRegistry,
distributedTokenBucket);
}

@Bean
public TrafficControlService trafficControlService(TrafficDecisionEngine trafficDecisionEngine) {
return new DefaultTrafficControlService(trafficDecisionEngine);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.yashdotdev.distributed_traffic_control.allocation;

import com.yashdotdev.distributed_traffic_control.policy.TrafficPolicy;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import static org.assertj.core.api.Assertions.assertThat;

class AllocationStrategyConfigurationTest {

private final ApplicationContextRunner contextRunner =
new ApplicationContextRunner()
.withConfiguration(
org.springframework.boot.autoconfigure.AutoConfigurations.of(
AllocationStrategyConfiguration.class));

@Test
void shouldRegisterFixedAllocationStrategyByDefault() {
contextRunner.run(context -> {
assertThat(context).hasNotFailed();
assertThat(context).hasSingleBean(AllocationStrategy.class);
assertThat(context.getBean(AllocationStrategy.class))
.isInstanceOf(FixedAllocationStrategy.class);
});
}

@Test
void shouldUseCustomAllocationStrategyWhenProvided() {
contextRunner
.withUserConfiguration(CustomStrategyConfiguration.class)
.run(context -> {
assertThat(context).hasNotFailed();
assertThat(context).hasSingleBean(AllocationStrategy.class);
assertThat(context.getBean(AllocationStrategy.class))
.isInstanceOf(CustomAllocationStrategy.class);
});
}

@Configuration(proxyBeanMethods = false)
static class CustomStrategyConfiguration {

@Bean
AllocationStrategy customAllocationStrategy() {
return new CustomAllocationStrategy();
}
}

static class CustomAllocationStrategy implements AllocationStrategy {

@Override
public long determineCapacity(TrafficPolicy policy) {
return 1;
}
}
}
Loading