This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hudi.git


The following commit(s) were added to refs/heads/master by this push:
     new 4985f93d6fb3 refactor(client): dedupe HoodieJavaEngineContext with 
local context (#19981)
4985f93d6fb3 is described below

commit 4985f93d6fb38627f928ea9995625696a47a45c2
Author: voonhous <[email protected]>
AuthorDate: Fri Sep 18 13:56:55 2026 +0800

    refactor(client): dedupe HoodieJavaEngineContext with local context (#19981)
    
    * refactor(client): dedupe HoodieJavaEngineContext with local context
    
    HoodieJavaEngineContext copied every method body of
    HoodieLocalEngineContext. Make it extend HoodieLocalEngineContext
    (no longer final) and keep only its constructors and the two real
    differences: the system-property allowlist in getEngineProperties
    and the Avro key generator in createKeyGenerator.
    
    * refactor(common): share engine logic via BaseLocalEngineContext
    
    Keep HoodieLocalEngineContext final. Move the shared in-JVM method
    bodies into a new abstract BaseLocalEngineContext in hudi-common.
    HoodieLocalEngineContext and HoodieJavaEngineContext both extend it,
    so the Java context is no longer a HoodieLocalEngineContext.
---
 .../client/common/HoodieJavaEngineContext.java     | 170 +--------------------
 ...ineContext.java => BaseLocalEngineContext.java} |  18 +--
 .../common/engine/HoodieLocalEngineContext.java    | 168 +-------------------
 3 files changed, 7 insertions(+), 349 deletions(-)

diff --git 
a/hudi-client/hudi-java-client/src/main/java/org/apache/hudi/client/common/HoodieJavaEngineContext.java
 
b/hudi-client/hudi-java-client/src/main/java/org/apache/hudi/client/common/HoodieJavaEngineContext.java
index a24d6fb4c25d..06b7566174b0 100644
--- 
a/hudi-client/hudi-java-client/src/main/java/org/apache/hudi/client/common/HoodieJavaEngineContext.java
+++ 
b/hudi-client/hudi-java-client/src/main/java/org/apache/hudi/client/common/HoodieJavaEngineContext.java
@@ -19,56 +19,20 @@
 package org.apache.hudi.client.common;
 
 import org.apache.hudi.common.config.TypedProperties;
-import org.apache.hudi.common.data.HoodieAccumulator;
-import org.apache.hudi.common.data.HoodieAtomicLongAccumulator;
-import org.apache.hudi.common.data.HoodieData;
-import org.apache.hudi.common.data.HoodieData.HoodieDataCacheKey;
-import org.apache.hudi.common.data.HoodieListData;
-import org.apache.hudi.common.data.HoodieListPairData;
-import org.apache.hudi.common.data.HoodiePairData;
-import org.apache.hudi.common.engine.AvroReaderContextFactory;
-import org.apache.hudi.common.engine.EngineProperty;
-import org.apache.hudi.common.engine.HoodieEngineContext;
-import org.apache.hudi.common.engine.ReaderContextFactory;
+import org.apache.hudi.common.engine.BaseLocalEngineContext;
 import org.apache.hudi.common.engine.TaskContextSupplier;
-import org.apache.hudi.common.function.SerializableBiFunction;
-import org.apache.hudi.common.function.SerializableConsumer;
-import org.apache.hudi.common.function.SerializableFunction;
-import org.apache.hudi.common.function.SerializablePairFlatMapFunction;
-import org.apache.hudi.common.function.SerializablePairFunction;
-import org.apache.hudi.common.table.HoodieTableMetaClient;
-import org.apache.hudi.common.util.Functions;
-import org.apache.hudi.common.util.Option;
-import org.apache.hudi.common.util.collection.ImmutablePair;
-import org.apache.hudi.common.util.collection.Pair;
 import org.apache.hudi.keygen.KeyGenerator;
 import org.apache.hudi.keygen.factory.HoodieAvroKeyGeneratorFactory;
 import org.apache.hudi.storage.StorageConfiguration;
 
-import org.apache.avro.generic.IndexedRecord;
-
 import java.io.IOException;
-import java.util.Collections;
 import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static java.util.stream.Collectors.toList;
-import static 
org.apache.hudi.common.function.FunctionWrapper.throwingFlatMapToPairWrapper;
-import static 
org.apache.hudi.common.function.FunctionWrapper.throwingFlatMapWrapper;
-import static 
org.apache.hudi.common.function.FunctionWrapper.throwingForeachWrapper;
-import static 
org.apache.hudi.common.function.FunctionWrapper.throwingMapToPairWrapper;
-import static 
org.apache.hudi.common.function.FunctionWrapper.throwingMapWrapper;
-import static 
org.apache.hudi.common.function.FunctionWrapper.throwingReduceWrapper;
 
 /**
  * A java engine implementation of HoodieEngineContext.
  */
-public class HoodieJavaEngineContext extends HoodieEngineContext {
+public class HoodieJavaEngineContext extends BaseLocalEngineContext {
 
   public HoodieJavaEngineContext(StorageConfiguration<?> conf) {
     this(conf, new JavaTaskContextSupplier());
@@ -78,121 +42,6 @@ public class HoodieJavaEngineContext extends 
HoodieEngineContext {
     super(conf, taskContextSupplier);
   }
 
-  @Override
-  public HoodieAccumulator newAccumulator() {
-    return HoodieAtomicLongAccumulator.create();
-  }
-
-  @Override
-  public <T> HoodieData<T> emptyHoodieData() {
-    return HoodieListData.eager(Collections.emptyList());
-  }
-
-  @Override
-  public <K, V> HoodiePairData<K, V> emptyHoodiePairData() {
-    return HoodieListPairData.eager(Collections.emptyList());
-  }
-
-  @Override
-  public <T> HoodieData<T> parallelize(List<T> data, int parallelism) {
-    return HoodieListData.eager(data);
-  }
-
-  @Override
-  public <I, O> List<O> map(List<I> data, SerializableFunction<I, O> func, int 
parallelism) {
-    return 
data.stream().parallel().map(throwingMapWrapper(func)).collect(toList());
-  }
-
-  @Override
-  public <I, K, V> List<V> mapToPairAndReduceByKey(List<I> data, 
SerializablePairFunction<I, K, V> mapToPairFunc, SerializableBiFunction<V, V, 
V> reduceFunc, int parallelism) {
-    return 
data.stream().parallel().map(throwingMapToPairWrapper(mapToPairFunc))
-        .collect(Collectors.groupingBy(p -> p.getKey())).values().stream()
-        .map(list -> list.stream().map(e -> 
e.getValue()).reduce(throwingReduceWrapper(reduceFunc)).get())
-        .collect(Collectors.toList());
-  }
-
-  @Override
-  public <I, K, V> Stream<ImmutablePair<K, V>> 
mapPartitionsToPairAndReduceByKey(Stream<I> data, 
SerializablePairFlatMapFunction<Iterator<I>, K, V> flatMapToPairFunc,
-                                                                               
  SerializableBiFunction<V, V, V> reduceFunc, int parallelism) {
-    return 
throwingFlatMapToPairWrapper(flatMapToPairFunc).apply(data.parallel().iterator())
-        .collect(Collectors.groupingBy(Pair::getKey)).entrySet().stream()
-        .map(entry -> new ImmutablePair<>(entry.getKey(), 
entry.getValue().stream().map(
-            
Pair::getValue).reduce(throwingReduceWrapper(reduceFunc)).orElse(null)))
-        .filter(Objects::nonNull);
-  }
-
-  @Override
-  public <I, K, V> List<V> reduceByKey(
-      List<Pair<K, V>> data, SerializableBiFunction<V, V, V> reduceFunc, int 
parallelism) {
-    return data.stream().parallel()
-        .collect(Collectors.groupingBy(p -> p.getKey())).values().stream()
-        .map(list -> list.stream().map(e -> 
e.getValue()).reduce(throwingReduceWrapper(reduceFunc)).orElse(null))
-        .filter(Objects::nonNull)
-        .collect(Collectors.toList());
-  }
-
-  @Override
-  public <I, O> List<O> flatMap(List<I> data, SerializableFunction<I, 
Stream<O>> func, int parallelism) {
-    return 
data.stream().parallel().flatMap(throwingFlatMapWrapper(func)).collect(toList());
-  }
-
-  @Override
-  public <I> void foreach(List<I> data, SerializableConsumer<I> consumer, int 
parallelism) {
-    data.stream().forEach(throwingForeachWrapper(consumer));
-  }
-
-  @Override
-  public <I, K, V> Map<K, V> mapToPair(List<I> data, 
SerializablePairFunction<I, K, V> func, Integer parallelism) {
-    return data.stream().map(throwingMapToPairWrapper(func)).collect(
-        Collectors.toMap(Pair::getLeft, Pair::getRight, (oldVal, newVal) -> 
newVal)
-    );
-  }
-
-  @Override
-  public void setProperty(EngineProperty key, String value) {
-    // no operation for now
-  }
-
-  @Override
-  public Option<String> getProperty(EngineProperty key) {
-    return Option.empty();
-  }
-
-  @Override
-  public void setJobStatus(String activeModule, String activityDescription) {
-    // no operation for now
-  }
-
-  @Override
-  public void clearJobStatus() {
-    // no operation for now
-  }
-
-  @Override
-  public void putCachedDataIds(HoodieDataCacheKey cacheKey, int... ids) {
-    // no operation for now
-  }
-
-  @Override
-  public List<Integer> getCachedDataIds(HoodieDataCacheKey cacheKey) {
-    return Collections.emptyList();
-  }
-
-  @Override
-  public List<Integer> removeCachedDataIds(HoodieDataCacheKey cacheKey) {
-    return Collections.emptyList();
-  }
-
-  @Override
-  public void cancelJob(String jobId) {
-    // no operation for now
-  }
-
-  @Override
-  public void cancelAllJobs() {
-    // no operation for now
-  }
-
   // Allowlist of safe system properties to include in commit metadata. Avoid 
wildcarding system
   // properties since callers may pass credentials via -D flags (e.g. 
-Ddb.password=...).
   private static final String[] SAFE_SYSTEM_PROPERTIES = {
@@ -217,21 +66,6 @@ public class HoodieJavaEngineContext extends 
HoodieEngineContext {
     return info;
   }
 
-  @Override
-  public <I, O> O aggregate(HoodieData<I> data, O zeroValue, 
Functions.Function2<O, I, O> seqOp, Functions.Function2<O, O, O> combOp) {
-    return data.collectAsList().stream().reduce(zeroValue, seqOp::apply, 
combOp::apply);
-  }
-
-  @Override
-  public ReaderContextFactory<IndexedRecord> 
getReaderContextFactory(HoodieTableMetaClient metaClient) {
-    return getEngineReaderContextFactory(metaClient);
-  }
-
-  @Override
-  public ReaderContextFactory<IndexedRecord> 
getEngineReaderContextFactory(HoodieTableMetaClient metaClient) {
-    return new AvroReaderContextFactory(metaClient, new TypedProperties());
-  }
-
   @Override
   public KeyGenerator createKeyGenerator(TypedProperties props) throws 
IOException {
     return HoodieAvroKeyGeneratorFactory.createKeyGenerator(props);
diff --git 
a/hudi-common/src/main/java/org/apache/hudi/common/engine/HoodieLocalEngineContext.java
 
b/hudi-common/src/main/java/org/apache/hudi/common/engine/BaseLocalEngineContext.java
similarity index 91%
copy from 
hudi-common/src/main/java/org/apache/hudi/common/engine/HoodieLocalEngineContext.java
copy to 
hudi-common/src/main/java/org/apache/hudi/common/engine/BaseLocalEngineContext.java
index acae6245968e..735018e64503 100644
--- 
a/hudi-common/src/main/java/org/apache/hudi/common/engine/HoodieLocalEngineContext.java
+++ 
b/hudi-common/src/main/java/org/apache/hudi/common/engine/BaseLocalEngineContext.java
@@ -36,12 +36,10 @@ import org.apache.hudi.common.util.Functions;
 import org.apache.hudi.common.util.Option;
 import org.apache.hudi.common.util.collection.ImmutablePair;
 import org.apache.hudi.common.util.collection.Pair;
-import org.apache.hudi.keygen.KeyGenerator;
 import org.apache.hudi.storage.StorageConfiguration;
 
 import org.apache.avro.generic.IndexedRecord;
 
-import java.io.IOException;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
@@ -59,15 +57,12 @@ import static 
org.apache.hudi.common.function.FunctionWrapper.throwingMapWrapper
 import static 
org.apache.hudi.common.function.FunctionWrapper.throwingReduceWrapper;
 
 /**
- * A java based engine context, use this implementation on the query engine 
integrations if needed.
+ * Base engine context that runs everything in the current JVM over in-memory 
lists.
+ * Shared by {@link HoodieLocalEngineContext} and the Java client's engine 
context.
  */
-public final class HoodieLocalEngineContext extends HoodieEngineContext {
+public abstract class BaseLocalEngineContext extends HoodieEngineContext {
 
-  public HoodieLocalEngineContext(StorageConfiguration<?> conf) {
-    this(conf, new LocalTaskContextSupplier());
-  }
-
-  public HoodieLocalEngineContext(StorageConfiguration<?> conf, 
TaskContextSupplier taskContextSupplier) {
+  protected BaseLocalEngineContext(StorageConfiguration<?> conf, 
TaskContextSupplier taskContextSupplier) {
     super(conf, taskContextSupplier);
   }
 
@@ -202,9 +197,4 @@ public final class HoodieLocalEngineContext extends 
HoodieEngineContext {
   public ReaderContextFactory<IndexedRecord> 
getEngineReaderContextFactory(HoodieTableMetaClient metaClient) {
     return new AvroReaderContextFactory(metaClient, new TypedProperties());
   }
-
-  @Override
-  public KeyGenerator createKeyGenerator(TypedProperties props) throws 
IOException {
-    throw new UnsupportedOperationException("Not yet implemented");
-  }
 }
diff --git 
a/hudi-common/src/main/java/org/apache/hudi/common/engine/HoodieLocalEngineContext.java
 
b/hudi-common/src/main/java/org/apache/hudi/common/engine/HoodieLocalEngineContext.java
index acae6245968e..dc6a8e9dbfcc 100644
--- 
a/hudi-common/src/main/java/org/apache/hudi/common/engine/HoodieLocalEngineContext.java
+++ 
b/hudi-common/src/main/java/org/apache/hudi/common/engine/HoodieLocalEngineContext.java
@@ -19,49 +19,15 @@
 package org.apache.hudi.common.engine;
 
 import org.apache.hudi.common.config.TypedProperties;
-import org.apache.hudi.common.data.HoodieAccumulator;
-import org.apache.hudi.common.data.HoodieAtomicLongAccumulator;
-import org.apache.hudi.common.data.HoodieData;
-import org.apache.hudi.common.data.HoodieData.HoodieDataCacheKey;
-import org.apache.hudi.common.data.HoodieListData;
-import org.apache.hudi.common.data.HoodieListPairData;
-import org.apache.hudi.common.data.HoodiePairData;
-import org.apache.hudi.common.function.SerializableBiFunction;
-import org.apache.hudi.common.function.SerializableConsumer;
-import org.apache.hudi.common.function.SerializableFunction;
-import org.apache.hudi.common.function.SerializablePairFlatMapFunction;
-import org.apache.hudi.common.function.SerializablePairFunction;
-import org.apache.hudi.common.table.HoodieTableMetaClient;
-import org.apache.hudi.common.util.Functions;
-import org.apache.hudi.common.util.Option;
-import org.apache.hudi.common.util.collection.ImmutablePair;
-import org.apache.hudi.common.util.collection.Pair;
 import org.apache.hudi.keygen.KeyGenerator;
 import org.apache.hudi.storage.StorageConfiguration;
 
-import org.apache.avro.generic.IndexedRecord;
-
 import java.io.IOException;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static java.util.stream.Collectors.toList;
-import static 
org.apache.hudi.common.function.FunctionWrapper.throwingFlatMapToPairWrapper;
-import static 
org.apache.hudi.common.function.FunctionWrapper.throwingFlatMapWrapper;
-import static 
org.apache.hudi.common.function.FunctionWrapper.throwingForeachWrapper;
-import static 
org.apache.hudi.common.function.FunctionWrapper.throwingMapToPairWrapper;
-import static 
org.apache.hudi.common.function.FunctionWrapper.throwingMapWrapper;
-import static 
org.apache.hudi.common.function.FunctionWrapper.throwingReduceWrapper;
 
 /**
  * A java based engine context, use this implementation on the query engine 
integrations if needed.
  */
-public final class HoodieLocalEngineContext extends HoodieEngineContext {
+public final class HoodieLocalEngineContext extends BaseLocalEngineContext {
 
   public HoodieLocalEngineContext(StorageConfiguration<?> conf) {
     this(conf, new LocalTaskContextSupplier());
@@ -71,138 +37,6 @@ public final class HoodieLocalEngineContext extends 
HoodieEngineContext {
     super(conf, taskContextSupplier);
   }
 
-  @Override
-  public HoodieAccumulator newAccumulator() {
-    return HoodieAtomicLongAccumulator.create();
-  }
-
-  @Override
-  public <T> HoodieData<T> emptyHoodieData() {
-    return HoodieListData.eager(Collections.emptyList());
-  }
-
-  @Override
-  public <K, V> HoodiePairData<K, V> emptyHoodiePairData() {
-    return HoodieListPairData.eager(Collections.emptyList());
-  }
-
-  @Override
-  public <T> HoodieData<T> parallelize(List<T> data, int parallelism) {
-    return HoodieListData.eager(data);
-  }
-
-  @Override
-  public <I, O> List<O> map(List<I> data, SerializableFunction<I, O> func, int 
parallelism) {
-    return 
data.stream().parallel().map(throwingMapWrapper(func)).collect(toList());
-  }
-
-  @Override
-  public <I, K, V> List<V> mapToPairAndReduceByKey(List<I> data, 
SerializablePairFunction<I, K, V> mapToPairFunc,
-                                                   SerializableBiFunction<V, 
V, V> reduceFunc, int parallelism) {
-    return 
data.stream().parallel().map(throwingMapToPairWrapper(mapToPairFunc))
-        .collect(Collectors.groupingBy(p -> p.getKey())).values().stream()
-        .map(list -> list.stream().map(e -> 
e.getValue()).reduce(throwingReduceWrapper(reduceFunc)).get())
-        .collect(Collectors.toList());
-  }
-
-  @Override
-  public <I, K, V> Stream<ImmutablePair<K, V>> 
mapPartitionsToPairAndReduceByKey(
-      Stream<I> data, SerializablePairFlatMapFunction<Iterator<I>, K, V> 
flatMapToPairFunc,
-      SerializableBiFunction<V, V, V> reduceFunc, int parallelism) {
-    return 
throwingFlatMapToPairWrapper(flatMapToPairFunc).apply(data.parallel().iterator())
-        .collect(Collectors.groupingBy(Pair::getKey)).entrySet().stream()
-        .map(entry -> new ImmutablePair<>(entry.getKey(), 
entry.getValue().stream().map(
-            
Pair::getValue).reduce(throwingReduceWrapper(reduceFunc)).orElse(null)))
-        .filter(Objects::nonNull);
-  }
-
-  @Override
-  public <I, K, V> List<V> reduceByKey(
-      List<Pair<K, V>> data, SerializableBiFunction<V, V, V> reduceFunc, int 
parallelism) {
-    return data.stream().parallel()
-        .collect(Collectors.groupingBy(p -> p.getKey())).values().stream()
-        .map(list -> list.stream().map(e -> 
e.getValue()).reduce(throwingReduceWrapper(reduceFunc)).orElse(null))
-        .filter(Objects::nonNull)
-        .collect(Collectors.toList());
-  }
-
-  @Override
-  public <I, O> List<O> flatMap(List<I> data, SerializableFunction<I, 
Stream<O>> func, int parallelism) {
-    return 
data.stream().parallel().flatMap(throwingFlatMapWrapper(func)).collect(toList());
-  }
-
-  @Override
-  public <I> void foreach(List<I> data, SerializableConsumer<I> consumer, int 
parallelism) {
-    data.stream().forEach(throwingForeachWrapper(consumer));
-  }
-
-  @Override
-  public <I, K, V> Map<K, V> mapToPair(List<I> data, 
SerializablePairFunction<I, K, V> func, Integer parallelism) {
-    return data.stream().map(throwingMapToPairWrapper(func)).collect(
-        Collectors.toMap(Pair::getLeft, Pair::getRight, (oldVal, newVal) -> 
newVal)
-    );
-  }
-
-  @Override
-  public void setProperty(EngineProperty key, String value) {
-    // no operation for now
-  }
-
-  @Override
-  public Option<String> getProperty(EngineProperty key) {
-    return Option.empty();
-  }
-
-  @Override
-  public void setJobStatus(String activeModule, String activityDescription) {
-    // no operation for now
-  }
-
-  @Override
-  public void clearJobStatus() {
-    // no operation for now
-  }
-
-  @Override
-  public void putCachedDataIds(HoodieDataCacheKey cacheKey, int... ids) {
-    // no operation for now
-  }
-
-  @Override
-  public List<Integer> getCachedDataIds(HoodieDataCacheKey cacheKey) {
-    return Collections.emptyList();
-  }
-
-  @Override
-  public List<Integer> removeCachedDataIds(HoodieDataCacheKey cacheKey) {
-    return Collections.emptyList();
-  }
-
-  @Override
-  public void cancelJob(String jobId) {
-    // no operation for now
-  }
-
-  @Override
-  public void cancelAllJobs() {
-    // no operation for now
-  }
-
-  @Override
-  public <I, O> O aggregate(HoodieData<I> data, O zeroValue, 
Functions.Function2<O, I, O> seqOp, Functions.Function2<O, O, O> combOp) {
-    return data.collectAsList().stream().reduce(zeroValue, seqOp::apply, 
combOp::apply);
-  }
-
-  @Override
-  public ReaderContextFactory<IndexedRecord> 
getReaderContextFactory(HoodieTableMetaClient metaClient) {
-    return getEngineReaderContextFactory(metaClient);
-  }
-
-  @Override
-  public ReaderContextFactory<IndexedRecord> 
getEngineReaderContextFactory(HoodieTableMetaClient metaClient) {
-    return new AvroReaderContextFactory(metaClient, new TypedProperties());
-  }
-
   @Override
   public KeyGenerator createKeyGenerator(TypedProperties props) throws 
IOException {
     throw new UnsupportedOperationException("Not yet implemented");

Reply via email to