Skip to content

Garante o registro do documento na coleção de origem do XML e guarda o nome do pacote SPS por coleção - #1492

Open
robertatakenaka wants to merge 17 commits into
scieloorg:mainfrom
robertatakenaka:main_multicollections
Open

robertatakenaka wants to merge 17 commits into
scieloorg:mainfrom
robertatakenaka:main_multicollections

Conversation

@robertatakenaka

Copy link
Copy Markdown
Member

O que esse PR faz?

Garante que o registro de um XML no pid_provider grave, de forma consistente, o pid v2 e a versão do XML da coleção de origem, ou falhe sem deixar registro parcial. Também passa a guardar o nome do pacote SPS em cada registro de coleção (CollectionPidV2.sps_pkg_name).

Problemas resolvidos:

  • uma falha durante o registro podia deixar o pid v2 da coleção principal gravado sem o CollectionPidV2 correspondente; _save agora executa dentro de transaction.atomic
  • um XML cuja coleção de origem (custom-meta) não está entre as coleções do periódico era aceito sem que o pid v2 e a versão daquela coleção fossem registrados; agora o registro é rejeitado com XMLCollectionNotFoundErrorToGetPidProviderXMLError
  • na falta do acrônimo do periódico na coleção, o registro da coleção falhava; agora usa o acrônimo do XML normalizado
  • OtherPid não era criado quando faltava a coleção principal (sem current_version), e o erro era descartado silenciosamente; version passa a ser opcional
  • os OtherPid passam a ser associados à versão da coleção do XML e, na falta dela, à da coleção principal
  • o erro de verificação de registro em BasePidProvider era descartado (return com valor em um gerador); agora é entregue com yield
  • FixPidV2.__str__ e autocomplete_label falhavam quando pid_provider_xml estava ausente

Funcionalidades adicionadas:

  • campo CollectionPidV2.sps_pkg_name, indexado e exibido somente para leitura no admin, preenchido a partir de current_version.xml_with_pre ao criar ou atualizar o registro
  • task task_complete_collection_pid_v2_sps_pkg_name, que preenche os registros existentes em lotes processados por subtarefas, e script pid_provider/scripts/complete_collection_pid_v2_sps_pkg_name.py para dispará-la
  • CollectionPidV2.get_or_create, que trata a criação concorrente via IntegrityError

Onde a revisão poderia começar?

pid_provider/models.py, em PidProviderXML.register (nova validação da coleção do XML e transaction.atomic em torno de _save). Em seguida, a classe CollectionPidV2 (campo sps_pkg_name e métodos de preenchimento) e pid_provider/tasks.py.

Como este poderia ser testado manualmente?

  1. Aplicar a migração: python manage.py migrate pid_provider
  2. Executar os testes: python manage.py test pid_provider article
  3. Registrar um XML de um periódico presente em mais de uma coleção e verificar, no admin, que cada CollectionPidV2 exibe o sps_pkg_name da sua versão do XML
  4. Registrar um XML cuja coleção de origem (custom-meta) não é uma das coleções do periódico e verificar que a resposta é de erro, com XMLCollectionNotFoundErrorToGetPidProviderXMLError, e que nenhum dado do documento foi alterado
  5. Executar python manage.py runscript complete_collection_pid_v2_sps_pkg_name e verificar que os CollectionPidV2 existentes com current_version tiveram sps_pkg_name preenchido

Algum cenário de contexto que queira dar?

Com a arquitetura de pid v2 por coleção, um mesmo documento pode ser registrado a partir de XMLs de coleções diferentes, cada um com seu pid v2 e sua versão. O PidProviderXML guarda o pid v2 e a versão da coleção principal, e cada coleção tem seu CollectionPidV2. Os casos corrigidos aqui deixavam esses dois níveis inconsistentes: o documento identificado, mas sem o registro da coleção de origem.

get_xml_collections retorna todas as coleções do periódico, sem filtrar pela coleção de origem do XML. É isso que permite a register detectar quando a coleção do XML não é uma das coleções do periódico.

O preenchimento de sps_pkg_name nos registros existentes exige ler o XML de cada versão, por isso é feito em lotes por subtarefas, para respeitar o limite de tempo das tarefas do celery. Após a implantação, é necessário executar o script uma vez.

Screenshots

N/A

Quais são os tickets relevantes?

complementar a #1483

Referências

N/A


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

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):

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

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)

Cria a exceção XMLCollectionNotFoundErrorToGetPidProviderXMLError para
sinalizar quando a coleção de origem informada no XML não está entre as
coleções do periódico.

Por ser subclasse de RequiredCollectionErrorToGetPidProviderXMLError, os
tratamentos existentes para falta de coleção continuam capturando o novo
caso.
O método é um gerador. O 'return' com valor encerrava a iteração e o
dicionário de erro era descartado, e o chamador não recebia nenhuma
informação da falha. Troca 'return' por 'yield'.
O registro de um XML deve gravar o pid v2 da coleção e a versão do XML
dessa coleção, ou não gravar nada. Antes, uma falha no meio do processo
podia deixar o pid v2 da coleção principal gravado sem o CollectionPidV2
correspondente. O mesmo acontecia com um XML cuja coleção de origem não
era uma das coleções do periódico: o registro era aceito sem que o pid v2
e a versão da coleção fossem gravados.

Cada CollectionPidV2 passa também a guardar o nome do pacote SPS da sua
versão do XML, permitindo localizar o documento por coleção sem ler o XML.

Detalhes de implementação:

- PidProviderXML.register: rejeita com
  XMLCollectionNotFoundErrorToGetPidProviderXMLError o XML cuja coleção
  (custom-meta) não está entre as coleções do periódico; executa _save
  dentro de transaction.atomic
- PidProviderXML.add_collections: na falta do acrônimo do periódico na
  coleção, usa o acrônimo do XML normalizado (normalize_acron)
- PidProviderXML.check_registered_pids_changed: associa os OtherPid à
  versão da coleção do XML ou, na falta dela, à da coleção principal
- OtherPid.get_or_create: version deixa de ser obrigatório, pois
  current_version fica vazio quando falta a coleção principal
- CollectionPidV2:
  - novo campo sps_pkg_name, indexado, exibido somente para leitura
  - set_sps_pkg_name: obtém o valor de current_version.xml_with_pre;
    chamado em create e create_or_update sem propagar erro
  - get_ids_to_complete_sps_pkg_name e complete_sps_pkg_name: preenchem
    os registros existentes, registrando falhas em UnexpectedEvent
  - get_or_create: obtém ou cria sem alterar o registro existente,
    tratando a concorrência via IntegrityError
  - is_equal_to e get_current_version: retornam sem consultar quando
    pid_provider_xml ainda não foi salvo
  - mensagem de erro de create_or_update lista todos os parâmetros
    obrigatórios
- FixPidV2.__str__ e autocomplete_label: não falham quando
  pid_provider_xml está ausente
Cria o campo CollectionPidV2.sps_pkg_name e o índice
pid_provide_sps_pkg_8e5c4f_idx.
Os CollectionPidV2 criados antes do novo campo ficam sem sps_pkg_name.
Como obter o valor exige ler o XML de cada versão, o preenchimento é
dividido em lotes para que cada execução termine dentro do limite de
tempo do celery.

Detalhes de implementação:

- task_complete_collection_pid_v2_sps_pkg_name: seleciona os ids a
  completar (ou todos, com force_update) e dispara uma subtarefa por lote
  de batch_size ids
- subtask_complete_collection_pid_v2_sps_pkg_name: executa
  CollectionPidV2.complete_sps_pkg_name para o lote
Substitui o teste que esperava ValueError na falta de version por um que
verifica a criação do OtherPid com version vazio.
Quando o item mais antigo não tem current_version, fix_duplicated_pkg_name
passa a criar o OtherPid sem version, em vez de descartá-lo
silenciosamente.
Configura a coleção do XML no setUp para que seja uma das coleções do
periódico e adiciona teste que verifica a resposta de erro, sem seleção
nem gravação do registro, quando a coleção do XML não é do periódico.
Verifica que o XML de uma coleção registra o pid v2 dessa coleção ou
falha sem deixar registro parcial, e que cada coleção guarda o nome do
pacote SPS da sua versão do XML.

Detalhes de implementação:

- XMLVersionByCollectionTest: sps_pkg_name igual ao de current_version
  em cada coleção; complete_sps_pkg_name restaura os valores;
  get_ids_to_complete_sps_pkg_name com e sem force_update; a task
  dispara uma subtarefa por lote
- RegisterCollectionPidV2GuaranteesTest: erro quando o periódico não
  está na coleção do XML; uso do acrônimo do XML quando falta na coleção;
  falha em CollectionPidV2.create_or_update não deixa registro parcial;
  novo registro bem-sucedido após a falha
Adiciona testes que verificam a identificação do artigo em cada coleção
a partir do registro do documento na coleção.
Adiciona testes que verificam que a migração de dados completa a coleção
dos artigos registrados antes da associação por coleção.
…ote SPS

Facilita completar o sps_pkg_name dos CollectionPidV2 já existentes
após a implantação, sem depender do agendamento de tarefas pelo admin.

Detalhes de implementação:

- script para `python manage.py runscript` que dispara
  task_complete_collection_pid_v2_sps_pkg_name, repassando usuário,
  force_update e batch_size
…do XML

Corrige a docstring de get_xml_collections, que descrevia um filtro pela
coleção de origem do XML que não corresponde ao comportamento atual.

Detalhes de implementação:

- o periódico é identificado pelos ISSNs, pelo PID do periódico contido
  no pid v2 ou pelo acrônimo
- retorna todas as coleções do periódico, com a principal primeiro, mesmo
  quando o XML informa a coleção de origem (custom-meta); a seleção da
  coleção é feita em PidProviderXML.add_collections
Quando o XML não traz a coleção de origem (custom-meta), a coleção pode
ser deduzida entre as coleções do periódico a partir dos dados do próprio
XML, desde que haja uma única candidata.

Detalhes de implementação:

- nova função get_xml_collection_acron(xml_with_pre, xml_collections)
- restringe as coleções do periódico, nesta ordem, pelo PID do periódico
  contido no pid v2 (issn_scielo) e pelo acrônimo do periódico
  normalizado; um critério sem valor ou sem correspondência é ignorado
- retorna o acron3 da coleção quando resta uma única candidata, ou None
  quando a identificação é ambígua (ex.: mesmo PID e acrônimo do
  periódico em mais de uma coleção) ou não há coleções
Antes, o XML que não informava a coleção de origem era registrado sem o
pid v2 e sem a versão do XML de nenhuma coleção. Agora a coleção é
identificada entre as coleções do periódico e o registro segue como se o
XML a informasse; se a identificação não for possível, o registro falha.

Detalhes de implementação:

- PidProviderXML.register: na falta de xml_with_pre.collection, obtém o
  acrônimo da coleção com get_xml_collection_acron e o atribui a
  xml_with_pre.collection, de modo que a versão registrada informe a
  coleção identificada
- coleção não identificada ou ambígua levanta
  RequiredCollectionErrorToGetPidProviderXMLError, com as coleções do
  periódico na mensagem
Adiciona GetXMLCollectionAcronTest, que verifica a identificação pelo
PID do periódico contido no pid v2, pelo acrônimo quando o PID é o mesmo
nas coleções ou desconhecido, o caso de coleção única e o retorno None
quando a identificação é ambígua ou não há coleções.
Substitui o teste que esperava nenhum registro de versão por testes do
novo comportamento.

Detalhes de implementação:

- coleção identificada pelo PID do periódico contido no pid v2, com a
  versão registrada informando a coleção
- XML da coleção principal passa a ser a current_version
- coleção identificada pelo acrônimo quando o PID do periódico é o mesmo
- coleção ambígua resulta em erro, sem registro de PidProviderXML,
  CollectionPidV2 ou XMLVersion
@robertatakenaka robertatakenaka changed the title Main multicollections Complementa solução de lidar com xml de artigos publicados em mais de uma coleção Oct 28, 2026
@robertatakenaka robertatakenaka changed the title Complementa solução de lidar com xml de artigos publicados em mais de uma coleção Garante o registro do documento na coleção de origem do XML e guarda o nome do pacote SPS por coleção Oct 28, 2026
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.

2 participants