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

wenjin272 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/flink-agents.git


The following commit(s) were added to refs/heads/main by this push:
     new a0f8351c [runtime] Count restored input runs once when tasks identify 
them first (#1245)
a0f8351c is described below

commit a0f8351c4b6164392e0254169aef7025ca304025
Author: Sangkyoon Nam <[email protected]>
AuthorDate: Fri Oct 16 13:05:54 2026 +0900

    [runtime] Count restored input runs once when tasks identify them first 
(#1245)
    
    Generated-by: Claude Code 2.1.296 (Claude Opus 5.5)
---
 .../runtime/metrics/BuiltInInputRunMetrics.java    |  4 +-
 .../TaskLifecycleListenerNotificationTest.java     | 47 ++++++++++++++++++++++
 .../metrics/BuiltInInputRunMetricsTest.java        | 17 ++++++++
 3 files changed, 67 insertions(+), 1 deletion(-)

diff --git 
a/runtime/src/main/java/org/apache/flink/agents/runtime/metrics/BuiltInInputRunMetrics.java
 
b/runtime/src/main/java/org/apache/flink/agents/runtime/metrics/BuiltInInputRunMetrics.java
index 390bf3bc..9c4480e7 100644
--- 
a/runtime/src/main/java/org/apache/flink/agents/runtime/metrics/BuiltInInputRunMetrics.java
+++ 
b/runtime/src/main/java/org/apache/flink/agents/runtime/metrics/BuiltInInputRunMetrics.java
@@ -129,7 +129,9 @@ final class BuiltInInputRunMetrics {
     }
 
     void restoreActiveInputRuns(long count) {
-        unidentifiedRestoredActiveRuns = Math.max(0L, count);
+        // The operator identifies runs from restored action tasks before it 
knows the count, so
+        // the already identified runs are part of count rather than in 
addition to it.
+        unidentifiedRestoredActiveRuns = Math.max(0L, count - 
activeInputRunIds.size());
         activeInputRuns.set(unidentifiedRestoredActiveRuns + 
activeInputRunIds.size());
     }
 
diff --git 
a/runtime/src/test/java/org/apache/flink/agents/runtime/lifecycle/TaskLifecycleListenerNotificationTest.java
 
b/runtime/src/test/java/org/apache/flink/agents/runtime/lifecycle/TaskLifecycleListenerNotificationTest.java
index d2baee41..1693af27 100644
--- 
a/runtime/src/test/java/org/apache/flink/agents/runtime/lifecycle/TaskLifecycleListenerNotificationTest.java
+++ 
b/runtime/src/test/java/org/apache/flink/agents/runtime/lifecycle/TaskLifecycleListenerNotificationTest.java
@@ -32,6 +32,7 @@ import 
org.apache.flink.agents.runtime.actionstate.ActionState;
 import org.apache.flink.agents.runtime.actionstate.ActionStateStore;
 import org.apache.flink.agents.runtime.actionstate.InMemoryActionStateStore;
 import org.apache.flink.agents.runtime.async.ContinuationActionExecutor;
+import org.apache.flink.agents.runtime.metrics.FlinkAgentsMetricGroupImpl;
 import org.apache.flink.agents.runtime.operator.ActionExecutionOperator;
 import org.apache.flink.agents.runtime.operator.ActionExecutionOperatorFactory;
 import org.apache.flink.agents.runtime.operator.ActionTask;
@@ -45,6 +46,7 @@ import 
org.apache.flink.streaming.util.KeyedOneInputStreamOperatorTestHarness;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
+import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
@@ -415,6 +417,51 @@ public class TaskLifecycleListenerNotificationTest {
         }
     }
 
+    @Test
+    void resumedInFlightRecordCountsAsOneActiveInputRun() throws Exception {
+        AgentConfiguration serialConfig = new AgentConfiguration();
+        serialConfig.set(AgentExecutionOptions.PARALLEL_EXECUTION_ENABLED, 
false);
+        AgentPlan plan = new AgentPlan(new SyncAgent(), serialConfig);
+        OperatorSubtaskState snapshot;
+
+        try (KeyedOneInputStreamOperatorTestHarness<Long, Long, Object> 
testHarness =
+                new KeyedOneInputStreamOperatorTestHarness<>(
+                        new ActionExecutionOperatorFactory<>(plan, true),
+                        (KeySelector<Long, Long>) value -> value,
+                        TypeInformation.of(Long.class))) {
+            testHarness.open();
+            testHarness.processElement(new StreamRecord<>(7L));
+            snapshot = testHarness.snapshot(1L, 1L);
+        }
+
+        try (KeyedOneInputStreamOperatorTestHarness<Long, Long, Object> 
testHarness =
+                new KeyedOneInputStreamOperatorTestHarness<>(
+                        new ActionExecutionOperatorFactory<>(plan, true),
+                        (KeySelector<Long, Long>) value -> value,
+                        TypeInformation.of(Long.class))) {
+            testHarness.initializeState(snapshot);
+            testHarness.open();
+            ActionExecutionOperator<Long, Object> operator =
+                    (ActionExecutionOperator<Long, Object>) 
testHarness.getOperator();
+            Field metricGroupField = 
ActionExecutionOperator.class.getDeclaredField("metricGroup");
+            metricGroupField.setAccessible(true);
+            FlinkAgentsMetricGroupImpl metricGroup =
+                    (FlinkAgentsMetricGroupImpl) 
metricGroupField.get(operator);
+
+            assertThat(
+                            ((Number) 
metricGroup.getGauge("numOfActiveInputRuns").getValue())
+                                    .longValue())
+                    .isEqualTo(1L);
+
+            operator.waitInFlightEventsFinished();
+
+            assertThat(
+                            ((Number) 
metricGroup.getGauge("numOfActiveInputRuns").getValue())
+                                    .longValue())
+                    .isZero();
+        }
+    }
+
     @Test
     void recordWithoutTriggeredActionsEmitsNoLifecycleEvents() throws 
Exception {
         AgentPlan plan = new AgentPlan(new EmptyAgent());
diff --git 
a/runtime/src/test/java/org/apache/flink/agents/runtime/metrics/BuiltInInputRunMetricsTest.java
 
b/runtime/src/test/java/org/apache/flink/agents/runtime/metrics/BuiltInInputRunMetricsTest.java
index fb38c894..3d0b306c 100644
--- 
a/runtime/src/test/java/org/apache/flink/agents/runtime/metrics/BuiltInInputRunMetricsTest.java
+++ 
b/runtime/src/test/java/org/apache/flink/agents/runtime/metrics/BuiltInInputRunMetricsTest.java
@@ -103,6 +103,23 @@ class BuiltInInputRunMetricsTest {
         
assertThat(gauge(BuiltInInputRunMetrics.NUM_ACTIVE_INPUT_RUNS)).isZero();
     }
 
+    @Test
+    void restoredRunIdentifiedBeforeCountIsNotCountedTwice() {
+        setTimeMillis(300L);
+        ExecutionTraceContext inputRun = 
ExecutionTraceContext.forInputRun("key", "agent");
+
+        // The operator restores action tasks, identifying their runs, before 
it counts the
+        // restored processing keys.
+        metrics.identifyRestoredActiveInputRun(inputRun.getInputRunId());
+        metrics.restoreActiveInputRuns(1L);
+        
assertThat(gauge(BuiltInInputRunMetrics.NUM_ACTIVE_INPUT_RUNS)).isEqualTo(1L);
+
+        setTimeMillis(375L);
+        metrics.inputRunCompleted(inputRun.getInputRunId());
+
+        
assertThat(gauge(BuiltInInputRunMetrics.NUM_ACTIVE_INPUT_RUNS)).isZero();
+    }
+
     @Test
     void 
restoredPendingInputRecordsLocallyObservedOutcomeAndProcessingLatency() {
         Event inputEvent = new InputEvent("restored-pending");

Reply via email to