1010import org .elasticsearch .action .support .master .AcknowledgedResponse ;
1111import org .elasticsearch .action .support .master .TransportMasterNodeAction ;
1212import org .elasticsearch .cluster .ClusterState ;
13+ import org .elasticsearch .cluster .ClusterStateUpdateTask ;
1314import org .elasticsearch .cluster .block .ClusterBlockException ;
1415import org .elasticsearch .cluster .block .ClusterBlockLevel ;
1516import org .elasticsearch .cluster .metadata .IndexNameExpressionResolver ;
17+ import org .elasticsearch .cluster .metadata .MetaData ;
1618import org .elasticsearch .cluster .service .ClusterService ;
1719import org .elasticsearch .common .inject .Inject ;
1820import org .elasticsearch .common .settings .Settings ;
1921import org .elasticsearch .threadpool .ThreadPool ;
2022import org .elasticsearch .transport .TransportService ;
23+ import org .elasticsearch .xpack .core .XPackPlugin ;
24+ import org .elasticsearch .xpack .core .ml .MlMetadata ;
2125import org .elasticsearch .xpack .core .ml .action .FinalizeJobExecutionAction ;
26+ import org .elasticsearch .xpack .core .ml .job .config .Job ;
2227
28+ import java .util .Arrays ;
29+ import java .util .Date ;
30+ import java .util .List ;
31+ import java .util .stream .Collectors ;
32+
33+ // This action is only called from modes before version 6.6.0
2334public class TransportFinalizeJobExecutionAction extends TransportMasterNodeAction <FinalizeJobExecutionAction .Request ,
2435 AcknowledgedResponse > {
2536
@@ -45,9 +56,55 @@ protected AcknowledgedResponse newResponse() {
4556 @ Override
4657 protected void masterOperation (FinalizeJobExecutionAction .Request request , ClusterState state ,
4758 ActionListener <AcknowledgedResponse > listener ) {
48- // This action is no longer required but needs to be preserved
49- // in case it is called by an old node in a mixed cluster
50- listener .onResponse (new AcknowledgedResponse (true ));
59+
60+ MlMetadata mlMetadata = MlMetadata .getMlMetadata (state );
61+ List <String > jobsInClusterState = Arrays .stream (request .getJobIds ())
62+ .filter (id -> mlMetadata .getJobs ().containsKey (id ))
63+ .collect (Collectors .toList ());
64+
65+ // This action should not be called for jobs that have
66+ // their configuration in index documents
67+
68+ if (jobsInClusterState .isEmpty ()) {
69+ // This action is a no-op for jobs not defined in the cluster state.
70+ listener .onResponse (new AcknowledgedResponse (true ));
71+ return ;
72+ }
73+
74+ String jobIdString = String .join ("," , jobsInClusterState );
75+ String source = "finalize_job_execution [" + jobIdString + "]" ;
76+ logger .debug ("finalizing jobs [{}]" , jobIdString );
77+ clusterService .submitStateUpdateTask (source , new ClusterStateUpdateTask () {
78+ @ Override
79+ public ClusterState execute (ClusterState currentState ) {
80+ XPackPlugin .checkReadyForXPackCustomMetadata (currentState );
81+ MlMetadata mlMetadata = MlMetadata .getMlMetadata (currentState );
82+ MlMetadata .Builder mlMetadataBuilder = new MlMetadata .Builder (mlMetadata );
83+ Date finishedTime = new Date ();
84+
85+ for (String jobId : jobsInClusterState ) {
86+ Job .Builder jobBuilder = new Job .Builder (mlMetadata .getJobs ().get (jobId ));
87+ jobBuilder .setFinishedTime (finishedTime );
88+ mlMetadataBuilder .putJob (jobBuilder .build (), true );
89+ }
90+ ClusterState .Builder builder = ClusterState .builder (currentState );
91+ return builder .metaData (new MetaData .Builder (currentState .metaData ())
92+ .putCustom (MlMetadata .TYPE , mlMetadataBuilder .build ()))
93+ .build ();
94+ }
95+
96+ @ Override
97+ public void onFailure (String source , Exception e ) {
98+ listener .onFailure (e );
99+ }
100+
101+ @ Override
102+ public void clusterStateProcessed (String source , ClusterState oldState ,
103+ ClusterState newState ) {
104+ logger .debug ("finalized job [{}]" , jobIdString );
105+ listener .onResponse (new AcknowledgedResponse (true ));
106+ }
107+ });
51108 }
52109
53110 @ Override
0 commit comments