/* * 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.policies.time; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.Period; import org.joda.time.format.PeriodFormatter; import org.joda.time.format.PeriodFormatterBuilder; import com.google.common.base.Optional; import gobblin.configuration.ConfigurationKeys; import gobblin.configuration.State; import gobblin.qualitychecker.row.RowLevelPolicy; import gobblin.writer.partitioner.TimeBasedWriterPartitioner; /** * An abstract {@link RowLevelPolicy} for checking a record's timestamp against the earliest allowed timestamp. * Records whose timestamps are earlier than the earliest allowed timestamp will fail. * * @author Ziyang Liu */ public abstract class RecordTimestampLowerBoundPolicy extends RowLevelPolicy { public static final String RECORD_MAX_ALLOWED_TIME_AGO = "record.max.allowed.time.ago"; public static final PeriodFormatter PERIOD_FORMATTER = new PeriodFormatterBuilder().appendMonths().appendSuffix("m") .appendDays().appendSuffix("d").appendHours().appendSuffix("h").toFormatter(); @SuppressWarnings("rawtypes") protected final TimeBasedWriterPartitioner partitioner; protected final DateTimeZone timeZone; protected final Optional<Long> earliestAllowedTimestamp; public RecordTimestampLowerBoundPolicy(State state, Type type) { super(state, type); this.partitioner = getPartitioner(); this.timeZone = DateTimeZone.forID( state.getProp(ConfigurationKeys.QUALITY_CHECKER_TIMEZONE, ConfigurationKeys.DEFAULT_QUALITY_CHECKER_TIMEZONE)); this.earliestAllowedTimestamp = getEarliestAllowedTimestamp(); } private Optional<Long> getEarliestAllowedTimestamp() { if (!this.state.contains(RECORD_MAX_ALLOWED_TIME_AGO)) { return Optional.<Long> absent(); } DateTime currentTime = new DateTime(this.timeZone); String maxTimeAgoStr = this.state.getProp(RECORD_MAX_ALLOWED_TIME_AGO); Period maxTimeAgo = PERIOD_FORMATTER.parsePeriod(maxTimeAgoStr); return Optional.of(currentTime.minus(maxTimeAgo).getMillis()); } protected abstract TimeBasedWriterPartitioner<?> getPartitioner(); @Override public Result executePolicy(Object record) { @SuppressWarnings("unchecked") long recordTimestamp = this.partitioner.getRecordTimestamp(record); if (this.earliestAllowedTimestamp.isPresent() && recordTimestamp < this.earliestAllowedTimestamp.get()) { return RowLevelPolicy.Result.FAILED; } return RowLevelPolicy.Result.PASSED; } }