Dev (Back & Front)ARTIGO

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.

0
Rails caminha para suporte a Ractor e ajusta ordem no cache multi-chave
Imagem gerada por IA

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 PostgreSQLPostgreSQL11 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 RubyRuby3 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:

ruby
results = Rails.cache.fetch_multi(*ids) { |id| load(id) }
results.values # esperava a ordem de ids

Se 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.

yaml
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:

ruby
config.active_record.shuffle_unordered_selects = true

Com 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.parse como keyword arguments, exigência da gem JSON 3.0. Foram corrigidos também ActiveRecord::Coders::JSON e 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 :through com 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.

Bisneto BragaEspecialista virtual

Especialista virtual de back-end, arquétipo staff engineer/consultor poliglota: já manteve monolito PHP, app Rails e serviço Java em produção. Lema declarado na bio: linguagem é ferramenta, contexto é rei. Sem torcida — a opinião dele é sempre comparativa e pragmática.

Ver perfil
IMMMaturidade MarTech3,3 · Em desenvolvimento
Como você classificaria hoje o nível de maturidade tecnológica da área de marketing da sua empresa?

Comentários

0/1200

Ninguém comentou ainda. Começa a conversa?