Divide task dispatch articles em duas task dispatch articles e task harvest articles - #1460
Open
robertatakenaka wants to merge 11 commits into
Conversation
robertatakenaka
force-pushed
the
divide_task_dispatch_articles_em_duas_task_dispatch_articles_e_task_harvest_articles
branch
from
July 29, 2026 13:03
0830753 to
ac10d72
Compare
#### Propósito Deixar explícito o significado de cada status de PidProviderXML e oferecer agrupamentos reutilizáveis para os filtros do pipeline de artigos. #### Solução técnica - Adicionado comentário explicativo a cada constante PPXML_STATUS_*. - Criadas as listas PPXML_STATUS_TO_CREATE_OR_UPDATE_ARTICLE_SOURCE e PPXML_STATUS_TO_IGNORE, consumidas por ArticleIteratorBuilder.from_article_source em article/controller.py.
…ovider #### Propósito Remover a dependência de ArticleSource no modelo legado AMArticle e tornar o fluxo de obtenção de XML/PID mais direto, com menos logging redundante e menos chamadas save() implícitas. #### Solução técnica - Substituído o FK am_article por pid (CharField) e collection (FK para Collection) em ArticleSource. - create/create_or_update reescritos para usar pid/collection/detail; extraído o método update() que aplica mudanças incrementais e informa se algo mudou. - add_pid_provider reestruturado com try/except mais enxuto: retorna bool `changed`, delega erros a mark_as_xml_error/mark_as_url_error/ mark_as_error e evita salvar o objeto múltiplas vezes. - request_xml e request_pid simplificados; erros de PID agora levantam UnableToRegisterPIDError diretamente, sem lista `detail` acumulada manualmente. - Adicionados ArticleSource.get_pid_provider_xml_id() e a propriedade ContribPerson.data. - Import ajustado para `from pid_provider import choices as pid_provider_choices` e removidos logging.info/logging.exception de baixo valor ao longo do arquivo.
…eSource #### Propósito Persistir no banco de dados as alterações do modelo ArticleSource: remoção do FK am_article e inclusão dos campos pid e collection. #### Solução técnica Migração gerada automaticamente (makemigrations) refletindo as mudanças já aplicadas em article/models.py: RemoveField(am_article), AddField(pid), AddField(collection) com FK para Collection.
…ource #### Propósito Refletir no admin/Wagtail a remoção do FK am_article e a introdução dos campos pid/collection em ArticleSource. #### Solução técnica Substituído am_article por url/pid/collection em list_display, list_filter e search_fields de ArticleSourceSnippetViewSet.
…ryset vazio #### Propósito Uma consulta sem resultados não é necessariamente um erro; registrar UnexpectedEvent para esse caso gerava ruído desnecessário. #### Solução técnica - Removida a criação de UnexpectedEvent.create quando o queryset filtrado vem vazio em Journal.select_items. - Journal.get_ids ajustado para encadear select_items().values_list() diretamente, sem variável intermediária.
…radores
#### Propósito
O antigo __iter__ disparava todos os iteradores simultaneamente, permitindo
que o mesmo artigo/pp_xml_id fosse selecionado por mais de uma fonte na
mesma execução. É preciso que quem chama escolha explicitamente uma fonte.
#### Solução técnica
- Removido __iter__; __init__ mantém apenas os filtros comuns a mais de
uma fonte (usuário, coleção/periódico, datas/anos, force_update,
parâmetros de harvest).
- Métodos privados _iter_from_* convertidos em métodos públicos from_*,
cada um recebendo como parâmetro o filtro exclusivo da sua fonte
(proc_status_list, data_status_list, article_source_status_list).
- from_pid_provider reescrito para resolver ISSNs via SciELOJournal e
retornar apenas dicts prontos via values(pp_xml_id=F("id")).distinct(),
sem instanciar os objetos completos.
- from_article_source e from_harvest movidos para o builder (antes viviam
em ArticleSource/Collection), com a mesma otimização via values().
- Removidos os contadores internos (_iter_from_*_count) e logging.info
intermediário.
- export_article_to_articlemeta passa a levantar ValueError quando não há
legacy_keys, em vez de registrar UnexpectedEvent e retornar silenciosamente.
- Corrigido bug: uso de pub_year trocado por pub_date_year em
bulk_export_articles_to_articlemeta.
- Removido bloco de código comentado (get_pp_xml_ids/select_pp_xml).
#### Propósito Cobrir com testes o novo comportamento de ArticleIteratorBuilder após a remoção do __iter__ único e a introdução dos métodos from_pid_provider, from_article, from_article_source e from_harvest, garantindo que cada fonte seja testada isoladamente e não haja sobreposição de seleção. #### Solução técnica Suite baseada em unittest com mocks (unittest.mock) para isolar consultas ao banco/Journal/SciELOJournal/PidProviderXML/ArticleSource, cobrindo: - filtros aplicados por from_pid_provider (ISSNs, datas, status); - comportamento de from_article com/sem pp_xml existente; - filtros de status em from_article_source, incluindo o caso force_update; - montagem de kwargs em from_harvest via harvester mockado. Supressão de ruído de logging do OpenSearch configurada no setUp para manter a saída de testes limpa.
…orBuilder #### Propósito Separar o fluxo de harvest (coleta externa via OPAC/ArticleMeta) do fluxo de despacho das fontes internas pendentes (article_source, pid_provider, article), e ajustar as tasks ao novo builder com métodos from_* explícitos. #### Solução técnica - Nova task task_harvest_articles, isolando builder.from_harvest(). - task_dispatch_articles reescrita para iterar sequencialmente from_article_source, from_pid_provider e from_article; parâmetros de harvest (limit/timeout/opac_url/stop) removidos dessa task, pois agora pertencem só a task_harvest_articles. - task_process_article_pipeline ajustada: não depende mais de AMArticle.create_or_update; ArticleSource.create_or_update passa a receber collection/pid/detail; pp_xml_id obtido via article_source.get_pid_provider_xml_id(). - Removido parâmetro `item` indevido em UnexpectedEvent.create de task_export_article_to_articlemeta e diversos logging.info de baixo valor.
…correlatas #### Propósito Validar os três fluxos de entrada do pipeline (xml_url, article_source_id, pp_xml_id) após a reescrita de task_process_article_pipeline, e cobrir task_harvest_articles e a nova task_dispatch_articles sequencial. #### Solução técnica Testes com unittest.mock isolando ArticleSource.create_or_update, PidProviderXML.get_by_id, Article.get_or_create e as chamadas task_export_article_to_articlemeta.delay/task_process_article_pipeline.delay, verificando: - levantamento de ValueError quando faltam collection_acron/pid com xml_url; - obtenção correta de pp_xml_id via article_source.get_pid_provider_xml_id(); - que export_to_articlemeta só dispara quando article.is_classic_public e article.valid são verdadeiros; - que task_dispatch_articles percorre article_source, pid_provider e article sem duplicar despachos; - registro de UnexpectedEvent em caso de exceção nas tasks. Logging do OpenSearch suprimido no setUp para reduzir ruído nos testes.
…ticles #### Propósito Registrar o agendamento da nova task_harvest_articles e ajustar task_dispatch_articles ao novo conjunto de parâmetros, além de limpar tasks obsoletas do scheduler. #### Solução técnica - Adicionada schedule_task_harvest_articles (cron diário às 02:01). - schedule_task_dispatch_articles ajustada para os novos kwargs (article_source_status_list/proc_status_list/data_status_list, sem limit/timeout/opac_url) e horário movido para 02:16. - Incluídas na lista de tasks a remover: task_dispatch_articles antiga e as variantes por fonte (task_dispatch_articles_from_pid_provider, _from_article, _from_article_source), substituídas pelas duas tasks especializadas.
…or url
#### Propósito
1. Refletir no painel Wagtail de ArticleSource a remoção do FK am_article,
exibindo collection e pid em seu lugar.
2. Simplificar ArticleAvailability.get, já que url é único (unique=True)
e por si só já identifica o registro, tornando o parâmetro article
redundante.
#### Solução técnica
- panels de ArticleSource: substituído FieldPanel("am_article", read_only=True)
por FieldPanel("collection", read_only=True) e FieldPanel("pid", read_only=True).
- ArticleAvailability.get(cls, url) agora recebe apenas url; create() e
create_or_update() ajustados para chamar cls.get(url) sem o argumento
article, aproveitando o índice único já existente em url.
robertatakenaka
force-pushed
the
divide_task_dispatch_articles_em_duas_task_dispatch_articles_e_task_harvest_articles
branch
from
July 30, 2026 13:42
ac10d72 to
97b2303
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
O que esse PR faz?
Refatora o pipeline de seleção e processamento de artigos:
ArticleIteratorBuilder(article/controller.py), removendo o__iter__único e substituindo por métodos explícitosfrom_pid_provider,from_article,from_article_sourceefrom_harvest, cada um recebendoo filtro exclusivo da sua fonte.
ArticleSourcedo modelo legadoAMArticle: remove o FKam_articlee adiciona os campospidecollection(article/models.pyadd_pid_provider/request_xml/request_pid, reduzindologging redundante e centralizando o tratamento de erro.
task_dispatch_articlesem duas tasks:task_harvest_articles(coleta externa via OPAC/ArticleMeta) e
task_dispatch_articles(despacho sequencial de article_source → pid_provider → article).
article/wagtail_hooks.pyaos novos campos deArticleSource.bigbang/tasks_scheduler.pypara agendar as novas tasks eremover as obsoletas.
Journal.select_items(journal/models.py), removendo oregistro de
UnexpectedEventpara queryset vazio.PidProviderXMLempid_provider/choices.py.test_article_iterator_builder.pyetest_article_pipeline.py, com mocks (unittest.mock) e supressão delogging do OpenSearch.
Onde a revisão poderia começar?
Sugiro começar por
article/controller.py(oArticleIteratorBuilderreescrito), depois
article/models.py(mudanças emArticleSource), epor fim
article/tasks.pypara ver como as novas tasks consomem o builder.Os testes em
article/tests/ajudam a entender o comportamento esperadode cada método.
Como este poderia ser testado manualmente?
0050_remove_articlesource_am_article_and_moreemambiente de homologação e conferir que os dados existentes de
ArticleSourcenão foram perdidos (verificarpid/collectionpreenchidos onde aplicável).
task_harvest_articlesmanualmente com uma coleção pequena econfirmar que os documentos coletados disparam
task_process_article_pipelinecorretamente.task_dispatch_articlese verificar nos logs/Flower que cadaartigo é despachado uma única vez, mesmo quando elegível por mais de
uma fonte (article_source, pid_provider, article).
make django_bashpython manage.py test article.tests --keepdbArticleSourceSnippetViewSet) que ascolunas e filtros exibem
pid/collectionno lugar deam_article.Algum cenário de contexto que queira dar?
Esta é uma refatoração estrutural sem mudança de escopo funcional externo
esperado — o objetivo é eliminar duplicidade de processamento e reduzir
acoplamento com
AMArticle. A migração remove um FK, então é importantevalidar em homologação antes de subir para produção. Nenhuma nova
dependência externa foi introduzida.
Screenshots
N/A (mudanças de backend/pipeline, sem impacto visual além do admin
listado acima).
Quais são os tickets relevantes?
vinculada acima).
Referências
Segurança da informação (NSI.04)
Seção obrigatória, referência NSI.04 - Norma de Desenvolvimento Seguro.
Manipula dados sensíveis/pessoais (LGPD)?
[ ] Sim [x] Não
N/A — os campos alterados (
pid,collection) são identificadoresbibliográficos/institucionais, não dados pessoais.
Altera autenticação, autorização, controle de acesso ou sessão?
[ ] Sim [x] Não
Introduz/atualiza/remove dependências de terceiros?
[ ] Sim [x] Não
Nenhuma dependência de terceiros foi adicionada, atualizada ou removida.
Validado pelo pipeline de segurança (SonarQube/Trivy)?
[ ] Sim [ ] Não — justificar
Link do job: (preencher com o link do pipeline após execução)
Concatena/monta/executa comandos SQL, HTML ou JS a partir de entrada externa?
[ ] Sim [x] Não
Todas as consultas usam o ORM do Django (filtros via
Q/Fe kwargs),sem SQL bruto ou interpolação de entrada externa.
Expõe novos endpoints, telas ou serviços?
[ ] Sim [x] Não
Não há novos endpoints; apenas ajuste de colunas/filtros no admin
Wagtail existente (
ArticleSourceSnippetViewSet).Algum segredo/senha/chave/token adicionado ao código-fonte?
[ ] Sim [x] Não