/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 gobblin.util.limiter; import java.util.concurrent.TimeUnit; import com.google.common.base.Preconditions; import gobblin.configuration.State; /** * A default factory class for {@link Limiter}s. * * @author Yinan Li */ public class DefaultLimiterFactory { public static final String EXTRACT_LIMIT_TYPE_KEY = "extract.limit.type"; public static final String EXTRACT_LIMIT_RATE_LIMIT_KEY = "extract.limit.rateLimit"; public static final String EXTRACT_LIMIT_RATE_LIMIT_TIMEUNIT_KEY = "extract.limit.rateLimitTimeunit"; public static final String EXTRACT_LIMIT_TIME_LIMIT_KEY = "extract.limit.timeLimit"; public static final String EXTRACT_LIMIT_TIME_LIMIT_TIMEUNIT_KEY = "extract.limit.timeLimitTimeunit"; public static final String EXTRACT_LIMIT_COUNT_LIMIT_KEY = "extract.limit.count.limit"; public static final String EXTRACT_LIMIT_POOL_SIZE_KEY = "extract.limit.pool.size"; @Deprecated public static final String EXTRACT_LIMIT_RATE_LIMIT_KEY_DEP = "extract.limit.rate.limit"; @Deprecated public static final String EXTRACT_LIMIT_RATE_LIMIT_TIMEUNIT_KEY_DEP = "extract.limit.rate.limit.timeunit"; @Deprecated public static final String EXTRACT_LIMIT_TIME_LIMIT_KEY_DEP = "extract.limit.time.limit"; @Deprecated public static final String EXTRACT_LIMIT_TIME_LIMIT_TIMEUNIT_KEY_DEP = "extract.limit.time.limit.timeunit"; /** * Create a new {@link Limiter} instance of one of the types in {@link BaseLimiterType}. * * <p> * Note this method will always return a new {@link Limiter} instance of one of the supported types defined * in {@link BaseLimiterType} as long as the input configuration specifies a supported {@link BaseLimiterType}. * It will throw an {@link IllegalArgumentException} if none of the supported {@link BaseLimiterType}s is * specified or if any of the required configuration properties for the specified {@link BaseLimiterType} * is not present. * </p> * * <p> * This method will return a functional {@link Limiter} if the configuration is correct. If instead, a * {@link Limiter} is optional or the caller is fine with a {@link Limiter} that is not really limiting any * events, then the caller should first make sure that the {@link Limiter} should indeed be created using * this method, or handle the exception (if any is thrown) appropriately. * </p> * * @param state a {@link State} instance carrying configuration properties * @return a new {@link Limiter} instance * @throws IllegalArgumentException if the input configuration does not specify a valid supported */ public static Limiter newLimiter(State state) { state = convertDeprecatedConfigs(state); Preconditions.checkArgument(state.contains(EXTRACT_LIMIT_TYPE_KEY), String.format("Missing configuration property %s for the Limiter type", EXTRACT_LIMIT_TYPE_KEY)); BaseLimiterType type = BaseLimiterType.forName(state.getProp(EXTRACT_LIMIT_TYPE_KEY)); switch (type) { case RATE_BASED: Preconditions.checkArgument(state.contains(EXTRACT_LIMIT_RATE_LIMIT_KEY)); int rateLimit = Integer.parseInt(state.getProp(EXTRACT_LIMIT_RATE_LIMIT_KEY)); if (state.contains(EXTRACT_LIMIT_RATE_LIMIT_TIMEUNIT_KEY)) { TimeUnit rateTimeUnit = TimeUnit.valueOf(state.getProp(EXTRACT_LIMIT_RATE_LIMIT_TIMEUNIT_KEY).toUpperCase()); return new RateBasedLimiter(rateLimit, rateTimeUnit); } return new RateBasedLimiter(rateLimit); case TIME_BASED: Preconditions.checkArgument(state.contains(EXTRACT_LIMIT_TIME_LIMIT_KEY)); long timeLimit = Long.parseLong(state.getProp(EXTRACT_LIMIT_TIME_LIMIT_KEY)); if (state.contains(EXTRACT_LIMIT_TIME_LIMIT_TIMEUNIT_KEY)) { TimeUnit timeTimeUnit = TimeUnit.valueOf(state.getProp(EXTRACT_LIMIT_TIME_LIMIT_TIMEUNIT_KEY).toUpperCase()); return new TimeBasedLimiter(timeLimit, timeTimeUnit); } return new TimeBasedLimiter(timeLimit); case COUNT_BASED: Preconditions.checkArgument(state.contains(EXTRACT_LIMIT_COUNT_LIMIT_KEY)); long countLimit = Long.parseLong(state.getProp(EXTRACT_LIMIT_COUNT_LIMIT_KEY)); return new CountBasedLimiter(countLimit); case POOL_BASED: Preconditions.checkArgument(state.contains(EXTRACT_LIMIT_POOL_SIZE_KEY)); int poolSize = Integer.parseInt(state.getProp(EXTRACT_LIMIT_POOL_SIZE_KEY)); return new PoolBasedLimiter(poolSize); default: throw new IllegalArgumentException("Unrecognized Limiter type: " + type.toString()); } } /** * Convert deprecated keys {@value #EXTRACT_LIMIT_RATE_LIMIT_KEY_DEP}, {@value #EXTRACT_LIMIT_RATE_LIMIT_TIMEUNIT_KEY_DEP}, * {@value #EXTRACT_LIMIT_TIME_LIMIT_KEY_DEP}, and {@value #EXTRACT_LIMIT_TIME_LIMIT_TIMEUNIT_KEY_DEP}, since they are not * TypeSafe compatible. The deprecated keys will be removed from @param state, and replaced with * {@value #EXTRACT_LIMIT_RATE_LIMIT_KEY}, {@value #EXTRACT_LIMIT_RATE_LIMIT_TIMEUNIT_KEY}, {@value #EXTRACT_LIMIT_TIME_LIMIT_KEY}, * and {@value #EXTRACT_LIMIT_TIME_LIMIT_TIMEUNIT_KEY}, respectively. */ private static State convertDeprecatedConfigs(State state) { if (state.contains(EXTRACT_LIMIT_RATE_LIMIT_KEY_DEP)) { state.setProp(EXTRACT_LIMIT_RATE_LIMIT_KEY, state.getProp(EXTRACT_LIMIT_RATE_LIMIT_KEY_DEP)); state.removeProp(EXTRACT_LIMIT_RATE_LIMIT_KEY_DEP); } if (state.contains(EXTRACT_LIMIT_RATE_LIMIT_TIMEUNIT_KEY_DEP)) { state.setProp(EXTRACT_LIMIT_RATE_LIMIT_TIMEUNIT_KEY, state.getProp(EXTRACT_LIMIT_RATE_LIMIT_TIMEUNIT_KEY_DEP)); state.removeProp(EXTRACT_LIMIT_RATE_LIMIT_TIMEUNIT_KEY_DEP); } if (state.contains(EXTRACT_LIMIT_TIME_LIMIT_KEY_DEP)) { state.setProp(EXTRACT_LIMIT_TIME_LIMIT_KEY, state.getProp(EXTRACT_LIMIT_TIME_LIMIT_KEY_DEP)); state.removeProp(EXTRACT_LIMIT_TIME_LIMIT_KEY_DEP); } if (state.contains(EXTRACT_LIMIT_TIME_LIMIT_TIMEUNIT_KEY_DEP)) { state.setProp(EXTRACT_LIMIT_TIME_LIMIT_TIMEUNIT_KEY, state.getProp(EXTRACT_LIMIT_TIME_LIMIT_TIMEUNIT_KEY_DEP)); state.removeProp(EXTRACT_LIMIT_TIME_LIMIT_TIMEUNIT_KEY_DEP); } return state; } }