CheckAttachController.class.php 7.46 KB
<?php
/**
 * Created by PhpStorm.
 * User: liyifei2012it
 * Date: 17/4/13
 * Time: 11:38
 */
namespace Frontend\Controller\Callback;

use Think\Log;
use VcySDK\Service;
use VcySDK\Cron;
use VcySDK\FileConvert;
use Common\Common\Constant;
use Common\Service\SourceService;
use Common\Service\SourceAttachService;
use Common\Service\TaskService;

class CheckAttachController extends AbstractController
{
    /**
     * 检查附件(视频转码、文件转换)计划任务回调接口
     * @author zhonglei
     */
    public function Index()
    {
        Log::record(sprintf('---%s %s CheckAttach START---', QY_DOMAIN, APP_IDENTIFIER), Log::INFO);

        $source_id = I('get.source_id', 0, 'intval');
        $cron_id = I('get.cron_id', '', 'trim');

        if (empty($cron_id) || empty($source_id)) {

            $this->_exit();
        }

        // 业务未找到任务,退出并删除传参过来的当前计划任务
        $taskServ = new TaskService();
        $task = $taskServ->get_by_conds(['source_id' => $source_id]);
        if (empty($task)) {

            Log::record("not found task, source_id: {$source_id}", Log::INFO);
            // 删除UC计划任务
            $this->_delCron($cron_id);
        }

        // 未找到素材,删除计划任务
        $cron_id = $task['cron_id'];
        $sourceServ = new SourceService();
        $source = $sourceServ->get($source_id);
        if (empty($source)) {

            Log::record("not found source, source_id: {$source_id}", Log::INFO);
            $this->_delTask($source_id, $cron_id);
        }

        // 未找到附件,删除计划任务
        $attachServ = new SourceAttachService();
        $source_attachs = $attachServ->list_by_conds(['source_id' => $source_id]);
        if (empty($source_attachs)) {
            // 将素材状态修改为正常
            $sourceServ->update($source_id, ['source_status' => Constant::SOURCE_STATUS_NORMAL]);

            Log::record("not found attach, source_id: {$source_id}", Log::INFO);
            $this->_delTask($source_id, $cron_id);
        }

        $convert_status = Constant::SOURCE_STATUS_CONVERT;
        $convertServ = new FileConvert(Service::instance());

        foreach ($source_attachs as $source_attach) {
            // 已完成
            if (!empty($source_attach['at_convert_url'])) {

                continue;
            }

            $at_convert_url = '';
            $at_cover_url = '';
            switch ($source_attach['at_type']) {
                // 视频
                case Constant::ATTACH_TYPE_VIDEO:
                    $result = $convertServ->getVodPlayUrl($source_attach['at_id']);
                    if (is_array($result) && (isset($result['url']) || isset($result['hd']))) {
                        // 转码后的视频url
                        $at_convert_url = str_replace('http://', '//', (!empty($result['hd']) ? $result['hd'] : $result['url']));
                        $at_convert_url = str_replace('https://', '//', $at_convert_url);

                        // 视频封面地址(5秒内会生成)
                        // FIXME 因前端技术实现难点,视频第一帧做为封面需求暂时废弃(2018-01-03)。视频第一帧图片先做存储,等待前端攻克技术难题后使用
                        $at_cover_url = str_replace('http://', '//', $result['coverUrl']);
                        $at_cover_url = str_replace('https://', '//', $at_cover_url);

                        $convert_status = Constant::SOURCE_STATUS_NORMAL;
                    }
                    break;

                // 文件
                case Constant::ATTACH_TYPE_FILE:
                    $result = $convertServ->get($source_attach['at_id']);
                    if (is_array($result) && isset($result['caConvertStatus'])) {
                        // 转码成功
                        if (FileConvert::CONVERT_STATUS_SUCCESS == $result['caConvertStatus']) {

                            $at_convert_url = $result['caAttachment'];
                            $convert_status = Constant::SOURCE_STATUS_NORMAL;
                        }

                        // 转码失败(状态不是:待处理、转码中、成功,即为失败)
                        $normalStatus = [
                            FileConvert::CONVERT_STATUS_WATTING,
                            FileConvert::CONVERT_STATUS_ING,
                            FileConvert::CONVERT_STATUS_SUCCESS,
                        ];

                        if (!in_array($result['caConvertStatus'], $normalStatus)) {

                            $convert_status = Constant::SOURCE_STATUS_FAIL;
                        }
                    }
                    break;
            }

            // 转码成功时,修改转码后url
            if (!empty($at_convert_url)) {
                // 待更新数据
                $update_data['at_convert_url'] = $at_convert_url;
                // 视频封面地址不为空,存储视频封面
                if (!empty($at_cover_url)) {

                    $update_data['at_cover_url'] = $at_cover_url;
                }

                $attachServ->update($source_attach['source_attach_id'], $update_data);
                Log::record("convert success, source_attach_id: {$source_attach['source_attach_id']}, at_convert_url: {$at_convert_url}", Log::INFO);
            }
        }

        // 更新素材状态、结束任务
        if ($convert_status != Constant::SOURCE_STATUS_CONVERT) {
            // 重置转码状态
            $successAttachs = $attachServ->count_by_conds(['source_id' => $source_id, 'at_convert_url != ?' => '']);
            if ($successAttachs != count($source_attachs) && Constant::SOURCE_STATUS_NORMAL == $convert_status) {

                $convert_status = Constant::SOURCE_STATUS_CONVERT;
            }

            $sourceServ->update($source_id, ['source_status' => $convert_status]);
            Log::record("update source_status, source: {$source_id}", Log::INFO);

            // 所有任务转码完成 或 转码失败,结束本地任务
            if ($successAttachs == count($source_attachs) || Constant::SOURCE_STATUS_FAIL == $convert_status) {

                $this->_delTask($source_id, $cron_id);
            }
        }

        // 结束回调
        $this->_exit();
    }

    /**
     * 退出
     * @author zhonglei
     * @return void
     */
    private function _exit()
    {
        // 日志结束
        Log::record(sprintf('---%s %s CheckAttach END---', QY_DOMAIN, APP_IDENTIFIER), Log::INFO);
        exit('SUCCESS');
    }

    /**
     * 删除计划任务并退出
     * @author zhonglei
     * @param int $source_id 素材ID
     * @param string $cron_id UC计划任务ID
     * @return void
     */
    private function _delTask($source_id, $cron_id)
    {
        // 删除业务计划任务记录
        $taskServ = new TaskService();
        $taskServ->delete_by_conds([
            'source_id' => $source_id,
            'cron_id' => $cron_id,
        ]);

        // 删除UC计划任务
        $this->_delCron($cron_id);
    }

    /**
     * 删除UC计划任务
     * @param string $cron_id 计划任务ID
     * @return void
     */
    private function _delCron($cron_id)
    {
        $cronSdk = new Cron(Service::instance());

        try {
            // 删除计划任务
            $cronSdk->delete($cron_id);
        } catch (\Exception $e) {

            Log::record('uc delete cron fail: cron_id=' . $cron_id . ', msg=' . $e->getMessage(), Log::ERR);
        }

        $this->_exit();
    }
}