private function perform_upload_tus(string $file_path, $file_size, array $attempt): string
    {
        $default_chunk_size = (100 * 1024 * 1024); // 100 MB

        $url = $attempt['body']['upload']['upload_link'];
        $url_path = parse_url($url)['path'];

        $base_url = str_replace($url_path, '', $url);
        $api_path = $url_path;
        $api_pathp = explode('/', $api_path);
        $key = $api_pathp[count($api_pathp) - 1];
        $api_path = str_replace('/' . $key, '', $api_path);

        $bytes_uploaded = 0;
        $failures = 0;
        $chunk_size = $this->getTusUploadChunkSize($default_chunk_size, (int)$file_size);

        $client = new \TusPhp\Tus\Client($base_url);
        $client->setApiPath($api_path);
        $client->setKey($key)->file($file_path);

        do {
            try {
                $bytes_uploaded = $client->upload($chunk_size);
            } catch (\Exception $e) {
                // We likely experienced a timeout, but if we experience three in a row, then we should back off and
                // fail so as to not overwhelm servers that are, probably, down.
                if ($failures >= 3) {
                    throw new VimeoUploadException($e->getMessage());
                }

                $failures++;
                sleep((int)pow(4, $failures)); // sleep 4, 16, 64 seconds (based on failure count)
            }
        } while ($bytes_uploaded < $file_size);

        return $attempt['body']['uri'];
    }