Skip to content

Reutiliza metadados entre processamentos de logs - #132

Merged
pitangainnovare merged 3 commits into
scieloorg:mainfrom
pitangainnovare:perf/parsing-metadata-cache
Aug 29, 2026
Merged

Reutiliza metadados entre processamentos de logs#132
pitangainnovare merged 3 commits into
scieloorg:mainfrom
pitangainnovare:perf/parsing-metadata-cache

Conversation

@pitangainnovare

@pitangainnovare pitangainnovare commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Descrição do PR

O que esse PR faz?

Implementa um cache local ao processo para reutilizar os metadados de documentos e fontes durante o processamento sequencial de logs.

A alteração:

  • evita reconstruir os dicionários de metadados a cada log;
  • habilita o cache por padrão para as 26 coleções previstas no mapa de coleções;
  • mantém somente uma coleção em cache por processo;
  • substitui a entrada quando o worker começa a processar outra coleção;
  • invalida o cache quando muda a quantidade ou a última atualização de Document ou Source;
  • constrói a entrada em uma transação de leitura consistente;
  • mantém a entrada anterior caso a reconstrução falhe;
  • cria um novo URLTranslationManager e um novo tradutor para cada log;
  • compartilha somente os grandes dicionários imutáveis de documentos e fontes;
  • permite restringir as coleções pela variável PARSING_METADATA_CACHE_COLLECTIONS.

O cache foi separado da preparação dos metadados:

  • metadata.py continua responsável pela seleção do tradutor e construção do manager;
  • metadata_cache.py concentra assinatura, armazenamento, invalidação, sincronização e isolamento dos objetos mutáveis.

Não foi utilizado functools.cache, pois ele não oferece a invalidação necessária quando o PostgreSQL é atualizado e poderia manter todas as coleções simultaneamente na memória.

Também não foi utilizado o cache Django/Redis porque isso exigiria serializar e transportar estruturas potencialmente muito grandes. O objetivo é reutilizar esses dados diretamente na memória do processo Celery responsável pelo parsing.

Onde a revisão poderia começar?

A revisão pode começar por:

  1. metrics/services/parsing/metadata_cache.py
  2. metrics/services/parsing/metadata.py
  3. config/settings/base.py
  4. config/collections.py
  5. metrics/tests/parsing/test_metadata_cache.py

Como este poderia ser testado manualmente?

Executar a suíte de métricas:

docker compose -p usage -f local.yml run --rm --no-deps django \
  pytest metrics/tests -q

Resultado obtido:

123 passed, 2 skipped

Confirmar que nenhuma migration foi introduzida:

docker compose -p usage -f local.yml run --rm --no-deps django \
  python manage.py makemigrations --check --dry-run

Resultado obtido:

No changes detected

Para observar o comportamento durante o processamento, executar dois logs consecutivos da mesma coleção e verificar os registros:

Parsing metadata cache miss
Parsing metadata cache hit

Ao alternar a coleção, o registro esperado é:

Parsing metadata cache rebuild
reason=collection_changed

Também é possível desabilitar ou restringir o cache por ambiente:

PARSING_METADATA_CACHE_COLLECTIONS=prt,books

Algum cenário de contexto que queira dar?

Antes desta alteração, cada log reconstruía integralmente os dicionários gerados por Document.metadata() e Source.metadata().

Na coleção PRT, com 35.020 documentos e 102 fontes, 25 preparações isoladas apresentaram:

  • sem cache: 9,458 segundos;
  • com cache: 0,553 segundo;
  • redução aproximada de 94% nessa etapa.

No teste manual de três logs completos da PRT, os payloads com e sem cache apresentaram exatamente os mesmos:

  • hashes SHA-256;
  • resumos;
  • totais de linhas válidas e descartadas;
  • documentos mensais e anuais;
  • arquivos JSON byte a byte.

As 26 coleções estarem habilitadas não significa que todas serão carregadas na memória. Cada processo mantém somente a coleção usada mais recentemente. Isso limita o consumo de memória, especialmente em workers que podem receber mais de uma coleção.

Os workers de parsing operam com concorrência igual a 1, o que favorece a reutilização sequencial. Ainda assim, o acesso ao cache é protegido por lock.

Screenshots

N/A

Quais são os tickets relevantes?

Parte de #128

Referências

  • Implementação anterior de Document.metadata() e Source.metadata().
  • Configuração das filas de parsing por tamanho de coleção.
  • Benchmark local realizado com os logs de julho de 2026 da coleção PRT.

Segurança da informação (NSI.04)

Seção obrigatória. Marque as opções aplicáveis e justifique quando necessário. Referência: NSI.04 - Norma de Desenvolvimento Seguro.

Este PR manipula dados sensíveis ou pessoais (LGPD)?

  • Sim — descreva os controles de proteção aplicados (criptografia, mascaramento, anonimização, etc.):
  • Não

Este PR altera autenticação, autorização, controle de acesso ou gerenciamento de sessão?

  • Sim — descreva o que mudou e por quê:
  • Não

Este PR introduz, atualiza ou remove dependências de terceiros?

  • Sim — as novas dependências foram verificadas no SBOM/Trivy sem vulnerabilidades críticas/altas em aberto?
    • Verificado e aprovado
    • Pendente / vulnerabilidade aceita com justificativa:
  • Não

Este PR foi validado pelo pipeline de segurança (SonarQube / Trivy)?

  • Sim — link do job:
  • Não aplicável a este PR (justifique):

Pendente de preenchimento após a execução do pipeline do pull request.

Este PR concatena, monta ou executa comandos SQL, HTML ou JavaScript a partir de entrada externa?

  • Sim — confirme que há sanitização/parametrização (prepared statements, escaping, etc.):
  • Não

A implementação executa somente uma instrução SQL fixa para configurar a transação de leitura, sem incorporar entrada externa.

Este PR expõe novos endpoints, telas ou serviços?

  • Sim — HTTPS obrigatório está garantido e o acesso segue o princípio de menor privilégio?
  • Não

Algum segredo, senha, chave ou token está sendo adicionado ao código-fonte?

  • Não, nenhum segredo foi commitado
  • Sim (bloquear merge e corrigir antes de prosseguir)

@pitangainnovare
pitangainnovare merged commit 4b51206 into scieloorg:main Aug 29, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant