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

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


The following commit(s) were added to refs/heads/master by this push:
     new e01bbcacd96 [FLINK-34246][runtime] Add option to only archive failed 
jobs to history server (#29015)
e01bbcacd96 is described below

commit e01bbcacd962189c726d8324a35d66cc162712e7
Author: Archit Goyal <[email protected]>
AuthorDate: Fri Sep 11 12:10:47 2026 -0700

    [FLINK-34246][runtime] Add option to only archive failed jobs to history 
server (#29015)
    
    * [FLINK-34246][runtime] Add option to only archive failed jobs to history 
server
    
    Adds jobmanager.archive.only-failed-jobs (default false) to skip archiving 
finished/canceled/suspended jobs to the history server.
    
    * Add missing positive archiving test and fix config option wording
    
    * Fix new test hanging by marking the application job status as failed
    
    * Set a failure cause on the archived execution graph for failed jobs in 
the test to avoid a hang
    
    * Regenerate the jobmanager archive only failed jobs config doc so it 
matches the option description
    
    ---------
    
    Co-authored-by: argoyal_Linkedin <[email protected]>
---
 .../generated/all_jobmanager_section.html          |  6 ++
 .../generated/job_manager_configuration.html       |  6 ++
 .../flink/configuration/JobManagerOptions.java     | 23 ++++++
 .../flink/runtime/dispatcher/Dispatcher.java       | 14 +++-
 .../dispatcher/DispatcherResourceCleanupTest.java  | 92 ++++++++++++++++++++--
 5 files changed, 135 insertions(+), 6 deletions(-)

diff --git a/docs/layouts/shortcodes/generated/all_jobmanager_section.html 
b/docs/layouts/shortcodes/generated/all_jobmanager_section.html
index 5d01a4a4885..42eb43eea22 100644
--- a/docs/layouts/shortcodes/generated/all_jobmanager_section.html
+++ b/docs/layouts/shortcodes/generated/all_jobmanager_section.html
@@ -86,6 +86,12 @@
             <td>String</td>
             <td>Directory for JobManager to store the archives of completed 
jobs.</td>
         </tr>
+        <tr>
+            <td><h5>jobmanager.archive.only-failed-jobs</h5></td>
+            <td style="word-wrap: break-word;">false</td>
+            <td>Boolean</td>
+            <td>Whether to only archive jobs that reached the <code 
class="highlighter-rouge">FAILED</code> terminal state to <code 
class="highlighter-rouge">jobmanager.archive.fs.dir</code>. When enabled, jobs 
that finished or were canceled are not archived to the history server, reducing 
the number of files written for large clusters running many short-lived batch 
jobs. This option has no effect unless <code 
class="highlighter-rouge">jobmanager.archive.fs.dir</code> is configured.</td>
+        </tr>
         <tr>
             <td><h5>jobmanager.bind-host</h5></td>
             <td style="word-wrap: break-word;">(none)</td>
diff --git a/docs/layouts/shortcodes/generated/job_manager_configuration.html 
b/docs/layouts/shortcodes/generated/job_manager_configuration.html
index 75aa1a1d9c8..1023058a36b 100644
--- a/docs/layouts/shortcodes/generated/job_manager_configuration.html
+++ b/docs/layouts/shortcodes/generated/job_manager_configuration.html
@@ -86,6 +86,12 @@
             <td>String</td>
             <td>Directory for JobManager to store the archives of completed 
jobs.</td>
         </tr>
+        <tr>
+            <td><h5>jobmanager.archive.only-failed-jobs</h5></td>
+            <td style="word-wrap: break-word;">false</td>
+            <td>Boolean</td>
+            <td>Whether to only archive jobs that reached the <code 
class="highlighter-rouge">FAILED</code> terminal state to <code 
class="highlighter-rouge">jobmanager.archive.fs.dir</code>. When enabled, jobs 
that finished or were canceled are not archived to the history server, reducing 
the number of files written for large clusters running many short-lived batch 
jobs. This option has no effect unless <code 
class="highlighter-rouge">jobmanager.archive.fs.dir</code> is configured.</td>
+        </tr>
         <tr>
             <td><h5>jobmanager.bind-host</h5></td>
             <td style="word-wrap: break-word;">(none)</td>
diff --git 
a/flink-core/src/main/java/org/apache/flink/configuration/JobManagerOptions.java
 
b/flink-core/src/main/java/org/apache/flink/configuration/JobManagerOptions.java
index a185ce22f67..847678a9e45 100644
--- 
a/flink-core/src/main/java/org/apache/flink/configuration/JobManagerOptions.java
+++ 
b/flink-core/src/main/java/org/apache/flink/configuration/JobManagerOptions.java
@@ -308,6 +308,29 @@ public class JobManagerOptions {
                     .withDescription(
                             "Directory for JobManager to store the archives of 
completed jobs.");
 
+    /**
+     * Whether only jobs that reached the {@code FAILED} terminal state should 
be archived to {@link
+     * #ARCHIVE_DIR}.
+     */
+    @Documentation.Section(Documentation.Sections.ALL_JOB_MANAGER)
+    public static final ConfigOption<Boolean> ARCHIVE_ON_FAILED_JOBS_ONLY =
+            key("jobmanager.archive.only-failed-jobs")
+                    .booleanType()
+                    .defaultValue(false)
+                    .withDescription(
+                            Description.builder()
+                                    .text(
+                                            "Whether to only archive jobs that 
reached the %s terminal state to %s. ",
+                                            code("FAILED"), 
code(ARCHIVE_DIR.key()))
+                                    .text(
+                                            "When enabled, jobs that finished 
or were canceled are not "
+                                                    + "archived to the history 
server, reducing the number of files written "
+                                                    + "for large clusters 
running many short-lived batch jobs. ")
+                                    .text(
+                                            "This option has no effect unless 
%s is configured.",
+                                            code(ARCHIVE_DIR.key()))
+                                    .build());
+
     /**
      * @deprecated Use {@link 
JobManagerOptions#COMPLETED_APPLICATION_STORE_CACHE_SIZE}
      */
diff --git 
a/flink-runtime/src/main/java/org/apache/flink/runtime/dispatcher/Dispatcher.java
 
b/flink-runtime/src/main/java/org/apache/flink/runtime/dispatcher/Dispatcher.java
index f64645b196b..c29be3274f2 100644
--- 
a/flink-runtime/src/main/java/org/apache/flink/runtime/dispatcher/Dispatcher.java
+++ 
b/flink-runtime/src/main/java/org/apache/flink/runtime/dispatcher/Dispatcher.java
@@ -33,6 +33,7 @@ import org.apache.flink.configuration.ConfigOptions;
 import org.apache.flink.configuration.Configuration;
 import org.apache.flink.configuration.DeploymentOptions;
 import org.apache.flink.configuration.HighAvailabilityOptions;
+import org.apache.flink.configuration.JobManagerOptions;
 import org.apache.flink.configuration.PipelineOptions;
 import org.apache.flink.configuration.ThreadDumpMode;
 import org.apache.flink.configuration.WebOptions;
@@ -2315,7 +2316,9 @@ public abstract class Dispatcher extends 
FencedRpcEndpoint<DispatcherId>
         // do not create an archive for suspended jobs, as this would 
eventually lead to
         // multiple archive attempts which we currently do not support
         CompletableFuture<Acknowledge> archiveFuture =
-                archiveExecutionGraphToHistoryServer(executionGraphInfo);
+                shouldArchiveToHistoryServer(terminalJobStatus)
+                        ? 
archiveExecutionGraphToHistoryServer(executionGraphInfo)
+                        : CompletableFuture.completedFuture(Acknowledge.get());
 
         return archiveFuture.thenCompose(
                 ignored -> 
registerGloballyTerminatedJobInJobResultStore(executionGraphInfo));
@@ -2413,6 +2416,15 @@ public abstract class Dispatcher extends 
FencedRpcEndpoint<DispatcherId>
         partialExecutionGraphInfoStore.put(executionGraphInfo.getJobId(), 
executionGraphInfo);
     }
 
+    /**
+     * Checks whether a job that reached the given globally terminal state 
should be archived to the
+     * history server, honoring {@link 
JobManagerOptions#ARCHIVE_ON_FAILED_JOBS_ONLY}.
+     */
+    private boolean shouldArchiveToHistoryServer(JobStatus terminalJobStatus) {
+        return terminalJobStatus == JobStatus.FAILED
+                || 
!configuration.get(JobManagerOptions.ARCHIVE_ON_FAILED_JOBS_ONLY);
+    }
+
     private CompletableFuture<Acknowledge> 
archiveExecutionGraphToHistoryServer(
             ExecutionGraphInfo executionGraphInfo) {
 
diff --git 
a/flink-runtime/src/test/java/org/apache/flink/runtime/dispatcher/DispatcherResourceCleanupTest.java
 
b/flink-runtime/src/test/java/org/apache/flink/runtime/dispatcher/DispatcherResourceCleanupTest.java
index 1d9b3e87475..ee6d146f560 100644
--- 
a/flink-runtime/src/test/java/org/apache/flink/runtime/dispatcher/DispatcherResourceCleanupTest.java
+++ 
b/flink-runtime/src/test/java/org/apache/flink/runtime/dispatcher/DispatcherResourceCleanupTest.java
@@ -22,6 +22,7 @@ import org.apache.flink.api.common.ApplicationID;
 import org.apache.flink.api.common.JobID;
 import org.apache.flink.api.common.JobStatus;
 import org.apache.flink.configuration.Configuration;
+import org.apache.flink.configuration.JobManagerOptions;
 import org.apache.flink.core.failure.FailureEnricher;
 import org.apache.flink.core.testutils.OneShotLatch;
 import org.apache.flink.runtime.application.SingleJobApplication;
@@ -32,6 +33,7 @@ import 
org.apache.flink.runtime.client.DuplicateJobSubmissionException;
 import org.apache.flink.runtime.client.JobSubmissionException;
 import 
org.apache.flink.runtime.dispatcher.cleanup.TestingResourceCleanerFactory;
 import org.apache.flink.runtime.executiongraph.ArchivedExecutionGraph;
+import org.apache.flink.runtime.executiongraph.ErrorInfo;
 import org.apache.flink.runtime.executiongraph.JobStatusListener;
 import org.apache.flink.runtime.heartbeat.HeartbeatServices;
 import org.apache.flink.runtime.highavailability.HighAvailabilityServices;
@@ -93,6 +95,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 /** Tests the resource cleanup by the {@link Dispatcher}. */
@@ -494,18 +497,31 @@ public class DispatcherResourceCleanupTest extends 
TestLogger {
         terminateJobWithState(takeCreatedJobManagerRunner, 
JobStatus.SUSPENDED);
     }
 
+    private void failJobAndApplication(TestingJobManagerRunner 
takeCreatedJobManagerRunner) {
+        terminateJobWithState(takeCreatedJobManagerRunner, JobStatus.FAILED);
+        application.jobStatusChanges(
+                takeCreatedJobManagerRunner.getJobID(),
+                JobStatus.FAILED,
+                System.currentTimeMillis());
+    }
+
     private void cancelJob(TestingJobManagerRunner 
takeCreatedJobManagerRunner) {
         terminateJobWithState(takeCreatedJobManagerRunner, JobStatus.CANCELED);
     }
 
     private void terminateJobWithState(
             TestingJobManagerRunner takeCreatedJobManagerRunner, JobStatus 
state) {
+        final ArchivedExecutionGraphBuilder archivedExecutionGraphBuilder =
+                new 
ArchivedExecutionGraphBuilder().setJobID(jobId).setState(state);
+
+        if (state == JobStatus.FAILED) {
+            archivedExecutionGraphBuilder.setFailureCause(
+                    new ErrorInfo(
+                            new FlinkException("Test job failure"), 
System.currentTimeMillis()));
+        }
+
         takeCreatedJobManagerRunner.completeResultFuture(
-                new ExecutionGraphInfo(
-                        new ArchivedExecutionGraphBuilder()
-                                .setJobID(jobId)
-                                .setState(state)
-                                .build()));
+                new ExecutionGraphInfo(archivedExecutionGraphBuilder.build()));
     }
 
     private void assertThatNoCleanupWasTriggered() {
@@ -736,6 +752,72 @@ public class DispatcherResourceCleanupTest extends 
TestLogger {
         assertFalse(isArchived.get());
     }
 
+    @Test
+    public void 
testNotArchivingFinishedJobToHistoryServerWhenOnlyFailedJobsConfigured()
+            throws Exception {
+
+        final AtomicBoolean isArchived = new AtomicBoolean(false);
+
+        final Configuration configuration = new Configuration();
+        configuration.set(JobManagerOptions.ARCHIVE_ON_FAILED_JOBS_ONLY, true);
+
+        final TestingDispatcher.Builder testingDispatcherBuilder =
+                createTestingDispatcherBuilder()
+                        .setConfiguration(configuration)
+                        .setHistoryServerArchivist(
+                                TestingHistoryServerArchivist.builder()
+                                        .setArchiveExecutionGraphFunction(
+                                                (executionGraphInfo, 
applicationId) -> {
+                                                    isArchived.set(true);
+                                                    return 
CompletableFuture.completedFuture(
+                                                            Acknowledge.get());
+                                                })
+                                        .build());
+
+        final TestingJobManagerRunnerFactory jobManagerRunnerFactory =
+                startDispatcherAndSubmitApplication(testingDispatcherBuilder, 
0);
+
+        
finishJobAndApplication(jobManagerRunnerFactory.takeCreatedJobManagerRunner());
+
+        assertGlobalCleanupTriggered(jobId);
+        dispatcher.getJobTerminationFuture(jobId, Duration.ofHours(1)).join();
+
+        assertFalse(isArchived.get());
+    }
+
+    @Test
+    public void 
testArchivingFailedJobToHistoryServerWhenOnlyFailedJobsConfigured()
+            throws Exception {
+
+        final AtomicBoolean isArchived = new AtomicBoolean(false);
+
+        final Configuration configuration = new Configuration();
+        configuration.set(JobManagerOptions.ARCHIVE_ON_FAILED_JOBS_ONLY, true);
+
+        final TestingDispatcher.Builder testingDispatcherBuilder =
+                createTestingDispatcherBuilder()
+                        .setConfiguration(configuration)
+                        .setHistoryServerArchivist(
+                                TestingHistoryServerArchivist.builder()
+                                        .setArchiveExecutionGraphFunction(
+                                                (executionGraphInfo, 
applicationId) -> {
+                                                    isArchived.set(true);
+                                                    return 
CompletableFuture.completedFuture(
+                                                            Acknowledge.get());
+                                                })
+                                        .build());
+
+        final TestingJobManagerRunnerFactory jobManagerRunnerFactory =
+                startDispatcherAndSubmitApplication(testingDispatcherBuilder, 
0);
+
+        
failJobAndApplication(jobManagerRunnerFactory.takeCreatedJobManagerRunner());
+
+        assertGlobalCleanupTriggered(jobId);
+        dispatcher.getJobTerminationFuture(jobId, Duration.ofHours(1)).join();
+
+        assertTrue(isArchived.get());
+    }
+
     private static final class BlockingJobManagerRunnerFactory
             extends TestingJobMasterServiceLeadershipRunnerFactory {
 

Reply via email to