Arquitetura de Upload de Vídeos: Web Workers e Multipart Upload
Introdução
O upload de arquivos grandes, especialmente vídeos, é um desafio em aplicações web. Se processado e enviado diretamente pela "Main Thread" (a thread principal do navegador), arquivos grandes podem travar a interface do usuário, causando uma má experiência (a famosa "tela congelada").
Para resolver isso, nossa arquitetura utiliza Web Workers para processar o upload em background, mantendo a interface do usuário totalmente responsiva.
[!NOTE] Embora muitas vezes confundido com Service Workers (que interceptam requisições de rede e funcionam como proxy), neste caso utilizamos Web Workers. A diferença crucial é que o Web Worker é focado em executar scripts em background para processamento pesado, enquanto o Service Worker é mais focado em cache e capacidades offline.
A Solução: upload.worker.js
Nossa solução reside no arquivo assets/js/upload.worker.js. Ele implementa uma estratégia robusta de Multipart Upload.
Como Funciona
Em vez de enviar o arquivo inteiro de uma só vez, o worker divide o arquivo em pequenos pedaços ("chunks" ou "parts") e os envia em paralelo. Isso traz várias vantagens:
- Concorrência Controlada: Podemos enviar várias partes ao mesmo tempo.
- Resiliência: Se uma parte falhar, precisamos reenviar apenas ela, não o arquivo todo.
- Não Bloqueante: Todo o processamento de "fatiar" o arquivo (slicing) acontece no worker, fora da thread principal.
O Fluxo do Processo
O processo é orquestrado em três etapas principais:
- Start: O worker solicita ao backend a iniciação do upload multipart e recebe um
uploadId. - Upload Part: O worker divide o arquivo e envia as partes. Aqui usamos um "limiter" para não sobrecarregar a rede, mantendo um número máximo de uploads simultâneos (atualmente configurado para 5).
- Complete: Após todas as partes serem enviadas com sucesso, o worker avisa o backend para remontar o arquivo final.
Diagrama da Arquitetura
Abaixo, um diagrama de sequência ilustrando a comunicação entre a UI (Main Thread), o Web Worker e a API Backend.
Detalhe Técnico: O uploadPromiseLimiter
Um ponto alto da implementação é a função uploadPromiseLimiter. Ela gerencia a fila de uploads das partes.
// Exemplo simplificado da lógica no worker
async function uploadPromiseLimiter(promises, limit) {
const executing = []
for (const promise of promises) {
// Inicia a promise e remove da lista de execução quando terminar
const p = promise().then(() => executing.splice(executing.indexOf(p), 1))
executing.push(p)
// Se atingiu o limite, espera alguma terminar antes de iniciar a próxima
if (executing.length >= limit) {
await Promise.race(executing)
}
}
}
Isso garante que, mesmo para um vídeo de 1GB dividido em centenas de partes, nunca teremos mais que 5 requisições ativas simultaneamente, evitando sobrecarga do navegador e do servidor.
Conclusão
O uso de Web Workers para essa tarefa transformou a experiência de upload. Conseguimos processar gigabytes de dados sem que o usuário perceba qualquer lentidão na interface, fornecendo feedback de progresso em tempo real e garantindo confiabilidade na transferência dos dados.

Comentarios (0)