Je n'ai pas pu reproduire ce problème localement en utilisant : Postgresql 9.4.26. Mais il pourrait être utile de partager ce que j'ai essayé et quelques réflexions autour du problème du serveur. Voici ce que j'ai essayé (une partie utile pourrait être une requête pour vérifier la version PG depuis Rails) :
# Confirmation que j'utilise PG 9.4.x :
irb(main):002:0> ActiveRecord::Base.connection.execute("select version()")
(10.8ms) select version()
=> #
irb(main):003:0> _.first
=> {"version"=>"PostgreSQL 9.4.26 on x86_64-apple-darwin18.7.0, compilé par Apple clang version 11.0.0 (clang-1100.0.33.17), 64-bit"}
# Définir un délai d'attente :
irb(main):004:0> ActiveRecord::Base.connection.execute("SET statement_timeout = 1000")
(0.4ms) SET statement_timeout = 1000
=> #
# Confirmer que cela fonctionne - c'est ~1s et la stacktrace est assez explicite à ce sujet :
irb(main):005:0> ActiveRecord::Base.connection.execute("select pg_sleep(4)")
(1071.2ms) select pg_sleep(4)
.... (stacktrace cachée)
ActiveRecord::StatementInvalid (PG::QueryCanceled: ERROR: cancelation de la requête en raison d'un dépassement du délai d'attente de la requête)
: select pg_sleep(4)
Voici ce qu'il faut essayer
Comme le problème survient uniquement sur le serveur et que statement_timeout
fonctionne sur d'autres versions mineures et localement, une chose qui vient à l'esprit est le manque de privilèges pour mettre à jour statement_timeout
à partir de l'endroit où cela est tenté. Peut-être que le login pg de rails utilisé pour établir la connexion à la base de données n'est pas autorisé à mettre à jour ce paramètre. Le mieux serait de vérifier cela soit via la console rails sur un serveur :
irb(main):004:0> ActiveRecord::Base.connection.execute("SET statement_timeout = 1000")
irb(main):004:0> irb(main):003:0> ActiveRecord::Base.connection.execute("show statement_timeout").first
(0.2ms) show statement_timeout
=> {"statement_timeout"=>"1s"}
Ou, cela peut être vérifié directement via la console psql (certaines installations le permettent aussi) :
psql myserveruser # si c'était le pg d'heroku : heroku pg:psql
postgres=# set statement_timeout = 1000;
SET
postgres=# select pg_sleep(4);
ERROR: cancelation de la requête en raison d'un dépassement du délai d'attente de la requête
Time: 1068.067 ms (00:01.068)
Autre chose à garder à l'esprit (extrait de https://dba.stackexchange.com/a/83035/90903) :
La façon dont statement_timeout fonctionne, le temps commence à être compté lorsque le serveur reçoit une nouvelle commande du client...
Et si une fonction fait SET statement_timeout = 100; cela n'aura d'effet qu'à partir de la prochaine commande du client.