|
3 | 3 | module Que |
4 | 4 | module ActiveRecord |
5 | 5 | class << self |
| 6 | + def active_rails_executor? |
| 7 | + defined?(::Rails.application.executor) && ::Rails.application.executor.active? |
| 8 | + end |
| 9 | + |
6 | 10 | def wrap_in_rails_executor(&block) |
7 | 11 | if defined?(::Rails.application.executor) |
8 | 12 | ::Rails.application.executor.wrap(&block) |
@@ -39,17 +43,36 @@ def call(job) |
39 | 43 | yield |
40 | 44 | end |
41 | 45 |
|
42 | | - # ActiveRecord will check out connections to the current thread when |
43 | | - # queries are executed and not return them to the pool until |
44 | | - # explicitly requested to. I'm not wild about this API design, and |
45 | | - # it doesn't pose a problem for the typical case of workers using a |
46 | | - # single PG connection (since we ensure that connection is checked |
47 | | - # in and checked out responsibly), but since ActiveRecord supports |
48 | | - # connections to multiple databases, it's easy for people using that |
49 | | - # feature to unknowingly leak connections to other databases. So, |
50 | | - # take the additional step of telling ActiveRecord to check in all |
51 | | - # of the current thread's connections after each job is run. |
52 | | - ::ActiveRecord::Base.clear_active_connections! unless job.class.resolve_que_setting(:run_synchronously) |
| 46 | + clear_active_connections_if_needed!(job) |
| 47 | + end |
| 48 | + |
| 49 | + private |
| 50 | + |
| 51 | + # ActiveRecord will check out connections to the current thread when |
| 52 | + # queries are executed and not return them to the pool until |
| 53 | + # explicitly requested to. I'm not wild about this API design, and |
| 54 | + # it doesn't pose a problem for the typical case of workers using a |
| 55 | + # single PG connection (since we ensure that connection is checked |
| 56 | + # in and checked out responsibly), but since ActiveRecord supports |
| 57 | + # connections to multiple databases, it's easy for people using that |
| 58 | + # feature to unknowingly leak connections to other databases. So, |
| 59 | + # take the additional step of telling ActiveRecord to check in all |
| 60 | + # of the current thread's connections after each job is run. |
| 61 | + def clear_active_connections_if_needed!(job) |
| 62 | + # don't clean in synchronous mode |
| 63 | + # see https://github.com/que-rb/que/pull/393 |
| 64 | + return if job.class.resolve_que_setting(:run_synchronously) |
| 65 | + |
| 66 | + # don't clear connections in nested jobs, |
| 67 | + # i.e. clear only if this is the outermost instance of |
| 68 | + # Que::ActiveRecord::Connection::JobMiddleware |
| 69 | + return if Que::ActiveRecord.active_rails_executor? |
| 70 | + |
| 71 | + if ::ActiveRecord.version >= Gem::Version.new('7.1') |
| 72 | + ::ActiveRecord::Base.connection_handler.clear_active_connections!(:all) |
| 73 | + else |
| 74 | + ::ActiveRecord::Base.clear_active_connections! |
| 75 | + end |
53 | 76 | end |
54 | 77 | end |
55 | 78 | end |
|
0 commit comments