Skip to content

Busca de Músicas — Design Técnico

Gerado pelo Writer (Reversa) em 2026-05-11

Interface

Símbolo Assinatura Retorno
getDetalhesTermoBusca (termo: string) { tipo: 'indice'\|'texto'\|'vazio', valor: any }
MusicasRepository.findAllBy ({ termo, livro?, rotulo?, page, pageSize }) Promise<{ items: Musica[], hasNextPage: boolean }>
buscarMusicas (thunk) (params: BuscaParams) ThunkAction

Fluxo Principal

  1. Usuário digita no campo de busca → debounce dispara buscarMusicas
  2. getDetalhesTermoBusca(termo) classifica:
  3. ""{ tipo: 'vazio' }
  4. parseInt(termo) não é NaN{ tipo: 'indice', valor: parseInt(termo) }
  5. qualquer outro → normalizar NFKD → uppercase → remove [^A-Z0-9 ] → trim → split por \s+ → cada token + "*" → join " " → remove "**"{ tipo: 'texto', valor: queryFTS5 }
  6. findAllBy seleciona estratégia:
  7. vazioSELECT ... FROM musica LEFT JOIN cantico_livro ... ORDER BY titulo LIMIT ? OFFSET ?
  8. indiceWHERE CAST(cantico_livro.indice AS INTEGER) = ?
  9. textoFROM musica_busca JOIN musica ON musica_busca.rowid = musica.id_musica WHERE musica_busca MATCH ? ORDER BY bm25(musica_busca, 50, 5)
  10. Cláusulas condicionais adicionadas se livro ou rotulo fornecidos
  11. LIMIT pageSize + 1 → se resultado > pageSize: hasNextPage=true, descarta último item
  12. Resultado retornado ao thunk → store atualizado

Dependências

  • op-sqlite — engine SQLite com FTS5 habilitado
  • musica_busca — tabela FTS5 virtual, deve estar sincronizada com musica
  • Redux Toolkit — store que recebe os resultados

Riscos e Lacunas

  • 🟡 Termo alfanumérico como "23a" cai na busca FTS5 e pode não encontrar o índice esperado
  • 🔴 Não mapeado: o que ocorre quando musica_busca está dessincronizada com musica (ex.: após falha de migração)