Skip to content

Commit

Permalink
Refactor config classes
Browse files Browse the repository at this point in the history
  • Loading branch information
the-other-tim-brown committed Aug 19, 2024
1 parent 18667ee commit 3159009
Show file tree
Hide file tree
Showing 38 changed files with 992 additions and 765 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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 org.apache.xtable.conversion;

import java.util.List;

import lombok.Builder;
import lombok.NonNull;
import lombok.Value;

import com.google.common.base.Preconditions;

import org.apache.xtable.model.sync.SyncMode;

@Value
public class ConversionConfig {
// The source of the sync
@NonNull SourceTable sourceTable;
// One or more targets to sync the table metadata to
List<TargetTable> targetTables;
// The mode, incremental or snapshot
SyncMode syncMode;

@Builder
ConversionConfig(
@NonNull SourceTable sourceTable, List<TargetTable> targetTables, SyncMode syncMode) {
this.sourceTable = sourceTable;
this.targetTables = targetTables;
Preconditions.checkArgument(
targetTables != null && !targetTables.isEmpty(),
"Please provide at-least one format to sync");
this.syncMode = syncMode == null ? SyncMode.INCREMENTAL : syncMode;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* 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 org.apache.xtable.conversion;

import java.util.Properties;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;

import org.apache.hadoop.fs.Path;

import com.google.common.base.Preconditions;

/** Defines a reference to a table in a particular format. */
@Getter
@EqualsAndHashCode
class ExternalTable {
/** The name of the table. */
protected final @NonNull String name;
/** The format of the table (e.g. DELTA, ICEBERG, HUDI) */
protected final @NonNull String formatName;
/** The path to the root of the table or the metadata directory depending on the format */
protected final @NonNull String basePath;
/** Optional namespace for the table */
protected final String[] namespace;
/** The configuration for interacting with the catalog that manages this table */
protected final CatalogConfig catalogConfig;

/** Optional, additional properties that can be used to define interactions with the table */
protected final Properties additionalProperties;

ExternalTable(
@NonNull String name,
@NonNull String formatName,
@NonNull String basePath,
String[] namespace,
CatalogConfig catalogConfig,
Properties additionalProperties) {
this.name = name;
this.formatName = formatName;
this.basePath = sanitizeBasePath(basePath);
this.namespace = namespace;
this.catalogConfig = catalogConfig;
this.additionalProperties = additionalProperties;
}

protected String sanitizeBasePath(String tableBasePath) {
Path path = new Path(tableBasePath);
Preconditions.checkArgument(path.isAbsolute(), "Table base path must be absolute");
if (path.isAbsoluteAndSchemeAuthorityNull()) {
// assume this is local file system and append scheme
return "file://" + path;
} else if (path.toUri().getScheme().equals("file")) {
// add extra slashes
return "file://" + path.toUri().getPath();
} else {
return path.toString();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,29 @@

package org.apache.xtable.conversion;

import org.apache.xtable.spi.extractor.SourcePartitionSpecExtractor;
import java.util.Properties;

public interface HudiSourceConfig {
String getPartitionSpecExtractorClass();
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;

SourcePartitionSpecExtractor loadSourcePartitionSpecExtractor();
@EqualsAndHashCode(callSuper = true)
@Getter
public class SourceTable extends ExternalTable {
/** The path to the data files, defaults to the metadataPath */
@NonNull private final String dataPath;

@Builder(toBuilder = true)
public SourceTable(
String name,
String formatName,
String basePath,
String dataPath,
String[] namespace,
CatalogConfig catalogConfig,
Properties additionalProperties) {
super(name, formatName, basePath, namespace, catalogConfig, additionalProperties);
this.dataPath = dataPath == null ? this.getBasePath() : sanitizeBasePath(dataPath);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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 org.apache.xtable.conversion;

import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.Properties;

import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;

@Getter
@EqualsAndHashCode(callSuper = true)
public class TargetTable extends ExternalTable {
private final Duration metadataRetention;

@Builder(toBuilder = true)
public TargetTable(
String name,
String formatName,
String basePath,
String[] namespace,
CatalogConfig catalogConfig,
Duration metadataRetention,
Properties additionalProperties) {
super(name, formatName, basePath, namespace, catalogConfig, additionalProperties);
this.metadataRetention =
metadataRetention == null ? Duration.of(7, ChronoUnit.DAYS) : metadataRetention;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

import org.apache.hadoop.conf.Configuration;

import org.apache.xtable.conversion.PerTableConfig;
import org.apache.xtable.conversion.TargetTable;
import org.apache.xtable.model.InternalTable;
import org.apache.xtable.model.metadata.TableSyncMetadata;
import org.apache.xtable.model.schema.InternalPartitionField;
Expand Down Expand Up @@ -89,5 +89,5 @@ public interface ConversionTarget {
String getTableFormat();

/** Initializes the client with provided configuration */
void init(PerTableConfig perTableConfig, Configuration configuration);
void init(TargetTable targetTable, Configuration configuration);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* 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 org.apache.xtable.conversion;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

import org.junit.jupiter.api.Test;

public class TestExternalTable {
@Test
void sanitizePath() {
ExternalTable tooManySlashes =
new ExternalTable("name", "hudi", "s3://bucket//path", null, null, null);
assertEquals("s3://bucket/path", tooManySlashes.getBasePath());

ExternalTable localFilePath =
new ExternalTable("name", "hudi", "/local/data//path", null, null, null);
assertEquals("file:///local/data/path", localFilePath.getBasePath());

ExternalTable properLocalFilePath =
new ExternalTable("name", "hudi", "file:///local/data//path", null, null, null);
assertEquals("file:///local/data/path", properLocalFilePath.getBasePath());
}

@Test
void errorIfRequiredArgsNotSet() {
assertThrows(
NullPointerException.class,
() -> new ExternalTable("name", "hudi", null, null, null, null));

assertThrows(
NullPointerException.class,
() -> new ExternalTable("name", null, "file://bucket/path", null, null, null));

assertThrows(
NullPointerException.class,
() -> new ExternalTable(null, "hudi", "file://bucket/path", null, null, null));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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 org.apache.xtable.conversion;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

class TestSourceTable {
@Test
void dataPathDefaultsToMetadataPath() {
String basePath = "file:///path/to/table";
SourceTable sourceTable =
SourceTable.builder().name("name").formatName("hudi").basePath(basePath).build();
assertEquals(basePath, sourceTable.getDataPath());
}

@Test
void dataPathIsSanitized() {
String basePath = "file:///path/to/table";
String dataPath = "file:///path/to/table//data";
SourceTable sourceTable =
SourceTable.builder()
.name("name")
.formatName("hudi")
.basePath(basePath)
.dataPath(dataPath)
.build();
assertEquals("file:///path/to/table/data", sourceTable.getDataPath());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,18 @@

package org.apache.xtable.conversion;

import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;

import org.apache.xtable.model.sync.SyncMode;
import java.time.Duration;

public interface PerTableConfig {
int getTargetMetadataRetentionInHours();
import org.junit.jupiter.api.Test;

String getTableBasePath();

String getTableDataPath();

String getTableName();

HudiSourceConfig getHudiSourceConfig();

List<String> getTargetTableFormats();

SyncMode getSyncMode();

String[] getNamespace();

CatalogConfig getIcebergCatalogConfig();
class TestTargetTable {
@Test
void retentionDefaultsToSevenDays() {
String basePath = "file:///path/to/table";
TargetTable targetTable =
TargetTable.builder().name("name").formatName("hudi").basePath(basePath).build();
assertEquals(Duration.ofDays(7), targetTable.getMetadataRetention());
}
}
Loading

0 comments on commit 3159009

Please sign in to comment.