Skip to content

Reduzir consultas e conexões ao banco de dados#1410

Merged
robertatakenaka merged 26 commits intoscieloorg:mainfrom
robertatakenaka:fechar_conexoes_banco_de_dados
Mar 17, 2026
Merged

Reduzir consultas e conexões ao banco de dados#1410
robertatakenaka merged 26 commits intoscieloorg:mainfrom
robertatakenaka:fechar_conexoes_banco_de_dados

Conversation

@robertatakenaka
Copy link
Copy Markdown
Member

O que esse PR faz?

Aplica um conjunto de otimizações para reduzir o número de queries ao banco de dados, eliminar saves desnecessários e diminuir a pressão sobre conexões PostgreSQL em produção.

As mudanças se organizam em cinco frentes:

1. Eliminação de N+1 queries no admin Wagtail
Adiciona select_related nos métodos get_queryset dos SnippetViewSet de Location, Issue, License, GenericThematicArea, ThematicArea e seus arquivos associados. Sem isso, listar N registros no admin disparava uma query extra por linha para resolver FKs como creator, updated_by, journal e country.

2. Eliminação de N+1 queries em models e tasks
Adiciona select_related em métodos que iteravam querysets sem JOIN: Journal.collection_acrons, Journal.get_ids, Journal.get_legacy_keys, PidProviderXML.public_items, PidProviderXML.best_matches e na task de migração de organization. Adiciona prefetch_related('researcheraka_set__researcher_identifier') na task de migração de researchers.

3. Redução de queries pontuais

  • Substitui loops com break por .filter().first() em OfficialJournal.add_old_title/add_new_title e CountryName.get_country
  • Substitui loops por values_list(..., flat=True).first() nas properties orcid e lattes de Researcher, projetando apenas a coluna necessária com LIMIT 1
  • Substitui duplo get/except + save por update_or_create em JournalHistory.load
  • Move User.objects.get() para fora do loop em bulk_cities.py, eliminando N queries durante importação CSV
  • Adiciona select_related('journal', 'journal__official', 'pp_xml') no iterator de bulk_export_articles_to_articlemeta

4. Eliminação de saves desnecessários
Introduz flag changed antes de chamar save() nos métodos create_or_update de Institution, InstitutionIdentification, State, CountryName e Country: o UPDATE só é emitido quando há mudança efetiva de valor. Refatora Organization.update_logo/update_url para retornar bool e consolidar o save() no chamador. Consolida saves internos em PidProviderXML e XMLVersion, delegando o save final ao chamador.

5. Redução de pressão sobre conexões PostgreSQL

  • CONN_MAX_AGE=60: reutiliza conexões abertas pelo worker por até 60 segundos, evitando abrir/fechar conexão a cada request
  • CONN_HEALTH_CHECKS=True: valida a conexão reutilizada antes de usá-la
  • Remove POOL_OPTIONS: incompatível com django-prometheus e estava sendo ignorado
  • SESSION_ENGINE=cache + SESSION_CACHE_ALIAS=default: migra sessões do PostgreSQL para o Redis, reduzindo writes no banco com SESSION_SAVE_EVERY_REQUEST=True
  • Comenta CELERY_RESULT_BACKEND='django-db': evita writes de resultado de task no PostgreSQL; Redis já é o backend configurado
  • CELERY_WORKER_MAX_TASKS_PER_CHILD=100: recicla workers após 100 tarefas, liberando conexões acumuladas

6. Consolidação de _get_user
Remove definições locais de _get_user duplicadas em bigbang/tasks.py, pid_provider/tasks.py e tracker/tasks.py. Todas passam a importar de core.utils.utils, onde a função foi corrigida para priorizar request.user autenticado antes de consultar o banco por user_id ou username.

7. Correção de bug em collection/tasks.py
Substitui if/if por if/elif/else em task_load_collections, evitando reatribuição silenciosa de user quando ambos user_id e username são fornecidos. Adiciona ValueError explícito quando nenhum dos dois é passado.


Onde a revisão poderia começar?

  • core/utils/utils.py — nova assinatura de _get_user e lógica de prioridade de autenticação
  • journal/models.pyadd_new_title remove o self.save() interno; verificar se todos os chamadores existentes salvam o objeto após chamar o método
  • organization/models.pyupdate_institutions passa a retornar bool; verificar chamadores externos ao módulo
  • pid_provider/models.py — consolidação de saves em _add_current_version e _add_other_pid; o save final está em _save() do objeto pai
  • config/settings/production.py — mudanças de SESSION_ENGINE e remoção de POOL_OPTIONS requerem atenção em deploy

Como este poderia ser testado manualmente?

  1. Ativar o Django Debug Toolbar (ou django-silk) e navegar pelas listagens do admin Wagtail para Location, Issue, License e ThematicArea — o número de queries por página deve cair visivelmente
  2. Executar bulk_export_articles_to_articlemeta com um queryset de ~500 artigos e comparar o tempo de execução e número de queries antes/depois
  3. Executar a task migrate_old_researcher_to_new_researcher e verificar via logs que não há queries repetidas por researcher
  4. Chamar task_load_collections sem user_id e sem username e confirmar que ValueError é levantado
  5. Em produção (staging), monitorar o número de conexões ativas no PostgreSQL via pg_stat_activity antes e depois do deploy — espera-se redução com CONN_MAX_AGE=60 e sessões no Redis
  6. Verificar no Redis que as chaves de sessão (django.contrib.sessions) estão sendo criadas após o deploy

Algum cenário de contexto que queira dar?

O conjunto de mudanças foi motivado por pressão crescente de conexões no PostgreSQL em produção, especialmente durante execuções concorrentes de tasks Celery que iteravam querysets grandes sem select_related. O admin Wagtail com listagens de centenas de registros também gerava picos de queries observados via monitoramento.

A remoção de POOL_OPTIONS é necessária porque o backend django-prometheus não é compatível com o pooling nativo do Django, fazendo as opções serem silenciosamente ignoradas. A estratégia adotada é CONN_MAX_AGE por worker, que é compatível e suficiente para o perfil de carga atual.

⚠️ Atenção no deploy: a mudança de SESSION_ENGINE invalida sessões existentes armazenadas no PostgreSQL. Usuários autenticados serão desconectados na primeira request após o deploy.


Screenshots

N/A — mudanças de backend sem alteração de interface


Quais são tickets relevantes?

Adicionar referências aos tickets correspondentes


Referências

…s de ambiente

- CELERY_TASK_TIME_LIMIT: hard limit configurável via env (default 36000s)
- CELERY_TASK_SOFT_TIME_LIMIT: soft limit configurável via env (default 3600s)
- Adiciona CELERY_WORKER_MAX_TASKS_PER_CHILD para reciclagem de workers (default 100)
- Adiciona CELERY_WORKER_CONCURRENCY configurável via env (default 4)
- Comenta CELERY_RESULT_BACKEND='django-db'; resultado já persiste via Redis
- Simplifica CONN_MAX_AGE para 60s fixo via env (remove variável duplicada)
- Remove POOL_OPTIONS (incompatível com django-prometheus backend)
- Migra SESSION_ENGINE para cache Redis (SESSION_ENGINE + SESSION_CACHE_ALIAS)
- Reduz escritas no PostgreSQL a cada request com SESSION_SAVE_EVERY_REQUEST=True
…ponível

- Prioriza request.user.is_authenticated antes de consultar o banco
- Fallback para user_id e username quando request não tem usuário autenticado
- Remove acesso incorreto a request.user_id (AttributeError silencioso anterior)
- Atribui request.user.collection.all() a variável local antes de reutilizar
- Elimina segunda query duplicada para set_current_collections e request.user_collection
- Evita N+1 queries ao listar licenças no admin Wagtail
…alores antes de persistir

- State.create_or_update: salva apenas se name ou acronym mudaram
- CountryName.create_or_update: salva apenas se country, language ou text mudaram
- Country.create_or_update: salva apenas se name, acronym ou acron3 mudaram
- CountryName.get_country: substitui loop por .filter(country__isnull=False).select_related().first()
- User.objects.get(id=user_id) executado uma única vez antes de iterar o CSV
- Elimina N queries redundantes ao banco durante importação em massa
- Inclui country, state, city e creator para evitar N+1 no admin Wagtail
…o valores antes de persistir

- Institution.create_or_update: salva apenas se institution_type ou url mudaram
- InstitutionIdentification.create_or_update: salva apenas se is_official ou official mudaram
- Garante que updated_by só é gravado quando há mudança efetiva
…nsolidar saves

- update_logo e update_url retornam True/False sem chamar save() internamente
- create_or_update chama save() uma única vez se logo ou url mudaram
- update_institutions retorna bool; create_or_update chama save() apenas se houve mudança
- Organization.update_institutions remove save() interno; responsabilidade delegada ao chamador
…__official em task de migração

- Evita query extra ao acessar official durante migração de Institution para Organization
…em JournalHistory

- OfficialJournal.add_old_title/add_new_title: substitui loop por .filter().first()
- add_old_title: remove self.save() após M2M .add() (desnecessário)
- add_new_title: remove self.save(); responsabilidade delegada ao chamador
- Journal.collection_acrons: substitui loop por values_list com select_related
- Journal.get_ids / get_legacy_keys: adiciona select_related('collection') nos filtros
- JournalHistory.load: substitui get/except+save duplo por update_or_create para ADMITTED e INTERRUPTED
…de IssueAdminSnippetViewSet

- Evita N+1 queries ao listar issues no admin Wagtail
…orcid e lattes

- Elimina iteração desnecessária; retorna diretamente o primeiro identifier encontrado
- Remove acesso ao atributo do objeto relacionado; usa projeção via values_list
…gração

- Adiciona select_related('affiliation__institution__location')
- Adiciona prefetch_related('researcheraka_set__researcher_identifier')
- Reduz queries N+1 ao acessar location e identifiers durante migração
…ueries extras

- XMLVersion.get_or_create: documenta fluxo de 3 saves (pk → arquivo → consolidação)
- PidProviderXML.public_items: adiciona select_related('current_version')
- PidProviderXML._add_current_version: remove save() interno; delegado ao chamador
- PidProviderXML._add_other_pid: remove save() interno; delegado ao chamador
- PidProviderXML._save: adiciona save() consolidado após _add_current_version/_add_other_pid
- best_matches: adiciona select_related('current_version') no iterator
- Elimina duplicação de _get_user em pid_provider/tasks.py
- Importa _get_user centralizado de core.utils.utils
- Elimina definição local de _get_user em tracker/tasks.py
- Função centralizada já disponível em core.utils.utils
- Elimina definição local de _get_user
- Atualiza chamadas para assinatura _get_user(request=None, user_id=..., username=...)
- Importa _get_user centralizado de core.utils.utils
…_collections

- Substitui if/if por if/elif para evitar reatribuição silenciosa de user
- Levanta ValueError explícito quando nem user_id nem username são fornecidos
…e_ebm

- Atribui request.user a user antes do loop para evitar acesso repetido ao objeto request
- Padroniza uso de user nas chamadas a create_or_update dentro do loop
…SnippetViewSets

- GenericThematicAreaAdmin, GenericThematicAreaFileAdmin
- ThematicAreaAdmin, ThematicAreaFileAdmin
- Evita N+1 queries ao listar registros no admin Wagtail
…to_articlemeta

- Inclui journal, journal__official e pp_xml para evitar N+1 durante exportação em massa
Copilot AI review requested due to automatic review settings March 17, 2026 16:54
@robertatakenaka robertatakenaka changed the title Fechar conexoes banco de dados Reduzir consultas e conexões ao banco de dados Mar 17, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Este PR reúne otimizações para reduzir volume de queries e writes no PostgreSQL (principalmente em listagens do Wagtail admin e em tasks Celery), além de ajustes de settings de produção para diminuir a pressão de conexões e mover sessões para Redis.

Changes:

  • Otimiza querysets (principalmente via select_related/prefetch_related) em múltiplos SnippetViewSets, models e tasks para eliminar N+1.
  • Reduz saves/updates desnecessários (flags de “changed”, consolidação de saves e refactors para evitar save() interno).
  • Ajusta settings operacionais (CONN_MAX_AGE/health checks, sessão via cache/Redis, parâmetros Celery) e consolida _get_user() em core.utils.utils.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tracker/tasks.py Remove helper _get_user duplicado (não utilizado no arquivo).
thematic_areas/wagtail_hooks.py Adiciona select_related("creator") nos querysets do admin para reduzir N+1.
researcher/tasks.py Adiciona select_related/prefetch_related para reduzir queries na migração.
researcher/models.py Otimiza orcid/lattes com values_list(...).first() evitando loops.
pid_provider/tasks.py Importa _get_user centralizado em vez de função local duplicada.
pid_provider/models.py Consolida saves e adiciona select_related("current_version") para reduzir N+1 (há pontos com save redundante).
organization/tasks.py Expande select_related para evitar queries adicionais em migração.
organization/models.py Evita saves internos; refatora helpers para retornarem “changed” e salvar apenas uma vez.
location/wagtail_hooks.py Adiciona select_related no admin de Location para evitar N+1 em FKs.
location/scripts/bulk_cities.py Move lookup de usuário para fora do loop para evitar N queries.
location/models.py Evita save() quando não há mudança real; otimiza get_country com .first().
journal/models.py Troca loops por .first(), otimiza acesso a coleções e usa update_or_create em histórico.
issue/wagtail_hooks.py Inclui creator/updated_by em select_related para reduzir N+1 no admin.
institution/models.py Evita save() quando não há mudança real em create_or_update.
editorialboard/views.py Evita acessos repetidos a request.user dentro do loop de importação.
core/wagtail_hooks.py Otimiza admin de License com select_related("creator").
core/utils/utils.py Atualiza _get_user para priorizar request.user autenticado antes de buscar no banco.
core/middleware.py Reutiliza o mesmo queryset de coleções do usuário no middleware (evita re-fetch).
config/settings/production.py Ajusta CONN_MAX_AGE/health checks, remove POOL_OPTIONS e move sessões para cache/Redis.
config/settings/base.py Ajusta time limits do Celery e configurações de reciclagem/concurrency; evita “django-db” como backend de results.
collection/tasks.py Corrige fluxo user_id vs username e adiciona erro explícito quando nenhum é fornecido.
bigbang/tasks.py Passa a usar _get_user centralizado com a nova assinatura.
article/controller.py Adiciona select_related no iterator do bulk export para reduzir queries por artigo.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 143 to 147
obj.save_file(
f"{pid_provider_xml.v3}.xml", xml_with_pre.tostring(pretty_print=True)
)
# Único save final após salvar o arquivo
obj.save()
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Este PR aplica otimizações transversais para reduzir consultas ao PostgreSQL (especialmente N+1 em admin/tasks), evitar save()/UPDATE desnecessários e ajustar configurações de produção para diminuir pressão de conexão e writes no banco.

Changes:

  • Adiciona select_related/values_list(...).first()/update_or_create em pontos quentes (admin Wagtail, tasks e models) para reduzir N+1 e queries pontuais.
  • Refatora métodos create_or_update/helpers para só persistirem quando houver mudança real, consolidando saves no chamador.
  • Ajusta settings (produção e base) para reduzir pressão no PostgreSQL (CONN_MAX_AGE, sessões em cache/Redis, backend de resultado Celery) e consolida _get_user em core.utils.utils.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tracker/tasks.py Remove helper _get_user duplicado em tasks do app tracker.
thematic_areas/wagtail_hooks.py Otimiza queryset do admin Wagtail com select_related("creator").
researcher/tasks.py Otimiza queryset da migração de pesquisadores com select_related/prefetch_related.
researcher/models.py Troca loop por values_list(...).first() em properties (orcid/lattes).
pid_provider/tasks.py Consolida uso de _get_user via import único de core.utils.utils.
pid_provider/models.py Reduz N+1 com select_related e consolida persistência/saves em _save e versões XML.
organization/tasks.py Aumenta select_related em task de migração para evitar N+1 em FK encadeada.
organization/models.py Elimina saves internos em helpers e retorna flags para consolidar persistência no chamador.
location/wagtail_hooks.py Otimiza listagem do admin Wagtail de Location com select_related.
location/scripts/bulk_cities.py Move lookup de User para fora do loop para evitar queries repetidas.
location/models.py Evita save() quando não há mudança e reduz query em CountryName.get_country.
journal/models.py Reduz queries em títulos/coleções e troca get+except+save por update_or_create.
issue/wagtail_hooks.py Otimiza queryset do admin Wagtail de Issue com select_related (creator/updated_by).
institution/models.py Evita save() quando não há mudança em create_or_update.
editorialboard/views.py Evita acesso repetido a request.user dentro do loop de importação.
core/wagtail_hooks.py Otimiza queryset do admin Wagtail de License com select_related("creator").
core/utils/utils.py Corrige e padroniza _get_user (prioriza request.user autenticado).
core/middleware.py Reusa queryset de coleções do usuário para evitar chamadas duplicadas.
config/settings/production.py Ajusta conexões persistentes, remove pooling e move sessões para cache/Redis em produção.
config/settings/base.py Ajusta limites/config do Celery (time limits, reciclagem e concorrência) e mantém result backend em Redis.
collection/tasks.py Corrige lógica de seleção de usuário (if/elif/else) e adiciona erro explícito quando ausente.
bigbang/tasks.py Consolida _get_user via util compartilhado.
article/controller.py Otimiza export em massa com select_related antes do .iterator().
Comments suppressed due to low confidence (1)

researcher/tasks.py:33

  • prefetch_related("researcheraka_set__researcher_identifier") não evita as queries dentro do loop porque o código usa old_researcher.researcheraka_set.filter(...).first(), e .filter() não usa o cache do prefetch (tende a executar uma query por researcher). Para realmente eliminar o N+1, ou remova este prefetch, ou refatore para consumir o conjunto prefetched em memória (ex.: iterar/next(...)) ou use Prefetch(..., to_attr=...) com queryset já filtrado por ORCID.
    ).prefetch_related(
        "researcheraka_set__researcher_identifier",
    )
    for old_researcher in old_researchers:
        orcid = (
            old_researcher.researcheraka_set.filter(
                researcher_identifier__source_name__iexact="ORCID"

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 143 to 147
obj.save_file(
f"{pid_provider_xml.v3}.xml", xml_with_pre.tostring(pretty_print=True)
)
# Único save final após salvar o arquivo
obj.save()
tracker/tasks.py Outdated
@@ -12,16 +12,6 @@
User = get_user_model()
@@ -26,21 +27,14 @@
User = get_user_model()
DATABASES["default"]["CONN_MAX_AGE"] = env.int("CONN_MAX_AGE", default=0) or env.int("DJANGO_CONN_MAX_AGE", default=60) # noqa F405
# Reutilizar conexões por 60s por padrão para reduzir overhead de reconexão.
# Em produção com gunicorn+gevent ou Celery, isto evita abrir/fechar conexão a cada request.
DATABASES["default"]["CONN_MAX_AGE"] = env.int("CONN_MAX_AGE", default=60) # noqa F405
Comment on lines +377 to +383
# Hard time limit: o worker é terminado (SIGKILL) após este tempo.
# Deve ser MAIOR que o soft time limit.
CELERY_TASK_TIME_LIMIT = env.int('CELERY_TASK_TIME_LIMIT', default=36000)
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#task-soft-time-limit
# TODO: set to whatever value is adequate in your circumstances
CELERY_TASK_SOFT_TIME_LIMIT = 36000
# Soft time limit: levanta SoftTimeLimitExceeded, permitindo cleanup.
# Deve ser MENOR que o hard time limit.
CELERY_TASK_SOFT_TIME_LIMIT = env.int('CELERY_TASK_SOFT_TIME_LIMIT', default=3600)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

O PR aplica um conjunto amplo de otimizações para reduzir consultas ao banco (evitando N+1), eliminar save()/UPDATEs desnecessários e ajustar configurações para reduzir pressão de conexões PostgreSQL em produção.

Changes:

  • Otimizações de querysets (principalmente select_related/prefetch_related) em admin Wagtail, tasks e fluxos de exportação/importação.
  • Refactors para reduzir gravações redundantes (consolidação de save() e flags de “changed”) em vários models.
  • Ajustes operacionais em settings (persistent connections, sessions no Redis, tuning do Celery) e consolidação do helper _get_user.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tracker/tasks.py Remove helper _get_user local; ajustes correlatos na task.
thematic_areas/wagtail_hooks.py Adiciona get_queryset() com select_related("creator") para reduzir N+1 no admin.
researcher/tasks.py Adiciona select_related/prefetch_related para reduzir queries na migração de researchers.
researcher/models.py Troca loop por values_list(...).first() nas properties orcid/lattes.
pid_provider/tasks.py Consolida import de _get_user (mas introduz duplicação crítica de task).
pid_provider/models.py Ajusta save()/select_related e consolida persistência em fluxos de versão/other pid.
organization/tasks.py Amplia select_related em task de migração para evitar N+1.
organization/models.py Refatora updates (logo/url/instituições) para evitar save() desnecessário.
location/wagtail_hooks.py Adiciona select_related no queryset do admin de Location.
location/scripts/bulk_cities.py Move busca do usuário para fora do loop para evitar N queries.
location/models.py Introduz flag changed e otimiza get_country() com .first() + select_related.
journal/models.py Remove save() redundante em M2M, otimiza lookups e usa update_or_create.
issue/wagtail_hooks.py Adiciona select_related("creator","updated_by") para reduzir N+1.
institution/models.py Introduz flag changed para evitar UPDATEs quando não há alteração real.
editorialboard/views.py Reusa request.user dentro do loop para evitar acessos repetidos.
core/wagtail_hooks.py Otimiza queryset do admin de License com select_related("creator").
core/utils/utils.py Consolida _get_user priorizando request.user autenticado.
core/middleware.py Reusa queryset de coleções do usuário para evitar queries duplicadas.
config/settings/production.py Ajusta conexões persistentes e migra sessions para cache (Redis).
config/settings/base.py Ajusta time limits e parâmetros do Celery; evita backend django-db para resultados.
collection/tasks.py Corrige lógica de seleção do usuário (if/elif/else) e validação explícita.
bigbang/tasks.py Passa a usar _get_user centralizado.
article/controller.py Adiciona select_related no iterator do bulk export para reduzir N+1.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 143 to 147
obj.save_file(
f"{pid_provider_xml.v3}.xml", xml_with_pre.tostring(pretty_print=True)
)
# Único save final após salvar o arquivo
obj.save()
@robertatakenaka
Copy link
Copy Markdown
Member Author

@copilot open a new pull request to apply changes based on the comments in this thread

1 similar comment
@robertatakenaka
Copy link
Copy Markdown
Member Author

@copilot open a new pull request to apply changes based on the comments in this thread

):
try:
user = _get_user(user_id, username)
user = _get_user(request=None, user_id=user_id, username=username)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot trocar request=None por request=self.request

def task_create_tasks(self, user_id=None, username=None, tasks_data=None):
if not tasks_data:
user = _get_user(user_id, username)
user = _get_user(request=None, user_id=user_id, username=username)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot trocar request=None por request=self.request

elif username:
user = User.objects.get(username=username)
else:
raise ValueError("user_id or username is required")
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot obtenha o usuário conforme foi feito em outras tarefas com from core.utils.utils import _get_user

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Conjunto de otimizações para reduzir o volume de queries e writes no PostgreSQL (N+1 em admin/tasks/iteradores, eliminação de saves redundantes) e diminuir pressão de conexões em produção (reuso de conexão, sessão em Redis, ajustes de Celery), além de consolidar _get_user em um ponto único.

Changes:

  • Otimiza querysets (principalmente com select_related/prefetch_related) em Wagtail admin, tasks e rotinas de exportação/migração.
  • Reduz writes desnecessários ao consolidar save() no chamador e evitar updates quando não há mudança efetiva.
  • Ajusta configurações (produção/base) para reduzir pressão no PostgreSQL (CONN_MAX_AGE, sessions em cache/Redis, settings de Celery) e remove _get_user duplicado.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tracker/tasks.py Remove _get_user duplicado e simplifica assinatura da task de limpeza.
thematic_areas/wagtail_hooks.py Adiciona select_related("creator") para evitar N+1 nas listagens do admin.
researcher/tasks.py Adiciona select_related/prefetch_related para migração de researchers.
researcher/models.py Otimiza properties orcid/lattes com values_list(...).first() para reduzir carga e colunas lidas.
pid_provider/tasks.py Passa a importar _get_user de core.utils.utils (remoção de duplicação).
pid_provider/models.py Otimiza consultas (ex.: select_related("current_version")) e consolida saves no fluxo de registro/versões.
organization/tasks.py Adiciona select_related adicional para reduzir queries durante migração.
organization/models.py Refatora updates de logo/url e consolida save() no chamador; update_institutions retorna bool.
location/wagtail_hooks.py Adiciona select_related no queryset do admin para evitar N+1 (country/state/city/creator).
location/scripts/bulk_cities.py Evita User.objects.get() dentro do loop (remove N queries).
location/models.py Evita save() quando não houve mudança e otimiza busca de país por nome.
journal/models.py Remove loops desnecessários, reduz saves, e evita N+1 ao acessar coleções/legacy keys.
issue/wagtail_hooks.py Adiciona select_related para creator/updated_by no queryset do admin.
institution/models.py Evita save() quando não houve mudança em create_or_update.
editorialboard/views.py Reusa request.user fora do loop para evitar acessos repetidos.
core/wagtail_hooks.py Adiciona select_related("creator") no queryset do admin de License.
core/utils/utils.py Consolida/ajusta _get_user para priorizar request.user autenticado antes de queries.
core/middleware.py Reusa o mesmo QuerySet de collections para evitar duplicação e potencial requery.
config/settings/production.py Ajusta conexões do DB (CONN_MAX_AGE/health checks) e move sessões para cache (Redis).
config/settings/base.py Ajusta time limits e reciclagem/concurrency de workers Celery; remove backend “django-db” comentando.
collection/tasks.py Corrige fluxo de seleção de usuário (if/elif/else) e adiciona erro explícito quando ausente.
bigbang/tasks.py Passa a usar _get_user centralizado (remove função local).
article/controller.py Otimiza iteração do bulk export com select_related(...) para reduzir queries.
Comments suppressed due to low confidence (1)

researcher/tasks.py:37

  • O prefetch_related("researcheraka_set__researcher_identifier") não é aproveitado porque no loop você usa old_researcher.researcheraka_set.filter(...).first(), o que normalmente dispara uma query por pesquisador. Para realmente eliminar o N+1, prefira Prefetch com queryset já filtrado (ex.: apenas ORCID) usando to_attr, ou então leia o ORCID a partir da lista prefetched (old_researcher.researcheraka_set.all()) sem .filter().
    old_researchers = Researcher.objects.filter(
        researcheraka__researcher_identifier__source_name="ORCID",
        researcheraka__researcher_identifier__identifier__isnull=False,
    ).select_related(
        "person_name",
        "affiliation__institution__institution_identification",
        "affiliation__institution__location",
    ).prefetch_related(
        "researcheraka_set__researcher_identifier",
    )
    for old_researcher in old_researchers:
        orcid = (
            old_researcher.researcheraka_set.filter(
                researcher_identifier__source_name__iexact="ORCID"
            )
            .first()
            .researcher_identifier.identifier
        )

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +139 to 147
# Salvar primeiro sem arquivo para obter o PK
obj.save()
# save_file já faz self.file.save() que persiste o campo file,
# mas precisamos persistir o registro completo com o path do arquivo
obj.save_file(
f"{pid_provider_xml.v3}.xml", xml_with_pre.tostring(pretty_print=True)
)
# Único save final após salvar o arquivo
obj.save()
@@ -26,21 +27,14 @@
User = get_user_model()
Comment on lines 310 to 311
except Exception as e:
return None
Comment on lines 324 to 325
except Exception as e:
return None
@robertatakenaka
Copy link
Copy Markdown
Member Author

@copilot open a new pull request to apply changes based on the comments in this thread

@robertatakenaka robertatakenaka merged commit 68dc536 into scieloorg:main Mar 17, 2026
7 of 9 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.

2 participants