zyanfei
9/29/2018 - 3:24 AM

定时脚本基类

定时脚本基类

<?php

/**
 * 执行cron基类
 *
 * @author      huangmin<andhm@126.com>
 * @version     $Id$
 * @since        1.0
 */
abstract class BaseCron
{

    /**
     * cron文件路径
     * @var string
     */
    protected $cronFile;

    /**
     * 脚本开始时间
     * @var int
     */
    protected $startTime;

    /**
     * 脚本结束时间
     * @var int
     */
    protected $endTime;

    /**
     * 脚本执行状态
     * @var int
     */
    protected $status;
    /*
     * 数据库连接
     */
    protected $dbConnection;
    /**
     * 需要关注的结果描述
     * @var string
     */
    protected $attention = [];


    /**
     * 当前cron执行的记录ID
     * @var int
     */
    private $cronLogId;

    CONST CRON_STATUS_SUCC = 1; // 脚本执行状态,成功
    CONST CRON_STATUS_FAIL = 2; // 脚本执行状态,失败

    /**
     * 构造方法
     * @param string $cronDesc cron用途描述
     * @param string $cronFile cron文件路径
     */
    public function __construct($cronFile = __FILE__)
    {
        if (defined('AG_DOC_ROOT')) {
            $cronFile = str_replace(AG_DOC_ROOT, '', $cronFile);
        }
        Context::getInstance()->initialize();
        $this->dbConnection = Propel::getConnection();
        $this->cronFile = $cronFile;
        $this->status = self::CRON_STATUS_SUCC; // 默认状态是 成功
    }

    /**
     * 获取数据库连接
     * @return Connection
     */
    public function getDBConnection()
    {
        return $this->dbConnection;
    }

    /**
     * 业务脚本执行核心逻辑
     * @return void
     */
    abstract protected function run();

    /**
     * 脚本执行流程
     * @return void
     */
    public function runAll()
    {
        $this->beforeRun();

        // 捕获异常
        $this->errorHandler();

        try {
            $this->run();
        } catch (Exception $ex) {
            $this->status = self::CRON_STATUS_FAIL;
            $this->setAttention('errormsg:' . $ex->getMessage() . ', line:' . $ex->getLine() . ', traceinfo:' . $ex->getTraceAsString());
        }

        $this->afterRun();
    }

    /**
     * 脚本执行之前处理逻辑
     * @return void
     */
    protected function beforeRun()
    {
        $this->startTime = time();
        $sql = 'insert into t_cron_log set cron_file=?,start_time=?,status=0';
        $smtm = $this->dbConnection->prepareStatement($sql);
        $smtm->executeUpdate([$this->cronFile, $this->startTime]);
        $this->cronLogId = mysql_insert_id();

        // TODO
        // 执行cron之前,写入t_cron_log执行记录
        // 需要写入的字段有:cron_file,start_time
        // 写入db后,需要获取到 记录的 主键ID, $this->cronLogId = ${主键ID}
    }

    /**
     * 脚本执行之后处理逻辑
     * @return void
     */
    protected function afterRun()
    {
        $attention = implode(',', $this->attention);
        $this->endTime = time();
        $sql = 'update  t_cron_log set status=?,attention=?,end_time=? where log_id=?';
        $smtm = $this->dbConnection->prepareStatement($sql);
        $smtm->executeUpdate([$this->status, $attention, time(), $this->cronLogId]);
        // TODO
        // 更新t_cron_log记录
        // 需要更新的字段有:end_time,status
        // 更新条件是 主键ID = $this->cronLogId
    }

    /**
     * fatal 错误捕获
     * @return void
     */
    protected function errorHandler()
    {
        $objCron = $this;
        register_shutdown_function(function () use ($objCron) {
            $errorInfo = error_get_last();
            $fatal = E_ERROR | E_USER_ERROR | E_CORE_ERROR |
                E_COMPILE_ERROR | E_RECOVERABLE_ERROR | E_PARSE;
            if (!empty($errorInfo) && ($errorInfo['type'] === ($errorInfo['type'] & $fatal))) {
                $objCron->status = self::CRON_STATUS_FAIL;
                $objCron->setAttention('errormsg:' . $errorInfo['message'] . ', line:' . $errorInfo['line']);
                $objCron->afterRun();
            }
        });
    }

    protected function setAttention($v)
    {
        $this->attention[] = $v;
    }

    protected function setSuccess()
    {
        $this->status = self::CRON_STATUS_SUCC;
    }

    protected function setFail()
    {
        $this->status = self::CRON_STATUS_FAIL;
    }

    protected function doChangeLog($table,$column,$from,$to,$pk,$id)
    {
        $data = [];
        $data['table'] = $table;
        $data['column'] = $column;
        $data['from'] = $from;
        $data['to'] = $to;
        $data[$pk] = $id;
        $str = json_encode($data)."\n";
        file_put_contents(AG_DOC_ROOT . '/var/logs/http_to_https/dbconvert.log',$str, FILE_APPEND);
    }

}