Skip to content

Separa caminho de gravação da URL pública de leitura no MinIO/S3#1015

Open
robertatakenaka wants to merge 12 commits into
scieloorg:mainfrom
robertatakenaka:minio_subdir
Open

Separa caminho de gravação da URL pública de leitura no MinIO/S3#1015
robertatakenaka wants to merge 12 commits into
scieloorg:mainfrom
robertatakenaka:minio_subdir

Conversation

@robertatakenaka

@robertatakenaka robertatakenaka commented Jun 30, 2026

Copy link
Copy Markdown
Member

O que esse PR faz?

Refatora a camada de armazenamento de arquivos (files_storage) para desacoplar onde o arquivo é gravado de qual URL é usada para lê-lo, e propaga essa mudança para quem consome o storage (package/models.py).

  • files_storage/minio.py: MinioStorage passa a receber bucket, object_name_prefix e public_url (em vez de um único bucket_root). get_uri prioriza public_url; sem ela, cai no presigned URL do próprio provedor, aplicando o prefixo via get_full_object_name. fput absorve o antigo _fput_object, mantendo o retry automático em caso de bucket inexistente. Remove build_object_name/register (responsabilidade de nomeação não é mais da classe de storage).
  • files_storage/models.py: MinioConfiguration ganha host_root_dir, bucket (renomeado de bucket_root) e public_base_url, com properties object_name_prefix/public_url que derivam os parâmetros passados ao MinioStorage. Corrige bug no log de erro de FileLocation.get_or_create (referenciava obj em vez de uri) e amplia COUNTRY_REGION.
  • Migração (0005_...): aplica a renomeação de campo e os novos campos no banco, removendo índices obsoletos.
  • files_storage/wagtail_hooks.py: ajusta list_display/search_fields para o campo bucket.
  • package/models.py: SPSPkg deixa de buscar a configuração do Minio internamente em cada chamada (MinioConfiguration.get_files_storage repetido); agora a configuração é obtida uma única vez (get_minio_config()) e injetada como parâmetro em toda a cadeia de upload (upload_items_to_the_cloud, upload_to_the_cloud, upload_zip_content_to_the_cloud, upload_components_to_the_cloud, upload_xml_to_the_cloud, upload_article_page_to_the_cloud).
  • files_storage/test_minio.py e files_storage/test_models.py (novo): suíte reescrita/criada cobrindo o novo contrato (prefixo de escrita, URL pública de leitura, retry em NoSuchBucket, propagação de outros S3Error, properties de MinioConfiguration, fallback de configuração).
  • Remoção de libs/dsm/: módulo legado (storage antigo, publicação direta no OPAC via mongoengine) que não é mais referenciado pelo fluxo atual.

Onde a revisão poderia começar?

  1. files_storage/minio.py — é a base de todo o resto; entender get_full_object_name, get_uri e o retry em fput.
  2. files_storage/models.py — como object_name_prefix/public_url são derivados de host_root_dir/public_base_url.
  3. package/models.py — como o minio passou a ser injetado em vez de buscado a cada chamada (ponto com maior superfície de mudança de assinatura de métodos).
  4. Migração 0005_... e wagtail_hooks.py — conferência de que tudo aponta para bucket.

Como este poderia ser testado manualmente?

  1. Subir um MinIO local (ou apontar para o ambiente de dev) e rodar as migrações (python manage.py migrate files_storage).
  2. Criar/editar uma MinioConfiguration no admin do Wagtail preenchendo bucket, host_root_dir e public_base_url (testar com e sem public_base_url preenchido).
  3. Disparar um upload de pacote SPS (SPSPkg.upload_to_the_cloud/fluxo completo) e confirmar:
    • o objeto é gravado no caminho esperado (com o prefixo, se host_root_dir estiver configurado);
    • a URI salva em FileLocation/SPSPkg reflete public_base_url (ou o fallback http(s)://host) corretamente, e o conteúdo é acessível por essa URL.
  4. Forçar o cenário de bucket inexistente (apagar o bucket antes do upload) e confirmar que o bucket é criado automaticamente e o upload é refeito com sucesso.
  5. Rodar a suíte: python manage.py test files_storage.

Algum cenário de contexto que queira dar?

A motivação principal foi permitir que o caminho físico de gravação (host interno, prefixo) seja independente da URL pública de leitura (ex.: CDN, domínio público diferente do host de escrita) — algo que o antigo bucket_root único não suportava. Como efeito colateral, isso obrigou a passar o objeto de configuração do Minio explicitamente pelas funções de upload do SPSPkg, em vez de buscá-lo repetidamente do banco a cada chamada (redução de N+1 consultas e maior previsibilidade de qual configuração está sendo usada durante todo o ciclo de upload de um pacote).

A remoção de libs/dsm/ é um cleanup de código morto: esse módulo implementava uma integração antiga e direta com o OPAC via mongoengine, hoje substituída pelo fluxo atual.

Screenshots

N/A — mudança de backend/infraestrutura, sem impacto visual direto. Se desejar, posso anexar prints do admin do Wagtail com os novos campos (host_root_dir, bucket, public_base_url).

Quais são tickets relevantes?

#999

Referências

[adicionar links, se houver — ex.: documentação interna sobre a topologia de storage MinIO/Wasabi]

Remove a implementação antiga de files_storage e publication (ISIS/DSM),
substituída pela arquitetura atual em files_storage/ e package/.

@rondinelisaad rondinelisaad left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

De acordo com a proposta.

…tância no upload

Extrai get_minio_config e injeta o cliente minio já resolvido ao longo
da cadeia de upload (upload_items/components/zip/xml/article_page),
evitando reinstanciar a configuração a cada arquivo enviado à nuvem.
…write_prefix

Substitui bucket_root/bucket_app_subdir pelo novo schema bucket/write_prefix
no arquivo de exemplo de desenvolvimento.
…Storage

Por quê: a URI pública salva no banco precisava poder divergir do
caminho físico de gravação (prefixo/host interno), o que o antigo
bucket_root único não permitia.

Como:
- Renomeia bucket_root para bucket
- Adiciona object_name_prefix (prefixo de escrita) e public_url (base
  de leitura), com get_full_object_name() centralizando o prefixo
- get_uri prioriza public_url; sem ela, cai no presigned URL aplicando
  o prefixo e removendo a query string assinada
- Funde _fput_object em fput, mantendo o retry automático em caso de
  bucket inexistente (cria bucket + policy e tenta de novo)
- remove/fget passam a aplicar get_full_object_name corretamente
- Remove build_object_name/register (nomeação de objeto deixa de ser
  responsabilidade da classe de storage)
- Move _create_tmp_file para função de módulo (não dependia de self)
…t/prefix/public_url

Por quê: o model precisa expor os três parâmetros que o novo
MinioStorage exige (bucket, object_name_prefix, public_url) e permitir
configurar leitura via CDN/domínio público distinto do host de escrita.

Como:
- Renomeia bucket_root para bucket; adiciona host_root_dir e
  public_base_url
- Adiciona properties object_name_prefix e public_url, que derivam os
  parâmetros passados ao MinioStorage em get_files_storage
- Amplia COUNTRY_REGION (China, Rússia, Panamá, República Dominicana)
- Corrige bug em FileLocation.get_or_create (mensagem de erro
  referenciava 'obj' indefinido em vez de 'uri')
- Ajusta obrigatoriedade/defaults de access_key, secret_key, bucket e
  remove índices obsoletos de host/bucket_root
Por quê: refletir no banco a renomeação bucket_root -> bucket e os
novos campos host_root_dir / public_base_url introduzidos no model.

Como: remove os índices obsoletos de host e bucket_root e aplica as
alterações de campo correspondentes (gerada via makemigrations).
Por quê: list_display/search_fields ainda referenciavam bucket_root,
o que quebraria o admin após a renomeação do campo no model.

Como: atualiza MinioConfigurationViewSet para usar bucket em vez de
bucket_root em list_display e search_fields.
…o leitura/escrita

Por quê: a suíte antiga testava bucket_root/build_object_name/register,
que não existem mais; era preciso cobrir o novo comportamento de
prefixo de escrita vs. URL pública de leitura.

Como:
- Cobre get_full_object_name com e sem prefixo
- Cobre get_uri com public_url (sem chamar presigned) e sem public_url
  (presigned com prefixo aplicado e query string removida)
- Cobre fput: grava sob object_name_prefix, retry em NoSuchBucket
  (cria bucket + policy) e propagação de outros S3Error sem conversão
- Cobre fput_content, remove e fget aplicando o prefixo
- Adiciona helper make_s3_error para instanciar S3Error 'congelado'
  via construtor oficial, já que code é uma property sem setter
Por quê: o model não tinha cobertura para get_or_create e para as
properties que derivam object_name_prefix/public_url a partir de
host_root_dir e public_base_url, usadas por get_files_storage.

Como: cobre get_or_create, os cálculos de object_name_prefix/public_url
nos cenários com e sem host_root_dir/public_base_url, e a instanciação
correta de MinioStorage via get_files_storage.
@robertatakenaka

Copy link
Copy Markdown
Member Author

@rondinelisaad revisar novamente, fiz ajustes após nossa reunião

@rondinelisaad rondinelisaad left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

De acordo.

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