Package com.google.code.lightssh.project.scheduler.service

Source Code of com.google.code.lightssh.project.scheduler.service.PlanManagerImpl

package com.google.code.lightssh.project.scheduler.service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.google.code.lightssh.common.ApplicationException;
import com.google.code.lightssh.common.dao.SearchCondition;
import com.google.code.lightssh.common.model.Result;
import com.google.code.lightssh.common.model.page.ListPage;
import com.google.code.lightssh.common.service.BaseManagerImpl;
import com.google.code.lightssh.common.util.TextFormater;
import com.google.code.lightssh.project.scheduler.dao.PlanDao;
import com.google.code.lightssh.project.scheduler.dao.PlanDetailDao;
import com.google.code.lightssh.project.scheduler.entity.Plan;
import com.google.code.lightssh.project.scheduler.entity.PlanDetail;
import com.google.code.lightssh.project.scheduler.entity.SchedulerType;
import com.google.code.lightssh.project.scheduler.entity.PlanDetail.Status;
import com.google.code.lightssh.project.sequence.service.SequenceManager;

/**
* 执行计划业务实现
* @author YangXiaojin
*
*/
@Component("planManager")
public class PlanManagerImpl extends BaseManagerImpl<Plan> implements PlanManager{

  private static final long serialVersionUID = -6376825556178324639L;
 
  private static Logger log = LoggerFactory.getLogger( PlanManagerImpl.class );
 
  @Resource(name="planDetailDao")
  private PlanDetailDao planDetailDao;
 
  @Resource(name="sequenceManager")
  private SequenceManager sequenceManager;
 
  @Resource(name="jobQueueManager")
  private JobQueueManager jobQueueManager;
 
  @Resource(name="planDao")
  public void setDao(PlanDao dao ){
    this.dao = dao;
  }
 
  public PlanDao getDao(){
    return (PlanDao)this.dao;
  }
 
  public ListPage<Plan> list(ListPage<Plan> page,Plan t ){
    SearchCondition sc = new SearchCondition();
    if( t != null ){
      if( !StringUtils.isEmpty(t.getId()) )
        sc.like( "id",t.getId() );
     
      if( t.get_pftPeriod() != null ){
        Calendar cal = Calendar.getInstance();
        Date start = t.get_pftPeriod().getStart();
        Date end = t.get_pftPeriod().getEnd();
       
        if( start != null ){
          cal.setTime(start);
          sc.greateThanOrEqual("planFireTime",cal);
        }
       
        if( end != null ){
          Calendar cal_end = Calendar.getInstance();
          cal_end.setTime(end);
          cal_end.add(Calendar.DAY_OF_MONTH, 1);
          cal_end.add(Calendar.SECOND, -1);
          sc.lessThanOrEqual("planFireTime",cal_end);
        }
      }
    }
   
    return super.list(page, sc);
  }
 
  /**
   * 计划明细
   */
  public PlanDetail getDetail( String id ){
    if( StringUtils.isEmpty(id) )
      return null;
   
    return this.planDetailDao.read(id);
  }
 
  /**
   * 计划明细
   */
  public PlanDetail getDetailWithLock( String id ){
    if( StringUtils.isEmpty(id) )
      return null;
   
    return this.planDetailDao.readWithLock(id);
  }
 
  /**
   * 更新明细状态
   */
  public void updateDetailStatus(String detailId,Status status ){
    PlanDetail detail = getDetail(detailId);
    if( detail == null )
      throw new ApplicationException("执行计划明细["+detailId+"]对应数据不存在!");
   
    detail.setStatus(status);
   
    this.planDetailDao.update(detail);
  }
 
  /**
   * 未成功记录
   */
  @Deprecated
  protected int getUnsuccessfulCount(String planId,String planDetailId ){
    ListPage<PlanDetail> page = new ListPage<PlanDetail>(0);
    SearchCondition sc = new SearchCondition();
    sc.equal("plan.id", planId);
    sc.notEqual("id", planDetailId);
    sc.notEqual("status", Status.SUCCESS );
   
    page = planDetailDao.list(page, sc);
   
    return page.getAllSize();
  }
 
  public void updateStatus(String detailId ){
    PlanDetail detail = getDetail(detailId);
    if( detail != null && detail.getPlan() != null &&
        getDao().updateStatusIfAllDetailFinished( detail.getPlan().getId() ))
      log.info("计划任务在明细[{}]完成执行后,进行状态更新!",detail);
  }
 
  /**
   * 更新明细状态
   */
  public void updateDetailStatus(String detailId,boolean success,String errMsg){
    PlanDetail detail = getDetailWithLock(detailId);
    if( detail == null )
      throw new ApplicationException("执行计划明细["+detailId+"]对应数据不存在!");
   
    PlanDetail.Status oldStatus = detail.getStatus();
    if( PlanDetail.Status.WAITING_FOR_REPLY.equals(detail.getStatus())
        || PlanDetail.Status.NEW.equals(detail.getStatus())
        || PlanDetail.Status.FAILURE.equals(detail.getStatus())
        || PlanDetail.Status.EXCEPTION.equals(detail.getStatus()) ){
     
      detail.setStatus(success?PlanDetail.Status.SUCCESS:PlanDetail.Status.FAILURE);
      detail.setFinishTime( Calendar.getInstance() );
      if( StringUtils.isEmpty(errMsg))
        detail.setDescription("回调结果["+(success?"成功":"失败")+"]");
      else
        detail.setDescription( TextFormater.format(errMsg,197,true) );
       
      this.planDetailDao.update(detail);
     
      log.info("执行计划明细["+detailId+"]状态["
          +oldStatus+"]更新为["+detail.getStatus()+"]!");
     
      //TODO 并发可能导致 计划任务状态 不能成功更新
      /*
      if( success ){
        String planId = detail.getPlan().getId();
        int count = getUnsuccessfulCount( planId,detail.getId());
        if( count == 0 ){
          updateFinishTime( planId,Calendar.getInstance());
          log.info("执行计划明细[{}]执行完成,整个任务完成!",detail.getId());
        }
      }
      */
     
      //TODO 可能导致并发问题
      //执行依赖任务
      /*
      List<PlanDetail> replyOnList = planDetailDao.listRelyOnUnsuccessful(detailId);
      if( replyOnList == null || replyOnList.isEmpty() )
        return;
     
      //TODO 线程池处理
      for( PlanDetail item:replyOnList ){
        if( item.getPlan()==null || item.getPlan().getType() == null ){
          log.warn("上级任务执行[{}]依赖任务[{}]无法调用执行,类型为空!",detailId,item.getId());
          continue;
        }else if( success ){
          log.info("回调任务[{}]执行成功,执行依赖任务[{}]。",detailId,item.getId());
          jobQueueManager.jobInQueue(item.getPlan().getType().getId(),item.getId(),1);
        }else{
          item.setStatus(Status.FAILURE);
          item.setDescription("依赖任务["+detailId+"]执行返回失败!");
         
          planDetailDao.update(item);
        }
      }*/
     
    }else{
      log.warn("执行计划明细["+detailId
          +"]状态已改变为["+detail.getStatus()+"]不能进行更新!");
    }
   
  }
 
  public void executeRelyOnPlanDetail(boolean success,String detailId ){
    //执行依赖任务
    List<PlanDetail> replyOnList = planDetailDao.listRelyOnUnsuccessful(detailId);
    if( replyOnList == null || replyOnList.isEmpty() )
      return;
   
    //TODO 线程池处理
    for( PlanDetail item:replyOnList ){
      if( item.getPlan()==null || item.getPlan().getType() == null ){
        log.warn("上级任务执行[{}]依赖任务[{}]无法调用执行,类型为空!",detailId,item.getId());
        continue;
      }else if( success ){
        log.info("回调任务[{}]执行成功,执行依赖任务[{}]。",detailId,item.getId());
        jobQueueManager.jobInQueue(item.getPlan().getType().getId()
            ,item.getId(),1,item.getPlan().getPlanFireTime());
      }else{
        item.setStatus(Status.FAILURE);
        item.setDescription("依赖任务["+detailId+"]执行返回失败!");
       
        planDetailDao.update(item);
      }
    }
  }
 
  /**
   * 执行计划明细
   */
  public List<PlanDetail> listDetail(String planId){
    if( StringUtils.isEmpty(planId) )
      return null;
   
    ListPage<PlanDetail> page = new ListPage<PlanDetail>(Integer.MAX_VALUE);
    SearchCondition sc = new SearchCondition();
    sc.equal("plan.id", planId );
   
    page.addAscending("sequence");
    page = this.planDetailDao.list(page, sc);
   
    return page.getList();
  }
 
  /**
   * 执行计划明细
   */
  public List<PlanDetail> listDetail(Plan plan){
    return listDetail(plan.getId());
  }
 
  /**
   * 查询执行计划明细
   */
  public List<PlanDetail> listDetail( Object[] ids ){
    ListPage<PlanDetail> page = new ListPage<PlanDetail>(Integer.MAX_VALUE);
    SearchCondition sc = new SearchCondition();
    sc.in("id",ids);
   
    page.addAscending("sequence");
    this.planDetailDao.list(page,sc);
   
    return page.getList();
  }
 
  /**
   * 取创建时间最新记录
   */
  public Plan getLast(SchedulerType type){
    if( type == null || type.getId() == null )
      return null;
   
    return getLastByType( type.getId() );
  }
 
  /**
   * 取创建时间最新记录
   */
  public Plan getLastByType(String type){
    ifStringUtils.isEmpty(type) )
      return null;
   
    ListPage<Plan> page = new ListPage<Plan>(1);
    SearchCondition sc = new SearchCondition();
    sc.equal("type.id", type );
   
    page.addDescending("createdTime");
   
    return dao.list(page, sc).getFirst();
  }
 
  /**
   * 保存执行计划
   */
  public void save( Plan plan,List<PlanDetail> details ){
    this.save(plan, details, true );
  }
 
  /**
   * 保存执行计划
   */
  public void save( Plan plan,List<PlanDetail> details,boolean putAllInQueue ){
    if( plan == null || details == null )
      throw new ApplicationException("参数为空!");
   
    plan.setId( sequenceManager.nextSequenceNumber(plan)
        .replaceFirst(Plan.SEQUENCE_KEY,"") );
    dao.create(plan);
   
    List<String> refIds = new ArrayList<String>();
    for( PlanDetail item:details ){
      item.setId( plan.getId() + "-" + item.getSequence() );
      item.setPlan(plan);
     
      //putAllInQueue=true,所有任务进入执行队行
      //putAllInQueue=false,只有没有依赖的任务才进入执行队列
      if( putAllInQueue || !item.isRelyOn() )
        refIds.add(item.getId());
    }
    planDetailDao.create(details);
   
    jobQueueManager.jobInQueue(plan.getType().getId()
        ,1,refIds.toArray(new String[0]),plan.getPlanFireTime());
  }
 
  /**
   * 明细入任务队列
   */
  public void detailInQueue(PlanDetail pd){
    PlanDetail detail = this.getDetail( pd.getId() );
    if( detail == null )
      throw new ApplicationException("明细数据["+pd.getId()+"]不存在!");
   
    if( detail.getPlan() == null || detail.getPlan().getType() == null )
      throw new ApplicationException("明细数据["+pd.getId()+"]不完整!");
   
    jobQueueManager.jobInQueue(
        detail.getPlan().getType().getId(),detail.getId(),1,detail.getPlan().getPlanFireTime());
  }
 
  /**
   * 更新执行时间
   */
  public void updateFireTime(String id,Calendar fireTime){
    if( StringUtils.isEmpty(id) )
      return;
   
    if( fireTime == null )
      fireTime = Calendar.getInstance();
   
    Plan plan = dao.read(id);
    if( plan != null ){
      plan.setFireTime(fireTime);
      dao.update(plan);
    }
  }
 
  /**
   * 更新完成时间
   */
  public void updateFinishTime(String id,Calendar finishTime){
    if( StringUtils.isEmpty(id) )
      return;
   
    if( finishTime == null )
      finishTime = Calendar.getInstance();
   
    Plan plan = dao.read(id);
    if( plan != null ){
      if( plan.getFinishTime() == null )
        plan.setFinishTime(finishTime);
      plan.setFinished(Boolean.TRUE);
     
      dao.update(plan);
    }
  }
 
  /**
   * 查询依赖未完成任务
   */
  public List<PlanDetail> listRelyOnUnsuccessful( String id ){
    return this.planDetailDao.listRelyOnUnsuccessful(id);
  }
 
  /**
   * 更新数据状态
   */
  public void updateDetailStatus(Collection<Result> results){
    if( results == null || results.isEmpty() )
      return;
   
    String anyTaskId = null;
    for( Result result:results ){
      PlanDetail detail = planDetailDao.readWithLock( result.getKey() );
      if( detail != null ){
        if( detail.getFireTime() == null )
          detail.setFireTime(Calendar.getInstance());
       
        PlanDetail.Status newStatus = PlanDetail.Status.WAITING_FOR_REPLY;
       
        if( result.isInvokeSuccess()){
          newStatus = detail.isSynTask()?PlanDetail.Status
              .WAITING_FOR_REPLY:PlanDetail.Status.SUCCESS;
          detail.setFinishTime( Calendar.getInstance() );
        }else{
          newStatus = result.isException()
            ?PlanDetail.Status.EXCEPTION:PlanDetail.Status.FAILURE;
          detail.setErrMsg( TextFormater.format(result.getMessage(),497,true) );
          detail.incFailureCount( );
        }
       
        //detail.setStatus(newStatus);
        //planDetailDao.update(detail);
       
        planDetailDao.updateFireTimeAfterInvoke(detail.getId(),detail.getFireTime());
       
        //int i = planDetailDao.update(detail.getId(),PlanDetail.Status.NEW, newStatus);
        //int i =planDetailDao.update("id",detail.getId(),"status",detail.getStatus(), newStatus);
       
        int i = planDetailDao.updateStatusAfterInvoke(detail.getId(),newStatus);
       
        log.info("计划任务[{}]状态从["+detail.getStatus()+"]更新为["
            +newStatus+"]-[{}]",detail.getId(),i>0?"成功":"失败");
       
        anyTaskId = detail.getId();
      }
    }//end for
   
    //如果计划任务明细执行完成,确认完成标志更新成功
    updateStatus( anyTaskId );
  }

}
TOP

Related Classes of com.google.code.lightssh.project.scheduler.service.PlanManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.