This is an automated email from the ASF dual-hosted git repository.
zhangshenghang pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/seatunnel.git
The following commit(s) were added to refs/heads/dev by this push:
new 25ad75cd65 [Improve][Zeta] Exclude runtime metrics snapshots from IMAP
persistence (#11244)
25ad75cd65 is described below
commit 25ad75cd65cea92f936c03bb77b946099ad8732a
Author: Doyeon Kim <[email protected]>
AuthorDate: Wed Jul 8 10:27:48 2026 +0900
[Improve][Zeta] Exclude runtime metrics snapshots from IMAP persistence
(#11244)
---
docs/en/engines/zeta/hybrid-cluster-deployment.md | 5 ++
.../engines/zeta/separated-cluster-deployment.md | 5 ++
docs/zh/engines/zeta/hybrid-cluster-deployment.md | 5 ++
.../engines/zeta/separated-cluster-deployment.md | 5 ++
.../engine/server/persistence/FileMapStore.java | 54 ++++++++++++++++++++++
.../server/persistence/FileMapStoreTest.java | 21 +++++++++
6 files changed, 95 insertions(+)
diff --git a/docs/en/engines/zeta/hybrid-cluster-deployment.md
b/docs/en/engines/zeta/hybrid-cluster-deployment.md
index 1c23bbee60..16aa323c15 100644
--- a/docs/en/engines/zeta/hybrid-cluster-deployment.md
+++ b/docs/en/engines/zeta/hybrid-cluster-deployment.md
@@ -319,6 +319,11 @@ map:
fs.defaultFS: file:///
```
+Note: `engine_runningJobMetrics` stores high-frequency runtime metrics
snapshots and is
+intentionally excluded from persistent IMAP storage even when `map.engine*`
uses `map-store`. This
+avoids excessive WAL growth for observability-only state. After an engine
restart, running-job
+metrics are rebuilt from subsequent reports instead of continuing from the
pre-restart snapshot.
+
If using OSS, you can configure it as follows:
```yaml
diff --git a/docs/en/engines/zeta/separated-cluster-deployment.md
b/docs/en/engines/zeta/separated-cluster-deployment.md
index 8cf659363d..02c07441c2 100644
--- a/docs/en/engines/zeta/separated-cluster-deployment.md
+++ b/docs/en/engines/zeta/separated-cluster-deployment.md
@@ -280,6 +280,11 @@ map:
fs.defaultFS: file:///
```
+Note: `engine_runningJobMetrics` stores high-frequency runtime metrics
snapshots and is
+intentionally excluded from persistent IMAP storage even when `map.engine*`
uses `map-store`. This
+avoids excessive WAL growth for observability-only state. After an engine
restart, running-job
+metrics are rebuilt from subsequent reports instead of continuing from the
pre-restart snapshot.
+
If you use OSS, you can configure it like this:
```yaml
diff --git a/docs/zh/engines/zeta/hybrid-cluster-deployment.md
b/docs/zh/engines/zeta/hybrid-cluster-deployment.md
index 991278d985..eafa13115c 100644
--- a/docs/zh/engines/zeta/hybrid-cluster-deployment.md
+++ b/docs/zh/engines/zeta/hybrid-cluster-deployment.md
@@ -315,6 +315,11 @@ map:
fs.defaultFS: file:///
```
+说明:`engine_runningJobMetrics` 保存的是高频运行时指标快照。即使通过 `map.engine*`
+配置了 `map-store`,它也会被有意排除在持久化 IMAP 存储之外,以避免仅用于可观测性的状态导致
+WAL 持续膨胀。Engine 重启后,running-job metrics 不会延续重启前的 snapshot,而是由后续
+report 重新构建。
+
如果您使用 OSS,可以像这样配置:
```yaml
diff --git a/docs/zh/engines/zeta/separated-cluster-deployment.md
b/docs/zh/engines/zeta/separated-cluster-deployment.md
index 7ad82b0d93..b9cdfbeb66 100644
--- a/docs/zh/engines/zeta/separated-cluster-deployment.md
+++ b/docs/zh/engines/zeta/separated-cluster-deployment.md
@@ -285,6 +285,11 @@ map:
fs.defaultFS: file:///
```
+说明:`engine_runningJobMetrics` 保存的是高频运行时指标快照。即使通过 `map.engine*`
+配置了 `map-store`,它也会被有意排除在持久化 IMAP 存储之外,以避免仅用于可观测性的状态导致
+WAL 持续膨胀。Engine 重启后,running-job metrics 不会延续重启前的 snapshot,而是由后续
+report 重新构建。
+
如果您使用 OSS,可以像这样配置:
```yaml
diff --git
a/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/persistence/FileMapStore.java
b/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/persistence/FileMapStore.java
index 2900430440..6230ff80c4 100644
---
a/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/persistence/FileMapStore.java
+++
b/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/persistence/FileMapStore.java
@@ -22,6 +22,7 @@ import
org.apache.seatunnel.shade.com.google.common.collect.Maps;
import org.apache.seatunnel.engine.common.utils.FactoryUtil;
import org.apache.seatunnel.engine.imap.storage.api.IMapStorage;
import org.apache.seatunnel.engine.imap.storage.api.IMapStorageFactory;
+import
org.apache.seatunnel.engine.server.common.statestore.EngineStateStoreNames;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.map.MapLoaderLifecycleSupport;
@@ -42,6 +43,15 @@ public class FileMapStore implements MapStore<Object,
Object>, MapLoaderLifecycl
@Override
public void init(HazelcastInstance hazelcastInstance, Properties
properties, String mapName) {
+ if (EngineStateStoreNames.RUNNING_JOB_METRICS.equals(mapName)) {
+ this.mapStorage = NoOpMapStorage.INSTANCE;
+ log.info(
+ "Skip persistence for map '{}' because runtime metrics
snapshots are auxiliary "
+ + "observability state and should not write to
persistent IMAP storage.",
+ mapName);
+ return;
+ }
+
Map<String, Object> initMap = new
HashMap<>(Maps.fromProperties(properties));
String storageType = (String) initMap.get("type");
try {
@@ -107,4 +117,48 @@ public class FileMapStore implements MapStore<Object,
Object>, MapLoaderLifecycl
public Iterable<Object> loadAllKeys() {
return mapStorage.loadAllKeys();
}
+
+ private static final class NoOpMapStorage implements IMapStorage {
+ private static final NoOpMapStorage INSTANCE = new NoOpMapStorage();
+
+ @Override
+ public void initialize(Map<String, Object> properties) {
+ // no-op
+ }
+
+ @Override
+ public boolean store(Object key, Object value) {
+ return true;
+ }
+
+ @Override
+ public java.util.Set<Object> storeAll(Map<Object, Object> map) {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public boolean delete(Object key) {
+ return true;
+ }
+
+ @Override
+ public java.util.Set<Object> deleteAll(Collection<Object> keys) {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Map<Object, Object> loadAll() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public java.util.Set<Object> loadAllKeys() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public void destroy(boolean deleteAllFileFlag) {
+ // no-op
+ }
+ }
}
diff --git
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/persistence/FileMapStoreTest.java
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/persistence/FileMapStoreTest.java
index 3c6d9e1c61..a1067c4f58 100644
---
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/persistence/FileMapStoreTest.java
+++
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/persistence/FileMapStoreTest.java
@@ -18,6 +18,7 @@
package org.apache.seatunnel.engine.server.persistence;
import org.apache.seatunnel.engine.imap.storage.file.common.FileConstants;
+import
org.apache.seatunnel.engine.server.common.statestore.EngineStateStoreNames;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -28,6 +29,7 @@ import org.junit.jupiter.api.io.TempDir;
import com.hazelcast.core.HazelcastInstance;
import java.nio.file.Path;
+import java.util.Collections;
import java.util.Properties;
import static org.mockito.Mockito.mock;
@@ -101,6 +103,25 @@ public class FileMapStoreTest {
"Exception message should identify the unknown type. Got: " +
msg);
}
+ @Test
+ public void testMetricsSnapshotMapSkipsPersistentStorageInitialization() {
+ FileMapStore store = new FileMapStore();
+ Properties props = new Properties();
+ props.setProperty("type", "non-existent-storage-type");
+
+ Assertions.assertDoesNotThrow(
+ () ->
+ store.init(
+ mock(HazelcastInstance.class),
+ props,
+ EngineStateStoreNames.RUNNING_JOB_METRICS));
+ Assertions.assertEquals(Collections.emptySet(), store.loadAllKeys());
+ Assertions.assertDoesNotThrow(() -> store.store("k", "v"));
+ Assertions.assertDoesNotThrow(() -> store.delete("k"));
+
+ store.destroy();
+ }
+
private Properties buildLocalFsProperties(String namespace) {
Properties props = new Properties();
// "hdfs" is the factoryIdentifier of IMapFileStorageFactory — covers
local fs via