O que diz a GoCardless
| Reason | Tipo | HTTP | Texto da GoCardless |
|---|---|---|---|
rate_limit_exceeded | invalid_api_usage | 429 | Rate limit reached. Check headers for reset time. |
A página de limites da GoCardless indica o número: 1 600 pedidos por minuto numa integração padrão e 1 600 por minuto e por comerciante numa integração de parceiro. Ao ultrapassá-lo, a API devolve o 429, e a GoCardless esclarece que estes pedidos podem ser repetidos sem problema: «These requests are safe to retry.». Para saber quando, remete para os cabeçalhos da resposta: ratelimit-limit, ratelimit-remaining e ratelimit-reset.

De onde vêm tantos pedidos
O limite conta todos os pedidos à API, não só os que criam cobranças. Com o conector, cada cobrança com um mandato guardado é um pedido, quer venha de uma subscrição que se renova quer de um pagamento registado com o método de pagamento do cliente. Cada evento de um pagamento que chega ao Odoo é outro, porque o conector não confia apenas no aviso: pede esse pagamento à GoCardless e aplica o estado que ela devolve. Um lote grande no mesmo momento, como muitas renovações ao mesmo tempo enquanto chegam os eventos das cobranças anteriores, soma as duas coisas.
A GoCardless classifica este reason entre os erros invalid_api_usage, os que vêm da forma como o pedido é feito, e para estes pede que se avise a equipa técnica («alert your dev team»). Um 429 isolado não o exige; um que se repete todos os dias, sim.
O que faz o conector
- Lê o cabeçalho
ratelimit-resete calcula quanto falta: a hora que indica menos a do servidor do Odoo. - Espera esse tempo, no mínimo 1 segundo e no máximo 65. Se o cabeçalho faltar ou não puder ser lido, espera 1 segundo. O teto existe para que um relógio mal configurado não deixe bloqueado o processo do Odoo que aguarda.
- Repete o pedido uma única vez.
- Se a repetição voltar a receber um 429, já não espera mais: trata-o como qualquer outra rejeição da API.
O conector não conta os seus pedidos nem os trava antecipadamente. Não lê ratelimit-remaining: só espera quando a GoCardless já respondeu com 429.

Se o segundo pedido também falhar
Depende do que o Odoo estava a fazer naquele momento.
- Se era uma cobrança, a transação passa a «Erro» com «A GoCardless rejeitou o pedido.» e, por baixo, a mensagem da GoCardless com
rate_limit_exceedede orequest_identre parênteses retos. A fatura continua pendente de cobrança. - Se estava a aplicar um evento da GoCardless, o webhook responde 500 para que a GoCardless volte a enviar, e os eventos que já foram aplicados não são aplicados duas vezes. A recuperação de cada hora também não deixa para trás um evento que falhou: volta a pedi-lo na passagem seguinte.
Um 429 não é o mesmo que uma cobrança sem resposta. Sem resposta, o conector não sabe se a GoCardless criou a cobrança, por isso deixa-a pendente e volta a enviá-la, com a mesma chave, em menos de uma hora. Com um 429 há resposta: a GoCardless não aceitou o pedido, e por isso a transação fica em erro.
Esta mensagem aparece no idioma de quem lança a cobrança. Se a lança uma ação agendada, como a renovação de uma subscrição, escreve-se sem ninguém à frente: numa base de dados criada em português aparece assim, e numa criada em inglês e passada depois para português, em inglês: «GoCardless rejected the request.».
O que fazer
- Abra a transação a partir da fatura, com o botão «Transação de Pagamento» no topo; o menu de transações só aparece em modo de programador, e no Odoo 20 não existe. Se a mensagem mencionar
rate_limit_exceeded, a GoCardless rejeitou esse pedido por causa do limite, não por causa do cliente nem do seu mandato. - Passado algum tempo, volte a cobrar a fatura com o método de pagamento guardado do cliente.
- Se acontecer com frequência, verifique a hora do servidor do Odoo: a espera resulta de subtraí-la à de
ratelimit-reset, e um relógio adiantado encurta-a. - Se precisar da GoCardless, guarde o
request_idda mensagem: a documentação pede que o inclua ao contactar o seu suporte.
O conector distribui os pedidos para não chegar ao limite?
Não. Não os conta nem os trava antecipadamente: reage quando a GoCardless responde com 429, com uma espera e uma única repetição.
Porque espera no máximo 65 segundos?
Enquanto espera, o processo do Odoo que faz o pedido não faz mais nada. O código do conector define esse teto para que um relógio mal configurado não o deixe bloqueado.
Perde-se algum evento da GoCardless por causa do limite?
Não se considera perdido: o webhook pede à GoCardless que o volte a enviar, e a recuperação de cada hora volta a pedi-lo na passagem seguinte.
Com o nosso conector
No Odoo 17, 18, 19 e 20 o conector trata o 429 como uma pausa: espera o tempo que a GoCardless pede, repete uma vez e, se o limite continuar, deixa a transação em erro com o request_id, para que saiba o que aconteceu e o que dar à GoCardless.
Continue a ler
Verificado no código do conector (versão 17.0, 18.0, 19.0 e 20.0) e nas fontes indicadas
Fontes
- docs.gocardless.com/docs/api-reference/limits
- docs.gocardless.com/docs/api-reference/responses-and-errors
- Código do módulo: flexigo_payment_gocardless: const.py, linha 113 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_provider.py, linha 378 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_provider.py, linha 408 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_provider.py, linha 379 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_provider.py, linha 383 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_provider.py, linha 397 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_provider.py, linha 462 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 281 em 17.0 (d203ee6), linha 281 em 18.0 (e2ab18b), linha 281 em 19.0 (ce7f5a3) e linha 292 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 247 em 17.0 (d203ee6), linha 247 em 18.0 (e2ab18b), linha 247 em 19.0 (ce7f5a3) e linha 258 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 299 em 17.0 (d203ee6), linha 299 em 18.0 (e2ab18b), linha 299 em 19.0 (ce7f5a3) e linha 310 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_transaction.py, linha 589 em 17.0 (d203ee6), linha 589 em 18.0 (e2ab18b), linha 588 em 19.0 (ce7f5a3) e linha 607 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: controllers/main.py, linha 124 em 17.0 (d203ee6), linha 124 em 18.0 (e2ab18b), linha 124 em 19.0 (ce7f5a3) e linha 127 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: controllers/main.py, linha 96 em 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/gocardless_webhook_event.py, linha 7 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: const.py, linha 117 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 20.0 (688d86b)
- Código do módulo: flexigo_payment_gocardless: models/payment_provider.py, linha 603 em 17.0 (d203ee6), linha 603 em 18.0 (e2ab18b), linha 603 em 19.0 (ce7f5a3) e linha 605 em 20.0 (688d86b)
- docs.gocardless.com/docs/api-reference/webhooks
- Código do módulo: flexigo_payment_gocardless: i18n/pt.po, linha 558 em 17.0 (d203ee6), linha 558 em 18.0 (e2ab18b), linha 558 em 19.0 (ce7f5a3) e linha 564 em 20.0 (688d86b)
- github.com/odoo/odoo/blob/20.0/addons/payment/i18n/pt.po
- github.com/odoo/odoo/blob/20.0/addons/payment/views/payment_transaction_views.xml
- github.com/odoo/odoo/blob/17.0/odoo/http.py
- github.com/odoo/odoo/blob/20.0/addons/account_payment/views/account_move_views.xml
- Código do módulo: flexigo_payment_gocardless: __manifest__.py, linha 31 em 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) e 20.0 (688d86b)
