All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.linkis.entrance.execute.EntranceExecutor.scala Maven / Gradle / Ivy

There is a newer version: 1.6.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.linkis.entrance.execute

import org.apache.commons.io.IOUtils
import org.apache.commons.lang.exception.ExceptionUtils
import org.apache.linkis.common.log.LogUtils
import org.apache.linkis.common.utils.{Logging, Utils}
import org.apache.linkis.entrance.job.EntranceExecuteRequest
import org.apache.linkis.governance.common.entity.ExecutionNodeStatus._
import org.apache.linkis.governance.common.protocol.task.{RequestTask, ResponseTaskStatus}
import org.apache.linkis.orchestrator.computation.operation.log.LogProcessor
import org.apache.linkis.orchestrator.computation.operation.progress.ProgressProcessor
import org.apache.linkis.orchestrator.computation.operation.resource.ResourceReportProcessor
import org.apache.linkis.orchestrator.core.OrchestrationFuture
import org.apache.linkis.protocol.UserWithCreator
import org.apache.linkis.scheduler.executer.ExecutorState.ExecutorState
import org.apache.linkis.scheduler.executer._


abstract class EntranceExecutor(val id: Long, val mark: MarkReq) extends Executor with Logging {

  private implicit var userWithCreator: UserWithCreator = _

  private var engineReturn: EngineExecuteAsyncReturn = _

  protected var interceptors: Array[ExecuteRequestInterceptor] = Array(LabelExecuteRequestInterceptor, JobExecuteRequestInterceptor)

  def setInterceptors(interceptors: Array[ExecuteRequestInterceptor]): Unit = if (interceptors != null && interceptors.nonEmpty) {
    this.interceptors = interceptors
  }

  def setUser(user: String): Unit = userWithCreator = if (userWithCreator != null) UserWithCreator(user, userWithCreator.creator)
  else UserWithCreator(user, null)

  def getUser: String = if (userWithCreator != null) userWithCreator.user else null

  def setCreator(creator: String): Unit = userWithCreator = if (userWithCreator != null) UserWithCreator(userWithCreator.user, creator)
  else UserWithCreator(null, creator)

  def getCreator: String = if (userWithCreator != null) userWithCreator.creator else null


  def getEngineExecuteAsyncReturn: Option[EngineExecuteAsyncReturn] = {
    Option(engineReturn)
  }

  def setEngineReturn(engineExecuteAsyncReturn: EngineExecuteAsyncReturn): Unit = {
    this.engineReturn = engineExecuteAsyncReturn
  }

  override def execute(executeRequest: ExecuteRequest): ExecuteResponse = {
    var request: RequestTask = null
    interceptors.foreach(in => request = in.apply(request, executeRequest))
    callExecute(executeRequest)
  }

  protected def callback(): Unit = {}

  protected def callExecute(request: ExecuteRequest): ExecuteResponse

  //  override def toString: String = s"${getInstance.getApplicationName}Engine($getId, $getUser, $getCreator, ${getInstance.getInstance})"
  override def toString: String = "${getId}"

  override def getId: Long = this.id

  override def state: ExecutorState = ExecutorState.Idle

  override def getExecutorInfo: ExecutorInfo = {
    null
  }

  def canEqual(other: Any): Boolean = other.isInstanceOf[EntranceExecutor]

  override def equals(other: Any): Boolean = other match {
    case that: EntranceExecutor =>
      (that canEqual this) && that.getId == this.getId
    case _ => false
  }

  def getExecId(jobId: String): String = {
    if (null != engineReturn && engineReturn.getJobId.contains(jobId)) {
      jobId
    } else {
      null
    }
  }


  override def hashCode(): Int = {
    //    getOrchestratorSession().hashCode()
    // todo
    super.hashCode()
  }

  def getRunningOrchestrationFuture: Option[OrchestrationFuture] = {
    if (null != engineReturn) {
      engineReturn.getOrchestrationFuture()
    } else {
      None
    }
  }

}

class EngineExecuteAsyncReturn(val request: ExecuteRequest,
                               callback: EngineExecuteAsyncReturn => Unit) extends AsynReturnExecuteResponse with Logging {

  private var notifyJob: ExecuteResponse => Unit = _

  private var error: Throwable = _

  private var errorMsg: String = _

  private var lastNotifyTime = System.currentTimeMillis

  private var orchestrationFuture: OrchestrationFuture = _

  private var logProcessor: LogProcessor = _

  private var progressProcessor: ProgressProcessor = _

  private var resourceReportProcessor : ResourceReportProcessor = _

  private var subJobId: String = _

  def getLastNotifyTime: Long = lastNotifyTime

  def setOrchestrationObjects(orchestrationFuture: OrchestrationFuture, logProcessor: LogProcessor, progressProcessor: ProgressProcessor): Unit = {
    this.orchestrationFuture = orchestrationFuture
    this.logProcessor = logProcessor
    this.progressProcessor = progressProcessor
  }

  def getOrchestrationFuture(): Option[OrchestrationFuture] = {
    Option(orchestrationFuture)
  }

  def getLogProcessor(): Option[LogProcessor] = {
    Option(logProcessor)
  }

  def getProgressProcessor(): Option[ProgressProcessor] = {
    Option(progressProcessor)
  }

  def closeOrchestration(): Unit = {
    getLogProcessor().foreach(IOUtils.closeQuietly(_))
    getProgressProcessor().foreach(IOUtils.closeQuietly(_))
  }

  def setSubJobId(subJobId: String): Unit = {
    this.subJobId = subJobId
  }

  private[execute] def notifyStatus(responseEngineStatus: ResponseTaskStatus): Unit = {
    lastNotifyTime = System.currentTimeMillis()
    val response = responseEngineStatus.status match {
      case Succeed => Some(SuccessExecuteResponse())
      case Failed | Cancelled | Timeout => Some(ErrorExecuteResponse(errorMsg, error))
      case _ => None
    }
    response.foreach { r =>
      getJobId.foreach(id => {
        request match {
          case entranceExecuteRequest: EntranceExecuteRequest =>
            r match {
              case ErrorExecuteResponse(errorMsg, error) =>
                val msg = s"Job with execId-$id + subJobId : $subJobId  execute failed,$errorMsg \n ${ExceptionUtils.getFullStackTrace(error)}"
                entranceExecuteRequest.getJob.getLogListener.foreach(_.onLogUpdate(entranceExecuteRequest.getJob, LogUtils.generateERROR(msg)))
              case _ =>
            }
          case _ =>
        }
      })
      Utils.tryAndWarn {
        if (null != callback) {
          callback(this)
        }
        if (notifyJob == null) this synchronized (while (notifyJob == null) this.wait(1000))
        notifyJob(r)
      }
      closeOrchestration()
    }
  }

  private[execute] def notifyHeartbeat(): Unit = {
    lastNotifyTime = System.currentTimeMillis()
  }

  private[execute] def notifyError(errorMsg: String): Unit = {
    lastNotifyTime = System.currentTimeMillis()
    this.errorMsg = errorMsg
  }

  private[execute] def notifyError(errorMsg: String, t: Throwable): Unit = {
    lastNotifyTime = System.currentTimeMillis()
    this.errorMsg = errorMsg
    this.error = t
  }

  private[execute] def getJobId: Option[String] = {
    //    val jobId = request.getProperties.get(JobExecuteRequestInterceptor.PROPERTY_JOB_ID)
    val jobId = request match {
      case entranceExecutorRequest: EntranceExecuteRequest =>
        entranceExecutorRequest.getJob.getId
      case _ =>
        null
    }
    jobId match {
      case j: String => Option(j)
      case _ => None
    }
  }

  override def notify(rs: ExecuteResponse => Unit): Unit = {
    notifyJob = rs
    //    this synchronized notify()
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy