Pular para conteúdo

0008 — Object storage Garage com 3 modos

Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-08-11 · Decidido em: 2026-05-21

Nota 2026-08-11: esta decisão é o design (3 modos, seam, chave content-addressed). A implementação (ArquivoXlsStorage/S3ArquivoXlsStorage/ArmazenamentoModo/S3Config/...) foi extraída para a lib br.com.xadm:xadm-comum-storage e o app adotou-a — ver decisão 0025. Prefixos de config e comportamento inalterados; as classes vivem agora em br.com.xadm.comum.armazenamento.

Contexto

O binário do .xlsx recebido era guardado em BYTEA no Postgres, o que infla o banco. Quer-se mover para object storage S3-compatível (Garage) sem perder a rede de segurança durante a transição.

Decisão

Um seam ArquivoXlsStorage (impl S3ArquivoXlsStorage, AWS SDK v2) com 3 modos (app.storage.modo / env S3_FILE_STORAGE):

  • PSQL — só Postgres (arquivo_bytes).
  • PSQL_GARAGE (default) — grava nos dois, lê do Garage. Rede de segurança.
  • GARAGE — só Garage; o BYTEA fica NULL.

Chave content-addressed: {aaaa}/{mm}/{checksum_sha256}.xlsx. O backfill (StorageBackfillService, @Order(-100), idempotente) roda no startup em todo modo; é no-op no modo PSQL.

Correção 2026-06-12: o texto dizia "backfill opt-in (app.storage.backfill.enabled)"; essa property não existe — o backfill roda sempre no startup. Fato incidental — a decisão (3 modos) segue (§1.4).

Consequências

  • Migração reversível: a coluna arquivo_bytes não é dropada — o "cleanup" do modo GARAGE é zerar bytes em runtime.
  • Falha de I/O no upload → StorageIndisponivelException → HTTP 503 (sem linha persistida; o cliente reenvia).

Alternativas consideradas

  • Só Postgres BYTEA: o banco infla com o volume de uploads. Descartado.
  • Migrar direto para GARAGE sem o modo dual: sem rede de segurança se o storage falhar durante a transição. Descartado em favor do PSQL_GARAGE.