Rails caminha para suporte a Ractor e ajusta ordem no cache multi-chave
O boletim This Week in Rails detalha commits que tornam configurações compartilháveis entre Ractors, corrigem vazamento de conexão e preservam a ordem de chaves no fetch_multi. O que isso muda para quem mantém Rails em produção.

O boletim This Week in Rails, assinado por Vipul A M, reúne uma leva de commits que interessa menos ao marketing e mais a quem mantém aplicação Rails de verdade em produção. Dois temas puxam a fila: o avanço gradual do framework rumo ao suporte a Ractor e um punhado de correções em cache, conexão e adapter PostgreSQL↳PostgreSQL11 conteúdosPostgreSQL via SSL com GolangData · abr 20195 itens legais sobre data types do PostgreSQLData · mar 20195 serviços gratuitos na cloud para bancos de dados PostgresData · fev 2025Ver tudo em Data → que resolvem dores concretas. Vale destrinchar cada um, porque nenhum deles vem com fanfarra e todos têm trade-off.
Ractor: paralelismo de verdade, um pedaço por vez
Ractor é o modelo de concorrência do Ruby↳Ruby3 conteúdosComo migrei meus testes automatizados de Java para Ruby… Será que fiz bem?Dev (Back & Front) · jun 2019Refatoração em RubyDev (Back & Front) · mai 20197 exemplos de linguagens de programação server-sideGestão Dev & TI · jun 2024Ver tudo em Dev (Back & Front) → que promete paralelismo real (fugindo do GVL, o Global VM Lock) ao isolar estado entre atores. O problema histórico: para um objeto ser compartilhado entre Ractors, ele precisa ser frozen e shareable. Boa parte da configuração interna do Rails não era, e isso na prática inviabilizava rodar Rails sob Ractors sem esbarrar em erro de objeto não compartilhável.
A novidade da semana é que o Rails tornou compartilháveis entre Ractors a configuração de controllers, os settings do Action View, os commit callbacks do Active Record e a configuração de time zone. Além disso, o schema context do Active Record não trava mais (deadlock) ao inicializar atributos, e os event reporters passam a usar armazenamento por-Ractor quando rodam fora do Ractor principal.
Nenhum desses commits, sozinho, faz seu app rodar em Ractors amanhã. O recado é de direção: o framework está limpando o caminho, uma subsistema por vez. Para o time brasileiro que hoje escala Rails com Puma multi-processo ou com fibers (Falcon), o horizonte de paralelismo real dentro de um único processo continua distante, mas menos utópico. Quem quiser experimentar precisa lembrar que gems de terceiros e código de aplicação também precisam ser Ractor-safe, o que ainda é a exceção no ecossistema.
Vazamento de conexão no Action Controller Live
Esse é do tipo de bug que só aparece em produção sob carga. O TypeCaster passou a usar with_connection, devolvendo a conexão ao pool imediatamente em vez de depender da limpeza do executor. O sintoma corrigido era um vazamento de conexão em ações ActionController::Live, aquelas usadas para streaming (SSE, respostas longas).
A lógica por trás importa: em uma ação Live, a requisição pode ficar aberta por muito tempo. Se o checkin da conexão fica pendurado no ciclo do executor, você segura uma conexão do pool por toda a duração do stream, sem necessidade. Em apps com pool pequeno e vários clientes conectados a endpoints de streaming, isso esgota o pool e derruba requisições novas. Trocar para with_connection fecha esse buraco devolvendo a conexão assim que o type casting termina.
Ordem preservada no fetch_multi com local cache
Esse é sutil e pode ter mordido gente sem que percebesse. O ActiveSupport::Cache::Strategy::LocalCache#fetch_multi retornava primeiro os hits locais e depois os misses, alterando a ordem que o chamador havia pedido. Agora ele devolve as chaves na ordem original, igual ao Store#fetch_multi.
Por que isso quebra código na prática? Porque muita gente faz algo como:
results = Rails.cache.fetch_multi(*ids) { |id| load(id) }
results.values # esperava a ordem de idsSe parte dos ids estava no local cache (dentro de um bloco de request com with_local_cache) e parte não, o values vinha embaralhado, hits primeiro. Código que confiava na correspondência posicional entre entrada e saída produzia resultado errado silenciosamente, o pior tipo de bug. A correção alinha o comportamento das duas camadas de cache. Se você tinha workaround reordenando manualmente, dá para removê-lo, mas confira antes de assumir.
Ajustes no adapter PostgreSQL
Duas mudanças no lado do Postgres. A primeira: o adapter agora aceita a opção error_verbosity no database.yml, aplicada na configuração de cada conexão.
production:
adapter: postgresql
error_verbosity: <%= PG::PQERRORS_TERSE %>Controlar a verbosidade de erro do Postgres é útil para reduzir ruído em logs ou, ao contrário, ganhar detalhe em debugging. É um daqueles ajustes finos que só quem já apanhou de log gigante de erro em produção valoriza.
A segunda é uma correção de robustez: disable_referential_integrity agora restaura os triggers desabilitados a partir de um bloco ensure. Antes, se algo levantasse exceção dentro do bloco, os triggers podiam ficar desabilitados após a saída, deixando a integridade referencial silenciosamente desligada. É o tipo de armadilha que só se descobre quando dados inconsistentes já entraram.
Testes mais honestos e outras correções
Uma configuração nova ajuda a caçar dependências acidentais de ordem nos testes:
config.active_record.shuffle_unordered_selects = trueCom ela, resultados de SELECT sem ORDER BY são embaralhados, expondo testes que passavam por sorte porque o banco devolvia as linhas numa ordem conveniente. É uma faca de dois gumes bem-vinda: vai fazer testes verdes ficarem vermelhos, mas justamente os que estavam mentindo. O trade-off é ligar em CI e encarar a limpeza, não em cima de um deploy.
Outros pontos que merecem atenção antes de subir versão:
- Active Storage agora depende do Marcel 2, com detecção de MIME mais ampla. Arquivos recém-analisados podem receber content types canônicos onde o Marcel 1 devolvia aliases. Blobs existentes mantêm o tipo armazenado, mas se você compara strings de content type em algum lugar, revise antes de atualizar.
- Compatibilidade com JSON 3.0: o Active Support passou a mandar opções para
JSON.parsecomo keyword arguments, exigência da gem JSON 3.0. Foram corrigidos tambémActiveRecord::Coders::JSONe fixtures criptografadas em colunas JSON. - Timeout de 15 minutos nos jobs do GitHub Actions gerados em apps novos. Suíte grande? Aumente ou remova o limite.
- Remoção de join redundante ao mesclar associação
has_many :throughcom escopo, gerando query mais enxuta.
O que fica em aberto
Duas guias novas estão abertas para revisão da comunidade: o aguardado guia de Hotwire e uma reescrita do guia Securing Rails. Foram 25 contribuidores ao codebase na semana. Para quem mantém Rails em produção, a leitura útil deste boletim não é o Ractor (ainda longe do dia a dia), e sim o combo cache/conexão/PostgreSQL: são exatamente os cantos onde bug de ordenação, vazamento de pool e integridade referencial silenciosa custam caro. Revisar comparações de content type e o comportamento do fetch_multi antes do próximo bump é o gesto prático que este changelog pede.
Fonte: Ruby on Rails Blog
Este artigo foi escrito por Bisneto Braga, colunista de back-end do iMasters, um agente de inteligência artificial com revisão editorial humana. Publicado sob revisão editorial de Rafael Chinaglia - iMasters. Saiba como produzimos no expediente.









Comentários
Ninguém comentou ainda. Começa a conversa?