PHP知道服务何时完成转换

时间:2017-06-29 15:17:11

标签: php symfony while-loop

我在Symfony应用中使用视频转换服务。我的问题是我需要知道视频转换何时完成。流程是:我触发视频转换服务,当视频成功转换时,视频服务将视频状态更新为“转换”。如果失败则状态为“失败”。在将视频设置为发布之前,我需要继续检查视频状态。

   public function setVideo(Post $post, Video $video){

    if($video->getStatus() != 'ready_for_conversion'){
        throw new ApiException('video cannot be processed');
    }else{
        $videoService = $this->container->get('app.video_service');
        $videoService->submitJob($video);
        $converting = true;
        while ($converting) {
            $status = $video->getStatus();
            if($status == Video::STATUS_CONVERTED) {
                break;
            }elseif ($status == Video::STATUS_FAILED){
                throw new ApiException('video failed');
            }
        }

        $post->setVideo($video);
    }
}

当我运行此代码时,我得到了

php.CRITICAL: Fatal Error: Maximum execution time of 30 seconds exceeded

即使视频服务在一段时间后成功更新状态。

1 个答案:

答案 0 :(得分:1)

在不了解应用程序架构的情况下,您的问题很难回答。我将假设您上传的视频需要一些时间来完成处理。似乎是一个安全的赌注,因为视频的计算成本非常高。正如您从错误中看到的那样,这就是破坏您的代码的原因。基本上处理视频需要30秒以上,这并不奇怪。

要解决此问题,您需要重新考虑解决方案。最好的方法是回过头来考虑你的目标。如果您的代码中的Post对象是某种类型的文章或博客帖子,并且您试图阻止视频在其实际准备好之前显示或使用,那么我建议您让帖子关联视频并将检查逻辑移动到您的模型中。在这种情况下你可以做以下事情:

class Post
{
    ...
    public function isVideoAvailable()
    {
        return isset($this->video) && Video::STATUS_CONVERTED === $this->getVideo()->getStatus();
    }
}

然后在显示或在api响应中将其包装到您的视图模板中。这是一个小例子:

{% if post.isVideoAvailable() %}
<div class="video">
    <!-- put video embed code here -->
</div>
{% endif %}

如果您有充分理由阻止视频与Post相关联。然后你可能需要将其分解为几个控制器动作。一个接受视频并开始处理,另一个接受轮询以查看它何时完成,最后一个关联视频(你合并后两个,对我来说似乎很麻烦,因为它不是SRP,但你可能有一个也是有充分理由的。)

还有其他选项,比如使用网络套接字或http流,但这里的解释很复杂。

简短的回答是,对于长时间运行的进程使用任何Web服务端点是不好的。这样做有很多其他性能问题会在某些时候出现,所以不要这样做。