Skip to content

Tira as integrações com o Telegram da requisição do usuário - #88

Merged
Hirley merged 2 commits into
mainfrom
claude-hirley/telegram-em-background
Sep 1, 2026
Merged

Hirley merged 2 commits into
mainfrom
claude-hirley/telegram-em-background

Conversation

@Hirley

@Hirley Hirley commented Sep 1, 2026

Copy link
Copy Markdown
Owner

Fecha a #78.

Duas telas falavam com a API do Telegram dentro do ciclo de request/response — o envio do relatório semanal (que ainda gerava o PDF antes) e a redefinição de senha por Telegram. A latência das duas dependia de um serviço de terceiro, e com RAILS_MAX_THREADS no default de 5 poucos pedidos presos bastavam para degradar a aplicação inteira, inclusive telas sem relação nenhuma com Telegram.

As duas passaram a enfileirar (RelatorioSemanalTelegramJob, TelegramPasswordResetJob) e responder na hora. Isso só faz sentido depois da #77: com a fila em memória, o que saía da requisição virava o que se perdia no restart seguinte.

Decisões

A checagem "dá pra enviar?" ficou na tela, não no job. Os dois motivos previsíveis de falha (servidor sem TELEGRAM_BOT_TOKEN, usuário sem Chat ID) são exatamente o que o alerta da tela explica, e nenhum precisa tocar a rede — então o aviso continua imediato. Virou TelegramNotifier#pode_enviar_para?, que de quebra passou a ser a guarda única dos três métodos de envio, no lugar da mesma condição repetida três vezes.

Enfileirar reforça a resposta genérica da redefinição de senha, não a enfraquece. Antes, o e-mail cadastrado com Chat ID esperava o Telegram responder e o e-mail desconhecido voltava na hora: a mensagem era a mesma nos dois casos, mas o cronômetro entregava a diferença que ela tenta esconder. Agora os dois caminhos fazem um SELECT, e um deles um INSERT na fila.

Descartado: enfileirar sempre, passando o e-mail digitado para o job (o que deixaria a resposta rigorosamente constante). Guardaria e-mail arbitrário de visitante anônimo na tabela de jobs e deixaria um formulário público encher a fila — e o throttle por IP/e-mail já é o que barra esse uso.

Relatorios::GerarPdfSemanal nasceu porque os dois caminhos que geram o PDF de verdade precisam fazer exatamente a mesma coisa: montar os dados, anunciar relatorio_gerado e renderizar. Repetir a montagem do payload nos dois era garantia de eles divergirem no primeiro campo novo. O download (GET /relatorios/semanal.pdf) continua síncrono de propósito: ali o PDF é a resposta, não há como devolvê-lo depois.

O que se perde

Uma falha no envio em si — Telegram fora do ar, timeout — não aparece mais na tela: quem pediu vê "chega em instantes" e nada chega. Fica registrada no log do job em nível warn. Trazer isso de volta exigiria persistir o resultado de cada envio e uma tela para consultar o status; é desproporcional para o caso raro, e a alternativa era continuar prendendo um worker do Puma por causa dele.

Consequência operacional que também entrou no README: sem o processo bin/jobs de pé, essas duas telas respondem normalmente e nada é entregue — os jobs se acumulam em solid_queue_jobs até alguém subir o worker.

Verificação

No container (ruby:4.0.6-slim + postgres:16-alpine, espelhando o ci.yml):

  • RuboCop — 110 arquivos, 0 ofensas;
  • bin/rails zeitwerk:checkAll is good!;
  • RSpec — 384 exemplos, 0 falhas (eram 375).

Não verificado no navegador. Nada de JS, CSS, HAML ou CSP mudou — só o texto de dois flashes, que os request specs conferem. Verificar a tela de ponta a ponta exigiria login, que não faço.

Vai junto um commit separado corrigindo o cabeçalho do WebhookDeliveryJob, que ainda descrevia o adapter :async e chamava a fila persistente de "assunto de outra issue" — a issue em questão é a #77, já entregue.

Hirley and others added 2 commits August 31, 2026 21:51
O cabeçalho da classe ainda dizia que o adapter era o :async e que
trocá-lo por um backend persistente seria "assunto de outra issue" — mas
essa outra issue (#77) já foi entregue, e em produção a fila é o Solid
Queue desde então.

Um comentário que descreve o código anterior é pior que nenhum: quem
lesse este ia concluir que as tentativas reagendadas ainda se perdem num
deploy, que é justamente o que deixou de acontecer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Duas telas falavam com a API do Telegram dentro do ciclo de
request/response: o envio do relatório semanal (que ainda gerava o PDF
antes) e a redefinição de senha por Telegram. A latência das duas
dependia do tempo de resposta de um serviço de terceiro, e com
RAILS_MAX_THREADS no default de 5 poucos pedidos presos bastavam para
degradar a aplicação inteira — inclusive telas sem relação nenhuma com
Telegram.

Agora as duas enfileiram (RelatorioSemanalTelegramJob e
TelegramPasswordResetJob) e respondem na hora. Como a fila é persistente
desde a #77, o que sai da requisição não vira o que se perde num
restart.

Decisões que valem registro:

A checagem "dá pra enviar?" ficou na TELA, não no job. Os dois motivos
previsíveis de falha (servidor sem TELEGRAM_BOT_TOKEN, usuário sem Chat
ID) são exatamente o que o alerta da tela explica, e nenhum dos dois
precisa tocar a rede — então o aviso continua imediato e útil. Virou
TelegramNotifier#pode_enviar_para?, que também passou a ser a guarda
única dos três métodos de envio, no lugar da mesma condição repetida
três vezes.

O que se perde com isso: uma falha no envio em si (Telegram fora do ar,
timeout) não aparece mais na tela — quem pediu vê "chega em instantes" e
nada chega; fica no log do job em nível warn. Mostrar isso de volta
exigiria persistir o resultado de cada envio e uma tela para consultar o
status, desproporcional para o caso raro; a alternativa era continuar
prendendo um worker do Puma por causa dele.

Na redefinição de senha, enfileirar REFORÇA a resposta genérica em vez
de enfraquecê-la. Antes, o e-mail cadastrado com Chat ID esperava o
Telegram responder e o e-mail desconhecido voltava na hora: a mensagem
era a mesma, mas o cronômetro entregava a diferença. Agora os dois
caminhos fazem um SELECT, e um deles um INSERT. Foi descartado
enfileirar sempre, passando o e-mail digitado para o job (resposta
rigorosamente constante): guardaria e-mail arbitrário de visitante
anônimo na tabela de jobs e deixaria o formulário encher a fila — e o
throttle por IP/e-mail já é o que barra esse uso.

Relatorios::GerarPdfSemanal nasceu porque os dois caminhos que geram o
PDF de verdade (o download, que segue síncrono porque o PDF É a
resposta, e o envio por Telegram, agora no job) precisam fazer
exatamente a mesma coisa: montar os dados, anunciar "relatorio_gerado" e
renderizar. Repetir a montagem do payload nos dois era garantia de eles
divergirem no primeiro campo novo.

Verificado no container: RuboCop 110 arquivos sem ofensas,
zeitwerk:check limpo, RSpec 384 exemplos e 0 falhas.

Closes #78

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Hirley
Hirley merged commit 6b52b06 into main Sep 1, 2026
3 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in @Hirley's task_keeper_api Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant