为了账号安全,请及时绑定邮箱和手机立即绑定

如何在后台执行长任务?

如何在后台执行长任务?

PHP
噜噜哒 2022-09-12 10:10:36
我有一个使用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如何做到这一点?
查看完整描述

1 回答

?
慕侠2389804

TA贡献1719条经验 获得超6个赞

有很多方法可以做到这一点,但你基本上想要的是解耦动作触发器及其执行。

只是:

  • 从控制器中删除所有繁重的工作。您的控制器最多只应检查客户端提供的视频 ID 是否存在于 .VideoRepository

  • 存在?很好,那么您需要将此“工作订单”存储在某个地方。

    有许多解决方案,具体取决于您已经安装的内容,您感觉更舒适的技术等。

    为了简单起见,假设您有一张带有 、 和 的表,也许还有 。因此,您的控制器唯一要做的就是在此表中创建一个新记录(也许检查作业是否尚未“排队”,这种详细信息取决于您的实现)。PendingUploadsvideoIdstatuscreatedAtuserId

  • 然后返回(或 ,在这种情况下可能更合适200202)

然后,您需要编写一个单独的进程。

很可能是您定期执行的控制台命令(使用最简单的方法)cron

在每次执行时,该进程(将具有所有逻辑,并且可能还有一个)将检查哪些作业正在等待上传,按顺序处理它们,并设置为您表示要完成的任何内容。例如,您可能必须(挂起)、(处理)和(已处理),并在脚本的每个步骤上相应地设置状态。Google_ClientPendingUploadsRepositorystatusstatus012

具体实现此目的的详细信息取决于您。这个问题过于宽泛和固执己见。选择一些你已经理解的东西,让你移动得更快。如果要将作业存储在 Rabbit、Redis、数据库或平面文件中,则不是特别重要。如果以 或 开头的“使用者”。cronsupervisor

Symfony有一个现成的组件,可以让你异步解耦这种消息传递(Symfony信使),这很不错。调查它是否是你的一杯茶,尽管如果你不打算在你的应用程序中将其用于其他任何事情,我会让它变得简单。


查看完整回答
反对 回复 2022-09-12
  • 1 回答
  • 0 关注
  • 69 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信