1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.linecorp.centraldogma.client.spring;
17
18 import java.net.UnknownHostException;
19 import java.util.List;
20 import java.util.Optional;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.TimeUnit;
23 import java.util.concurrent.TimeoutException;
24
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
28 import org.springframework.boot.context.properties.EnableConfigurationProperties;
29 import org.springframework.context.annotation.Bean;
30 import org.springframework.context.annotation.Configuration;
31 import org.springframework.core.env.Environment;
32
33 import com.google.common.net.HostAndPort;
34
35 import com.linecorp.armeria.client.ClientFactory;
36 import com.linecorp.armeria.client.ClientFactoryBuilder;
37 import com.linecorp.centraldogma.client.CentralDogma;
38 import com.linecorp.centraldogma.client.armeria.ArmeriaCentralDogmaBuilder;
39 import com.linecorp.centraldogma.client.armeria.ArmeriaClientConfigurator;
40 import com.linecorp.centraldogma.client.armeria.DnsAddressEndpointGroupConfigurator;
41
42 import io.micrometer.core.instrument.MeterRegistry;
43
44
45
46
47 @Configuration
48 @ConditionalOnMissingBean(CentralDogma.class)
49 @EnableConfigurationProperties(CentralDogmaSettings.class)
50 public class CentralDogmaClientAutoConfiguration {
51
52 private static final Logger logger = LoggerFactory.getLogger(CentralDogmaClientAutoConfiguration.class);
53
54 static final long DEFAULT_INITIALIZATION_TIMEOUT_MILLIS = 15000;
55
56
57
58
59 @Bean
60 public CentralDogma dogmaClient(
61 Environment env,
62 CentralDogmaSettings settings,
63 Optional<List<CentralDogmaClientFactoryConfigurator>> factoryConfigurators,
64 Optional<ArmeriaClientConfigurator> armeriaClientConfigurator,
65 Optional<DnsAddressEndpointGroupConfigurator> dnsAddressEndpointGroupConfigurator,
66 Optional<MeterRegistry> meterRegistry)
67 throws UnknownHostException {
68
69 final ArmeriaCentralDogmaBuilder builder = new ArmeriaCentralDogmaBuilder();
70
71 if (factoryConfigurators.isPresent()) {
72 final ClientFactoryBuilder clientFactoryBuilder = ClientFactory.builder();
73 factoryConfigurators.get().forEach(configurator -> configurator.configure(clientFactoryBuilder));
74 builder.clientFactory(clientFactoryBuilder.build());
75 }
76
77 builder.clientConfigurator(cb -> armeriaClientConfigurator.ifPresent(
78 configurator -> configurator.configure(cb)));
79 dnsAddressEndpointGroupConfigurator.ifPresent(builder::dnsAddressEndpointGroupConfigurator);
80
81
82 final Long healthCheckIntervalMillis = settings.getHealthCheckIntervalMillis();
83 if (healthCheckIntervalMillis != null) {
84 builder.healthCheckIntervalMillis(healthCheckIntervalMillis);
85 }
86
87
88 final Boolean useTls = settings.getUseTls();
89 if (useTls != null) {
90 builder.useTls(useTls);
91 }
92
93
94 final String accessToken = settings.getAccessToken();
95 if (accessToken != null) {
96 builder.accessToken(accessToken);
97 }
98
99
100 final String profile = settings.getProfile();
101 final List<String> hosts = settings.getHosts();
102 if (profile != null) {
103 if (hosts != null) {
104 throw new IllegalStateException(
105 "'hosts' and 'profile' are mutually exclusive. Do not set both of them.");
106 }
107 builder.profile(CentralDogmaClientAutoConfiguration.class.getClassLoader(), profile);
108 } else if (hosts != null) {
109 for (String h : hosts) {
110 final HostAndPort hostAndPort = HostAndPort.fromString(h);
111 if (hostAndPort.hasPort()) {
112 builder.host(hostAndPort.getHost(), hostAndPort.getPort());
113 } else {
114 builder.host(hostAndPort.getHost());
115 }
116 }
117 } else {
118
119 final String[] springBootProfiles = env.getActiveProfiles();
120 logger.info("Using the Spring Boot profiles as the source of the Central Dogma client profile: {}",
121 springBootProfiles);
122 builder.profile(springBootProfiles);
123 }
124
125
126 final Integer maxNumRetriesOnReplicationLag = settings.getMaxNumRetriesOnReplicationLag();
127 if (maxNumRetriesOnReplicationLag != null) {
128 builder.maxNumRetriesOnReplicationLag(maxNumRetriesOnReplicationLag);
129 }
130
131 final Long retryIntervalOnReplicationLagMillis = settings.getRetryIntervalOnReplicationLagMillis();
132 if (retryIntervalOnReplicationLagMillis != null) {
133 builder.retryIntervalOnReplicationLagMillis(retryIntervalOnReplicationLagMillis);
134 }
135
136 meterRegistry.ifPresent(builder::meterRegistry);
137
138 final CentralDogma centralDogma = builder.build();
139 Long initializationTimeoutMillis = settings.getInitializationTimeoutMillis();
140 if (initializationTimeoutMillis == null) {
141 initializationTimeoutMillis = DEFAULT_INITIALIZATION_TIMEOUT_MILLIS;
142 }
143 if (initializationTimeoutMillis > 0) {
144 try {
145 centralDogma.whenEndpointReady().get(initializationTimeoutMillis, TimeUnit.MILLISECONDS);
146 } catch (InterruptedException | ExecutionException | TimeoutException e) {
147 throw new IllegalStateException(
148 "Failed to initialize the endpoints of " + centralDogma + " in " +
149 initializationTimeoutMillis + " milliseconds", e);
150 }
151 }
152 return centralDogma;
153 }
154 }