HeartbeatController.class.php 3.91 KB
<?php
/**
 * 心跳 刷新在线存活状态
 * Created by PhpStorm.
 * User: zhoutao
 * Date: 2018/2/1
 * Time: 下午4:38
 */

namespace Api\Controller\Room;

use Common\Common\Constant;
use Common\Common\Order;
use Common\Service\MainService;
use Common\Service\StudioService;
use Org\Util\DistributedRedisLock;
use VcySDK\Enterprise;
use VcySDK\Service;

class HeartbeatController extends AbstractController
{

    /**
     * Heartbeat
     * @author zhoutao
     * @desc 心跳 刷新在线存活状态
     * @param Int lm_id:true:1 直播活动ID
     * @return array
            [
                'onlineTotal' => 12 // 直播当前在线人数
            ]
     */
    public function index()
    {
        $lmId = I('post.lm_id');
        if (empty($lmId)) {
            E('_EMPTY_LIVE_ID');
        }

        $redis = new \Redis();
        $redis->connect(cfg('REDIS_HOST'), cfg('REDIS_PORT'));
        if (cfg('REDIS_PWD')) {
            $redis->auth(cfg('REDIS_PWD'));
        }

        // 获取当前在线人数
        $this->_result['onlineTotal'] = count($redis->keys('Live_' . $lmId . '_USER_*'));
        // 是否在在线人数内 不计算峰值
        $userInRedisKey = 'Live_' . $lmId . '_USER_' . $this->uid;
        if ($redis->exists($userInRedisKey)) {

            // 刷新存活时长
            $redis->set($userInRedisKey, '', Constant::ONLINE_SURVIVAL_TIME);
        } else {
            $this->_result['onlineTotal'] ++;

            // 不存在 当成新人计算
            // 获取直播活动详情
            $mainServ = new MainService();
            $mainDetail = $mainServ->get($lmId);
            // 如果已经结束了 不扣减并发人数
            if ($mainDetail['live_status'] == Constant::LIVE_STATUS_OVER) {
                // 算进在线人数内
                $redis->set($userInRedisKey, '', Constant::ONLINE_SURVIVAL_TIME);
                return true;
            }

            // 获取锁
            $redLock = new DistributedRedisLock([$redis], 500, 10);
            $lock = $redLock->lock('Live_' . $lmId . '_Lock_Update_Peak', 1000);
            if (!$lock) {
                E('_ERR_PLEASE_TRY_AGAIN_LATER');
            }

            // 获取峰值
            $redisKeyNamePeak = 'Live_' . $lmId . '_PEAK';
            $peakMemberNum = $redis->get($redisKeyNamePeak) ?: $mainDetail['online_peak'];

            // 在线人数超过峰值
            if ($this->_result['onlineTotal'] > $peakMemberNum) {
                $studioServ = new StudioService();
                $studioDetail = $studioServ->get_by_conds(['lm_id' => $mainDetail['lm_id']]);

                // isStandard -- 企业是否使用标准产品 : 0:非标准, 1:标准产品
                $sdk = new Enterprise(Service::instance());
                $epDetail = $sdk->detail();
                if (1 == $epDetail['isStandard']) {
                    // 扣减并发人数
                    $orderUtil = new Order();
                    $deductionsSuccess = $orderUtil->LiveCaseExpend([
                        'liveCastId' => $studioDetail['stream_id'],
                        'lcelSpendAmout' => 1
                    ]);
                    \Think\Log::record('扣减结果:::' . var_export($deductionsSuccess, true));
                    // 扣减失败
                    if (!$deductionsSuccess) {
                        E('_ERR_PLEASE_TRY_AGAIN_LATER');
                    }
                }

                // 单个用户进来只会增加一个峰值
                $redis->incr($redisKeyNamePeak);
                $redis->expire($redisKeyNamePeak, Constant::PEAK_SURVIVAL_TIME);
                // 增加峰值
                $mainServ->update($lmId, ['online_peak = online_peak + ?' => 1]);
            }

            // 释放锁
            $redLock->unlock($lock);
            // 算进在线人数内
            $redis->set($userInRedisKey, '', Constant::ONLINE_SURVIVAL_TIME);
        }

        return true;
    }
}