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

org.apache.linkis.entrance.EntranceServer.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

import org.apache.linkis.common.exception.{ErrorException, LinkisException, LinkisRuntimeException}
import org.apache.linkis.common.utils.{Logging, Utils}
import org.apache.linkis.entrance.exception.{EntranceErrorException, SubmitFailedException}
import org.apache.linkis.entrance.execute.{EntranceExecutorManager, EntranceJob}
import org.apache.linkis.entrance.log.LogReader
import org.apache.linkis.entrance.timeout.JobTimeoutManager
import org.apache.linkis.governance.common.entity.job.JobRequest
import org.apache.linkis.rpc.Sender
import org.apache.linkis.scheduler.queue.{Job, SchedulerEventState}
import org.apache.linkis.server.conf.ServerConfiguration
import org.apache.commons.lang.exception.ExceptionUtils


abstract class EntranceServer extends Logging {

  private var entranceWebSocketService: Option[EntranceWebSocketService] = None

  private val jobTimeoutManager: JobTimeoutManager = new JobTimeoutManager()

  def init(): Unit

  def getName: String

  def getEntranceContext: EntranceContext


  /**
    * Execute a task and return an execId(执行一个task,返回一个execId)
    * @param params
    * @return
    */
  def execute(params: java.util.Map[String, Any]): String = {
    if (!params.containsKey(EntranceServer.DO_NOT_PRINT_PARAMS_LOG)) debug("received a request: " + params)
    else params.remove(EntranceServer.DO_NOT_PRINT_PARAMS_LOG)
    var jobRequest = getEntranceContext.getOrCreateEntranceParser().parseToTask(params)
    // tod multi entrance instances
    jobRequest.setInstances(Sender.getThisInstance)

    //After parse the map into a jobRequest, we need to store it in the database, and the jobRequest can get a unique taskID.
    //将map parse 成 jobRequest 之后,我们需要将它存储到数据库中,task可以获得唯一的taskID
    getEntranceContext.getOrCreatePersistenceManager().createPersistenceEngine().persist(jobRequest)
    if (null == jobRequest.getId || jobRequest.getId <= 0) {
      throw new EntranceErrorException(20052, "Persist jobRequest error, please submit again later(存储Job异常,请稍后重新提交任务)")
    }
    info(s"received a request,convert $jobRequest ")

    val logAppender = new java.lang.StringBuilder()
    Utils.tryThrow(getEntranceContext.getOrCreateEntranceInterceptors().foreach(int => jobRequest = int.apply(jobRequest, logAppender))) { t =>
      val error = t match {
        case error: ErrorException => error
        case t1:Throwable => val exception = new EntranceErrorException(20039, "failed to analysis task ! the reason is :"+ExceptionUtils.getRootCauseMessage(t)+"(解析task失败!原因:" + ExceptionUtils.getRootCauseMessage(t))
          exception.initCause(t1)
          exception
        case _ => new EntranceErrorException(20039, "failed to analysis task ! the reason is :"+ExceptionUtils.getRootCauseMessage(t)+"(解析task失败!原因:" + ExceptionUtils.getRootCauseMessage(t))
      }
      jobRequest match {
        case t: JobRequest =>
          t.setErrorCode(error.getErrCode)
          t.setErrorDesc(error.getDesc)
          t.setStatus(SchedulerEventState.Failed.toString)
          t.setProgress(EntranceJob.JOB_COMPLETED_PROGRESS.toString)
        case _ =>
      }
      getEntranceContext.getOrCreatePersistenceManager().createPersistenceEngine().updateIfNeeded(jobRequest)
      error
    }

    val job = getEntranceContext.getOrCreateEntranceParser().parseToJob(jobRequest)
    Utils.tryThrow{
      job.init()
      job.setLogListener(getEntranceContext.getOrCreateLogManager())
      job.setProgressListener(getEntranceContext.getOrCreatePersistenceManager())
      job.setJobListener(getEntranceContext.getOrCreatePersistenceManager())
      job match {
        case entranceJob: EntranceJob => {
          entranceJob.setEntranceListenerBus(getEntranceContext.getOrCreateEventListenerBus)
        }
        case _ =>
      }
      Utils.tryCatch{
        if (logAppender.length() > 0) job.getLogListener.foreach(_.onLogUpdate(job, logAppender.toString.trim))
      }{
        t => logger.error("Failed to write init log, reason: ", t)
      }

      /**
       * job.afterStateChanged() method is only called in job.run(), and job.run() is called only after job is scheduled
       * so it suggest that we lack a hook for job init, currently we call this to trigger JobListener.onJobinit()
       * */
      Utils.tryAndWarn(job.getJobListener.foreach(_.onJobInited(job)))
      getEntranceContext.getOrCreateScheduler().submit(job)
      val msg = s"Job with jobId : ${jobRequest.getId} and execID : ${job.getId()} submitted "
      logger.info(msg)

      job match {
        case entranceJob: EntranceJob =>
          entranceJob.getJobRequest.setReqId(job.getId())
          if(jobTimeoutManager.timeoutCheck && JobTimeoutManager.hasTimeoutLabel(entranceJob)) jobTimeoutManager.add(job.getId(), entranceJob)
          entranceJob.getLogListener.foreach(_.onLogUpdate(entranceJob, msg))
        case _ =>
      }

      job.getId()
    }{t =>
      job.onFailure("Submitting the query failed!(提交查询失败!)", t)
      val _jobRequest: JobRequest = getEntranceContext.getOrCreateEntranceParser().parseToJobRequest(job)
      getEntranceContext.getOrCreatePersistenceManager().createPersistenceEngine().updateIfNeeded(_jobRequest)
      t match {
        case e: LinkisException => e
        case e: LinkisRuntimeException => e
        case t: Throwable =>
          new SubmitFailedException(30009, "Submitting the query failed!(提交查询失败!)" + ExceptionUtils.getRootCauseMessage(t), t)
      }
    }


  }

//  def killJobFromJobHistory(jobId: String): String = {
//    val rpcSender = Sender.getSender(EntranceConfiguration.QUERY_PERSISTENCE_SPRING_APPLICATION_NAME.getValue)
//    val jobQueryRequest = new JobRequest
//    jobQueryRequest.setId(java.lang.Long.parseLong(jobId))
//    jobQueryRequest.setStatus(SchedulerEventState.Cancelled.toString)
//    val response = rpcSender.ask(JobReqUpdate(jobQueryRequest)).asInstanceOf[JobRespProtocol]
//    response.getStatus match {
//      case 0 => "success"
//      case _ => response.getMsg
//    }
//  }


  def logReader(execId: String): LogReader

  def getJob(execId: String): Option[Job] = getEntranceContext.getOrCreateScheduler().get(execId).map(_.asInstanceOf[Job])

  private[entrance] def getEntranceWebSocketService: Option[EntranceWebSocketService] = if (ServerConfiguration.BDP_SERVER_SOCKET_MODE.getValue) {
    if (entranceWebSocketService.isEmpty) synchronized {
      if (entranceWebSocketService.isEmpty) {
        entranceWebSocketService = Some(new EntranceWebSocketService)
        entranceWebSocketService.foreach(_.setEntranceServer(this))
        entranceWebSocketService.foreach(getEntranceContext.getOrCreateEventListenerBus.addListener)
      }
    }
    entranceWebSocketService
  } else None

}
object EntranceServer {
  val DO_NOT_PRINT_PARAMS_LOG = "doNotPrintParamsLog"
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy