1818import org .elasticsearch .action .support .master .TransportMasterNodeAction ;
1919import org .elasticsearch .client .Client ;
2020import org .elasticsearch .cluster .ClusterState ;
21+ import org .elasticsearch .cluster .ClusterStateUpdateTask ;
2122import org .elasticsearch .cluster .block .ClusterBlockException ;
2223import org .elasticsearch .cluster .block .ClusterBlockLevel ;
2324import org .elasticsearch .cluster .metadata .AliasOrIndex ;
2425import org .elasticsearch .cluster .metadata .IndexMetaData ;
2526import org .elasticsearch .cluster .metadata .IndexNameExpressionResolver ;
2627import org .elasticsearch .cluster .metadata .MappingMetaData ;
28+ import org .elasticsearch .cluster .metadata .MetaData ;
2729import org .elasticsearch .cluster .node .DiscoveryNode ;
2830import org .elasticsearch .cluster .routing .IndexRoutingTable ;
2931import org .elasticsearch .cluster .service .ClusterService ;
@@ -471,12 +473,25 @@ protected ClusterBlockException checkBlock(OpenJobAction.Request request, Cluste
471473 protected void masterOperation (OpenJobAction .Request request , ClusterState state , ActionListener <OpenJobAction .Response > listener ) {
472474 OpenJobAction .JobParams jobParams = request .getJobParams ();
473475 if (licenseState .isMachineLearningAllowed ()) {
474- // Step 5. Wait for job to be started and respond
475- ActionListener <PersistentTasksCustomMetaData .PersistentTask <OpenJobAction .JobParams >> finalListener =
476+
477+ // Step 6. Clear job finished time once the job is started and respond
478+ ActionListener <OpenJobAction .Response > clearJobFinishTime = ActionListener .wrap (
479+ response -> {
480+ if (response .isAcknowledged ()) {
481+ clearJobFinishedTime (jobParams .getJobId (), listener );
482+ } else {
483+ listener .onResponse (response );
484+ }
485+ },
486+ listener ::onFailure
487+ );
488+
489+ // Step 5. Wait for job to be started
490+ ActionListener <PersistentTasksCustomMetaData .PersistentTask <OpenJobAction .JobParams >> waitForJobToStart =
476491 new ActionListener <PersistentTasksCustomMetaData .PersistentTask <OpenJobAction .JobParams >>() {
477492 @ Override
478493 public void onResponse (PersistentTasksCustomMetaData .PersistentTask <OpenJobAction .JobParams > task ) {
479- waitForJobStarted (task .getId (), jobParams , listener );
494+ waitForJobStarted (task .getId (), jobParams , clearJobFinishTime );
480495 }
481496
482497 @ Override
@@ -492,7 +507,7 @@ public void onFailure(Exception e) {
492507 // Step 4. Start job task
493508 ActionListener <PutJobAction .Response > establishedMemoryUpdateListener = ActionListener .wrap (
494509 response -> persistentTasksService .sendStartRequest (MlTasks .jobTaskId (jobParams .getJobId ()),
495- OpenJobAction .TASK_NAME , jobParams , finalListener ),
510+ OpenJobAction .TASK_NAME , jobParams , waitForJobToStart ),
496511 listener ::onFailure
497512 );
498513
@@ -574,6 +589,35 @@ public void onTimeout(TimeValue timeout) {
574589 });
575590 }
576591
592+ private void clearJobFinishedTime (String jobId , ActionListener <OpenJobAction .Response > listener ) {
593+ clusterService .submitStateUpdateTask ("clearing-job-finish-time-for-" + jobId , new ClusterStateUpdateTask () {
594+ @ Override
595+ public ClusterState execute (ClusterState currentState ) {
596+ MlMetadata mlMetadata = MlMetadata .getMlMetadata (currentState );
597+ MlMetadata .Builder mlMetadataBuilder = new MlMetadata .Builder (mlMetadata );
598+ Job .Builder jobBuilder = new Job .Builder (mlMetadata .getJobs ().get (jobId ));
599+ jobBuilder .setFinishedTime (null );
600+
601+ mlMetadataBuilder .putJob (jobBuilder .build (), true );
602+ ClusterState .Builder builder = ClusterState .builder (currentState );
603+ return builder .metaData (new MetaData .Builder (currentState .metaData ())
604+ .putCustom (MlMetadata .TYPE , mlMetadataBuilder .build ()))
605+ .build ();
606+ }
607+
608+ @ Override
609+ public void onFailure (String source , Exception e ) {
610+ logger .error ("[" + jobId + "] Failed to clear finished_time; source [" + source + "]" , e );
611+ listener .onResponse (new OpenJobAction .Response (true ));
612+ }
613+
614+ @ Override
615+ public void clusterStateProcessed (String source , ClusterState oldState ,
616+ ClusterState newState ) {
617+ listener .onResponse (new OpenJobAction .Response (true ));
618+ }
619+ });
620+ }
577621 private void cancelJobStart (PersistentTasksCustomMetaData .PersistentTask <OpenJobAction .JobParams > persistentTask , Exception exception ,
578622 ActionListener <OpenJobAction .Response > listener ) {
579623 persistentTasksService .sendRemoveRequest (persistentTask .getId (),
0 commit comments