|
29 | 29 | from .utils.messages import Messages
|
30 | 30 | from .utils.properties import Properties, WrapperProperties
|
31 | 31 |
|
| 32 | +logger = Logger(__name__) |
| 33 | + |
32 | 34 |
|
33 | 35 | class HostSelector(Protocol):
|
34 | 36 | """
|
@@ -168,23 +170,92 @@ def _update_cache_properties_for_round_robin_cluster_info(self, round_robin_clus
|
168 | 170 |
|
169 | 171 | for pair in host_weight_pairs:
|
170 | 172 | match = search(RoundRobinHostSelector._HOST_WEIGHT_PAIRS_PATTERN, pair)
|
| 173 | + message = "RoundRobinHostSelector.RoundRobinInvalidHostWeightPairs" |
171 | 174 | if match:
|
172 | 175 | host_name = match.group("host")
|
173 | 176 | host_weight = match.group("weight")
|
174 | 177 | else:
|
175 |
| - raise AwsWrapperError(Messages.get("RoundRobinHostSelector.RoundRobinInvalidHostWeightPairs")) |
| 178 | + logger.error(message, pair) |
| 179 | + raise AwsWrapperError(Messages.get_formatted(message), pair) |
176 | 180 |
|
177 | 181 | if len(host_name) == 0 or len(host_weight) == 0:
|
178 |
| - raise AwsWrapperError(Messages.get("RoundRobinHostSelector.RoundRobinInvalidHostWeightPairs")) |
| 182 | + logger.error(message, pair) |
| 183 | + raise AwsWrapperError(Messages.get_formatted(message), pair) |
179 | 184 | try:
|
180 | 185 | weight: int = int(host_weight)
|
181 | 186 |
|
182 | 187 | if weight < RoundRobinHostSelector._DEFAULT_WEIGHT:
|
183 |
| - raise AwsWrapperError(Messages.get("RoundRobinHostSelector.RoundRobinInvalidHostWeightPairs")) |
| 188 | + logger.error(message, pair) |
| 189 | + raise AwsWrapperError(Messages.get_formatted(message), pair) |
184 | 190 |
|
185 | 191 | round_robin_cluster_info.cluster_weights_dict[host_name] = weight
|
186 | 192 | except ValueError:
|
187 |
| - raise AwsWrapperError(Messages.get("RoundRobinHostSelector.RoundRobinInvalidHostWeightPairs")) |
| 193 | + logger.error(message, pair) |
| 194 | + raise AwsWrapperError(Messages.get_formatted(message), pair) |
188 | 195 |
|
189 | 196 | def clear_cache(self):
|
190 | 197 | RoundRobinHostSelector._round_robin_cache.clear()
|
| 198 | + |
| 199 | + |
| 200 | +class WeightedRandomHostSelector(HostSelector): |
| 201 | + _DEFAULT_WEIGHT: int = 1 |
| 202 | + _HOST_WEIGHT_PAIRS_PATTERN = r"((?P<host>[^:/?#]*):(?P<weight>.*))" |
| 203 | + _host_weight_map: Dict[str, int] = {} |
| 204 | + |
| 205 | + def get_host(self, hosts: Tuple[HostInfo, ...], role: HostRole, props: Optional[Properties] = None) -> HostInfo: |
| 206 | + |
| 207 | + eligible_hosts: List[HostInfo] = [host for host in hosts if host.role == role and host.get_availability() == HostAvailability.AVAILABLE] |
| 208 | + eligible_hosts.sort(key=lambda host: host.host, reverse=False) |
| 209 | + if len(eligible_hosts) == 0: |
| 210 | + message = "HostSelector.NoHostsMatchingRole" |
| 211 | + logger.error(message, role) |
| 212 | + raise AwsWrapperError(Messages.get_formatted("HostSelector.NoHostsMatchingRole", role)) |
| 213 | + |
| 214 | + self._update_host_weight_map_from_string(props) |
| 215 | + |
| 216 | + default_weight: int = WeightedRandomHostSelector._DEFAULT_WEIGHT |
| 217 | + if props is not None: |
| 218 | + default_weight = WrapperProperties.WEIGHTED_RANDOM_DEFAULT_WEIGHT.get_int(props) |
| 219 | + if default_weight < WeightedRandomHostSelector._DEFAULT_WEIGHT: |
| 220 | + logger.error("WeightedRandomHostSelector.WeightedRandomInvalidDefaultWeight") |
| 221 | + raise AwsWrapperError(Messages.get("WeightedRandomHostSelector.WeightedRandomInvalidDefaultWeight")) |
| 222 | + |
| 223 | + selection_list: List[HostInfo] = [] |
| 224 | + for host in eligible_hosts: |
| 225 | + if host.host in self._host_weight_map: |
| 226 | + selection_list = selection_list + self._host_weight_map[host.host] * [host] |
| 227 | + else: |
| 228 | + selection_list = selection_list + default_weight * [host] |
| 229 | + |
| 230 | + return random.choice(selection_list) |
| 231 | + |
| 232 | + def _update_host_weight_map_from_string(self, props: Optional[Properties] = None) -> None: |
| 233 | + if props is not None: |
| 234 | + host_weights: Optional[str] = WrapperProperties.WEIGHTED_RANDOM_HOST_WEIGHT_PAIRS.get(props) |
| 235 | + if host_weights is not None and len(host_weights) != 0: |
| 236 | + host_weight_pairs: List[str] = host_weights.split(",") |
| 237 | + |
| 238 | + for pair in host_weight_pairs: |
| 239 | + match = search(WeightedRandomHostSelector._HOST_WEIGHT_PAIRS_PATTERN, pair) |
| 240 | + message = "WeightedRandomHostSelector.WeightedRandomInvalidHostWeightPairs" |
| 241 | + if match: |
| 242 | + host_name = match.group("host") |
| 243 | + host_weight = match.group("weight") |
| 244 | + else: |
| 245 | + logger.error(message, pair) |
| 246 | + raise AwsWrapperError(Messages.get_formatted(message), pair) |
| 247 | + |
| 248 | + if len(host_name) == 0 or len(host_weight) == 0: |
| 249 | + logger.error(message, pair) |
| 250 | + raise AwsWrapperError(Messages.get_formatted(message), pair) |
| 251 | + try: |
| 252 | + weight: int = int(host_weight) |
| 253 | + |
| 254 | + if weight < WeightedRandomHostSelector._DEFAULT_WEIGHT: |
| 255 | + logger.error(message, pair) |
| 256 | + raise AwsWrapperError(Messages.get_formatted(message), pair) |
| 257 | + |
| 258 | + self._host_weight_map[host_name] = weight |
| 259 | + except ValueError: |
| 260 | + logger.error(message, pair) |
| 261 | + raise AwsWrapperError(Messages.get_formatted(message), pair) |
0 commit comments