Execute a long task in background

I have an app made using Symfony 5, and I have a script that upload a video located on the server to the logged-in user channel.

Here’s basically the code of my controller:

    /**
     * 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
        );

        $media = new Google_Http_MediaFileUpload($googleClient, $insertRequest, 'video/*', null, true, $chunkSizeBytes);
        $media->setFileSize(filesize($videoPath));

        $uploadStatus = false;
        $handle = fopen($videoPath, "rb");

        while (!$uploadStatus && !feof($handle)) {
            $chunk = fread($handle, $chunkSizeBytes);
            $uploadStatus = $media->nextChunk($chunk);
        }

        fclose($handle);
    }

This basically works, but the problem is that the video can be very big (10G+), so it’s taking a very long time, and basically Nginx terminates before it’s ended and returns a “504 Gateway Timeout” before the upload is completed.

And anyway, I don’t want the user to have to wait for a page to load while it’s uploading.

So, I’m looking for a way to, instead of just immediately running that script, execute that script in some kind of background thread, or in a asynchronous way.

The controller returns a 200 to the user, I can tell him that uploading is happening and to come back later to check progress.

Any idea if:
1/ It’s possible
2/ How to that?

Source: Symfony Questions

Was this helpful?

0 / 0

Leave a Reply 0

Your email address will not be published. Required fields are marked *