This is an automated email from the ASF dual-hosted git repository. yihua pushed a commit to branch release-1.2.0 in repository https://gitbox.apache.org/repos/asf/hudi.git
commit 11a243752970322d4febfc28137240c6470651df Author: deepakpanda93 <[email protected]> AuthorDate: Wed May 20 01:29:19 2026 +0530 fix(aws): implement writer-version update in Glue sync client (#18707) --- .../hudi/aws/sync/AWSGlueCatalogSyncClient.java | 16 +++++++ .../hudi/aws/sync/TestAWSGlueSyncClient.java | 51 ++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/hudi-aws/src/main/java/org/apache/hudi/aws/sync/AWSGlueCatalogSyncClient.java b/hudi-aws/src/main/java/org/apache/hudi/aws/sync/AWSGlueCatalogSyncClient.java index faf015a9aaf5..884b5c53a25d 100644 --- a/hudi-aws/src/main/java/org/apache/hudi/aws/sync/AWSGlueCatalogSyncClient.java +++ b/hudi-aws/src/main/java/org/apache/hudi/aws/sync/AWSGlueCatalogSyncClient.java @@ -18,6 +18,7 @@ package org.apache.hudi.aws.sync; +import org.apache.hudi.HoodieVersion; import org.apache.hudi.aws.credentials.HoodieAWSCredentialsProviderFactory; import org.apache.hudi.aws.sync.util.GluePartitionFilterGenerator; import org.apache.hudi.common.fs.FSUtils; @@ -532,6 +533,21 @@ public class AWSGlueCatalogSyncClient extends HoodieSyncClient { } } + @Override + public void updateHoodieWriterVersion(String tableName) { + try { + updateTableParameters( + awsGlue, + databaseName, + tableName, + Collections.singletonMap(HoodieVersion.HOODIE_WRITER_VERSION, HoodieVersion.get()), + skipTableArchive); + } catch (Exception e) { + throw new HoodieGlueSyncException(String.format("Failed to update hudi writer version %s for %s", + HoodieVersion.get(), tableName), e); + } + } + @Override public void updateTableSchema(String tableName, HoodieSchema newSchema, SchemaDifference schemaDiff) { try { diff --git a/hudi-aws/src/test/java/org/apache/hudi/aws/sync/TestAWSGlueSyncClient.java b/hudi-aws/src/test/java/org/apache/hudi/aws/sync/TestAWSGlueSyncClient.java index 0cbe4b764bc0..f4822e32f05d 100644 --- a/hudi-aws/src/test/java/org/apache/hudi/aws/sync/TestAWSGlueSyncClient.java +++ b/hudi-aws/src/test/java/org/apache/hudi/aws/sync/TestAWSGlueSyncClient.java @@ -18,6 +18,7 @@ package org.apache.hudi.aws.sync; +import org.apache.hudi.HoodieVersion; import org.apache.hudi.aws.testutils.GlueTestUtil; import org.apache.hudi.common.config.TypedProperties; import org.apache.hudi.common.schema.HoodieSchema; @@ -774,6 +775,56 @@ class TestAWSGlueSyncClient { assertEquals("Production", dbTagRequest.tagsToAdd().get("Environment")); } + @Test + void testUpdateHoodieWriterVersion() throws ExecutionException, InterruptedException { + String tableName = "test"; + List<Column> columns = Arrays.asList( + GlueTestUtil.getColumn("name", "string", "person's name"), + GlueTestUtil.getColumn("age", "int", "person's age")); + List<Column> partitionKeys = Collections.singletonList( + GlueTestUtil.getColumn("city", "string", "person's city")); + CompletableFuture<GetTableResponse> tableResponseFuture = + getTableWithDefaultProps(tableName, columns, partitionKeys); + + CompletableFuture<UpdateTableResponse> mockUpdateTableResponse = Mockito.mock(CompletableFuture.class); + Mockito.when(mockUpdateTableResponse.get()).thenReturn(UpdateTableResponse.builder().build()); + Mockito.when(mockAwsGlue.getTable(any(GetTableRequest.class))).thenReturn(tableResponseFuture); + Mockito.when(mockAwsGlue.updateTable(any(UpdateTableRequest.class))).thenReturn(mockUpdateTableResponse); + + awsGlueSyncClient.updateHoodieWriterVersion(tableName); + + // Capture the request to verify the writer-version parameter was set correctly + ArgumentCaptor<UpdateTableRequest> captor = ArgumentCaptor.forClass(UpdateTableRequest.class); + verify(mockAwsGlue, times(1)).updateTable(captor.capture()); + UpdateTableRequest sent = captor.getValue(); + assertEquals( + HoodieVersion.get(), + sent.tableInput().parameters().get(HoodieVersion.HOODIE_WRITER_VERSION), + "Writer version parameter should be set on the table"); + } + + @Test + void testUpdateHoodieWriterVersionThrowsGlueException() throws ExecutionException, InterruptedException { + String tableName = "test"; + List<Column> columns = Collections.singletonList( + GlueTestUtil.getColumn("name", "string", "person's name")); + List<Column> partitionKeys = Collections.singletonList( + GlueTestUtil.getColumn("city", "string", "person's city")); + CompletableFuture<GetTableResponse> tableResponseFuture = + getTableWithDefaultProps(tableName, columns, partitionKeys); + + CompletableFuture<UpdateTableResponse> mockUpdateTableResponse = Mockito.mock(CompletableFuture.class); + Mockito.when(mockUpdateTableResponse.get()).thenThrow(new InterruptedException()); + Mockito.when(mockAwsGlue.getTable(any(GetTableRequest.class))).thenReturn(tableResponseFuture); + Mockito.when(mockAwsGlue.updateTable(any(UpdateTableRequest.class))).thenReturn(mockUpdateTableResponse); + + HoodieGlueSyncException ex = assertThrows( + HoodieGlueSyncException.class, + () -> awsGlueSyncClient.updateHoodieWriterVersion(tableName)); + assertTrue(ex.getMessage().contains(tableName), "exception message should mention the table"); + assertTrue(ex.getMessage().contains(HoodieVersion.get()), "exception message should mention the writer version"); + } + private CompletableFuture<GetTableResponse> getTableWithDefaultProps(String tableName, List<Column> columns, List<Column> partitionColumns) { String databaseName = "testdb"; String inputFormatClass = "inputFormat";
