如何在后台执行长任务?

我有一个使用Symfony 5制作的应用程序,我有一个脚本,可以将服务器上的视频上传到登录的用户频道。


这基本上是我的控制器的代码:


    /**

     * Upload a video to YouTube.

     *

     * @Route("/upload_youtube/{id}", name="api_admin_video_upload_youtube", methods={"POST"}, requirements={"id" = "\d+"})

     */

    public function upload_youtube(int $id, Request $request, VideoRepository $repository, \Google_Client $googleClient): JsonResponse

    {

        $video = $repository->find($id);


        if (!$video) {

            return $this->json([], Response::HTTP_NOT_FOUND);

        }


        $data = json_decode(

            $request->getContent(),

            true

        );


        $googleClient->setRedirectUri($_SERVER['CLIENT_URL'] . '/admin/videos/youtube');

        $googleClient->fetchAccessTokenWithAuthCode($data['code']);


        $videoPath = $this->getParameter('videos_directory') . '/' . $video->getFilename();


        $service = new \Google_Service_YouTube($googleClient);

        $ytVideo = new \Google_Service_YouTube_Video();


        $ytVideoSnippet = new \Google_Service_YouTube_VideoSnippet();

        $ytVideoSnippet->setTitle($video->getTitle());

        $ytVideo->setSnippet($ytVideoSnippet);


        $ytVideoStatus = new \Google_Service_YouTube_VideoStatus();

        $ytVideoStatus->setPrivacyStatus('private');

        $ytVideo->setStatus($ytVideoStatus);


        $chunkSizeBytes = 1 * 1024 * 1024;


        $googleClient->setDefer(true);


        $insertRequest = $service->videos->insert(

            'snippet,status',

            $ytVideo

        );


       

这基本上是有效的,但问题是视频可能非常大(10G +),所以它需要很长时间,基本上Nginx在结束之前终止,并在上传完成之前返回“504网关超时”。


无论如何,我不希望用户在上传页面时必须等待页面加载。


因此,我正在寻找一种方法,而不仅仅是立即运行该脚本,而是在某种后台线程中或以异步方式执行该脚本。


控制器向用户返回a,我可以告诉他正在上传,稍后再回来检查进度。200


如何做到这一点?


噜噜哒
浏览 75回答 1
1回答

慕侠2389804

有很多方法可以做到这一点,但你基本上想要的是解耦动作触发器及其执行。只是:从控制器中删除所有繁重的工作。您的控制器最多只应检查客户端提供的视频 ID 是否存在于 .VideoRepository存在?很好,那么您需要将此“工作订单”存储在某个地方。有许多解决方案,具体取决于您已经安装的内容,您感觉更舒适的技术等。为了简单起见,假设您有一张带有 、 和 的表,也许还有 。因此,您的控制器唯一要做的就是在此表中创建一个新记录(也许检查作业是否尚未“排队”,这种详细信息取决于您的实现)。PendingUploadsvideoIdstatuscreatedAtuserId然后返回(或 ,在这种情况下可能更合适200202)然后,您需要编写一个单独的进程。很可能是您定期执行的控制台命令(使用最简单的方法)cron在每次执行时,该进程(将具有所有逻辑,并且可能还有一个)将检查哪些作业正在等待上传,按顺序处理它们,并设置为您表示要完成的任何内容。例如,您可能必须(挂起)、(处理)和(已处理),并在脚本的每个步骤上相应地设置状态。Google_ClientPendingUploadsRepositorystatusstatus012具体实现此目的的详细信息取决于您。这个问题过于宽泛和固执己见。选择一些你已经理解的东西,让你移动得更快。如果要将作业存储在 Rabbit、Redis、数据库或平面文件中,则不是特别重要。如果以 或 开头的“使用者”。cronsupervisorSymfony有一个现成的组件,可以让你异步解耦这种消息传递(Symfony信使),这很不错。调查它是否是你的一杯茶,尽管如果你不打算在你的应用程序中将其用于其他任何事情,我会让它变得简单。
打开App,查看更多内容
随时随地看视频慕课网APP