queue_classic 3.2.0.RC1 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/codeql-analysis.yml +72 -0
  3. data/.github/workflows/main.yaml +71 -0
  4. data/.gitignore +2 -0
  5. data/{changelog → CHANGELOG.md} +87 -34
  6. data/CODE_OF_CONDUCT.md +46 -0
  7. data/Gemfile +9 -5
  8. data/README.md +103 -126
  9. data/Rakefile +2 -0
  10. data/lib/generators/queue_classic/install_generator.rb +6 -0
  11. data/lib/generators/queue_classic/templates/add_queue_classic.rb +3 -1
  12. data/lib/generators/queue_classic/templates/update_queue_classic_3_0_0.rb +3 -1
  13. data/lib/generators/queue_classic/templates/update_queue_classic_3_0_2.rb +3 -1
  14. data/lib/generators/queue_classic/templates/update_queue_classic_3_1_0.rb +3 -1
  15. data/lib/generators/queue_classic/templates/update_queue_classic_4_0_0.rb +11 -0
  16. data/lib/queue_classic/config.rb +2 -1
  17. data/lib/queue_classic/conn_adapter.rb +29 -15
  18. data/lib/queue_classic/queue.rb +66 -12
  19. data/lib/queue_classic/railtie.rb +2 -0
  20. data/lib/queue_classic/setup.rb +24 -7
  21. data/lib/queue_classic/tasks.rb +4 -5
  22. data/lib/queue_classic/version.rb +3 -1
  23. data/lib/queue_classic/worker.rb +15 -6
  24. data/lib/queue_classic.rb +4 -11
  25. data/queue_classic.gemspec +3 -2
  26. data/sql/create_table.sql +7 -16
  27. data/sql/ddl.sql +6 -82
  28. data/sql/downgrade_from_4_0_0.sql +88 -0
  29. data/sql/update_to_3_0_0.sql +5 -5
  30. data/sql/update_to_3_1_0.sql +6 -6
  31. data/sql/update_to_4_0_0.sql +6 -0
  32. data/test/benchmark_test.rb +2 -0
  33. data/test/config_test.rb +2 -0
  34. data/test/helper.rb +34 -0
  35. data/test/lib/queue_classic_rails_connection_test.rb +9 -6
  36. data/test/lib/queue_classic_test.rb +2 -0
  37. data/test/lib/queue_classic_test_with_activerecord_typecast.rb +21 -0
  38. data/test/queue_test.rb +62 -2
  39. data/test/rails-tests/.gitignore +2 -0
  40. data/test/rails-tests/rails523.sh +23 -0
  41. data/test/worker_test.rb +138 -17
  42. metadata +43 -13
  43. data/.travis.yml +0 -15
data/README.md CHANGED
@@ -1,41 +1,54 @@
1
1
  # queue_classic
2
+ A simple, efficient worker queue for Ruby & PostgreSQL.
2
3
 
3
- <p align="center">
4
- <b>Simple, efficient worker queue for Ruby & PostgreSQL</b>
5
- <br />
6
- <a href="https://travis-ci.org/QueueClassic/queue_classic"><img src="http://img.shields.io/travis/QueueClassic/queue_classic/master.svg?style=flat" /></a>
4
+ Why this over something like Resque. Two reasons:
7
5
 
8
- <a href="https://codeclimate.com/github/QueueClassic/queue_classic"><img src="http://img.shields.io/codeclimate/github/QueueClassic/queue_classic.svg?style=flat" /></a>
6
+ 1. Your jobs can be equeued in the same transaction as other modifications to the database, and will only be processed when everything is commited. This is a hard pattern to develop around for queues done outside your database
7
+ 2. Less things to run, if you don't already have Redis or a dedicated queue in your stack.
9
8
 
10
- <a href="http://badge.fury.io/rb/queue_classic"><img src="http://img.shields.io/gem/v/queue_classic.svg?style=flat" alt="Gem Version" height="18"></a>
11
- </p>
9
+ ![master](https://github.com/QueueClassic/queue_classic/actions/workflows/main.yaml/badge.svg?branch=master)
12
10
 
11
+ [![Gem Version](http://img.shields.io/gem/v/queue_classic.svg?style=flat)](http://badge.fury.io/rb/queue_classic)
13
12
 
14
- **IMPORTANT NOTE REGARDING VERSIONS**
13
+ **IMPORTANT NOTE: This README is representing the current work for queue_classic, which is generally the pending next version.**
15
14
 
16
- **This README is representing the current work for queue_classic edge [unstable]. You can find the README for other versions:**
15
+ You can always find the latest and previous releases here:
17
16
 
18
- - current release candidate: [v3.1.X](https://github.com/QueueClassic/queue_classic/tree/3-1-stable)
19
- - latest stable can be found: [v3.0.X](https://github.com/QueueClassic/queue_classic/tree/3-0-stable)
20
- - older stable: [v2.2.3](https://github.com/QueueClassic/queue_classic/tree/v2.2.3)
17
+ https://github.com/QueueClassic/queue_classic/releases
21
18
 
19
+ ## Other related projects
20
+ If you're interested in this project, you might also want to checkout:
22
21
 
23
- ## What is queue_classic?
22
+ * [Que](https://github.com/que-rb/que)
23
+ * [GoodJob](https://github.com/bensheldon/good_job)
24
+ * [Delayed Job](https://github.com/collectiveidea/delayed_job)
25
+
26
+ For a list of other queues (which may or may not be Postgres backed), checkout - https://edgeapi.rubyonrails.org/classes/ActiveJob/QueueAdapters.html
24
27
 
28
+ ## What is queue_classic?
25
29
  queue_classic provides a simple interface to a PostgreSQL-backed message queue. queue_classic specializes in concurrent locking and minimizing database load while providing a simple, intuitive developer experience. queue_classic assumes that you are already using PostgreSQL in your production environment and that adding another dependency (e.g. redis, beanstalkd, 0mq) is undesirable.
26
30
 
27
- ## Features
31
+ A major benefit is the ability to enqueue inside transactions, ensuring things are done only when your changes are commited.
28
32
 
29
- * Leverage of PostgreSQL's listen/notify & row locking.
33
+ ## Other related projects
34
+ * [Queue Classic Plus](https://github.com/rainforestapp/queue_classic_plus) - adds support for retrying with specific exceptions, transaction processing of jobs, metric collection, etc
35
+ * [Queue Classic Admin](https://github.com/QueueClassic/queue_classic_admin) - Admin interface for queue_classic
36
+ * [Queue Classic Matchers](https://github.com/rainforestapp/queue_classic_matchers) - RSpec matchers for queue_classic
37
+
38
+ ## Features
39
+ * Leverage of PostgreSQL's listen/notify, skip locked, and row locking.
30
40
  * Support for multiple queues with heterogeneous workers.
31
41
  * JSON data format.
32
- * Forking workers.
33
42
  * Workers can work multiple queues.
34
- * Reduced row contention using a [relaxed FIFO](http://www.cs.tau.ac.il/~shanir/nir-pubs-web/Papers/Lock_Free.pdf) technique.
35
43
 
36
- ## Table of content
44
+ ### Requirements
45
+ For this version, the requirements are as follows:
46
+ * Ruby 2.6, 2.7, 3.0, 3.1 - i.e. currently supported Ruby versions
47
+ * Postgres ~> 9.6
48
+ * Rubygem: pg ~> 1.1
37
49
 
38
- * [Documentation](http://rubydoc.info/gems/queue_classic/2.2.3/frames)
50
+ ## Table of contents
51
+ * [Documentation](https://www.rubydoc.info/gems/queue_classic/)
39
52
  * [Usage](#usage)
40
53
  * [Setup](#setup)
41
54
  * [Upgrade from earlier versions to V3.1](#upgrade-from-earlier-versions)
@@ -47,15 +60,14 @@ queue_classic provides a simple interface to a PostgreSQL-backed message queue.
47
60
  * [License](#license)
48
61
 
49
62
  ## Usage
50
-
51
- There are 2 ways to use queue_classic.
63
+ There are 2 ways to use queue_classic:
52
64
 
53
65
  * Producing Jobs
54
66
  * Working Jobs
55
67
 
56
68
  ### Producing Jobs
57
-
58
- The first argument is a string which represents a ruby object and a method name. The second argument(s) will be passed along as arguments to the method invocation defined by the first argument. The set of arguments will be encoded as JSON in the database.
69
+ #### Simple Enqueue
70
+ The first argument is a string which represents a ruby object and a method name. The second argument(s) will be passed along as arguments to the method defined by the first argument. The set of arguments will be encoded as JSON and stored in the database.
59
71
 
60
72
  ```ruby
61
73
  # This method has no arguments.
@@ -78,47 +90,50 @@ p_queue = QC::Queue.new("priority_queue")
78
90
  p_queue.enqueue("Kernel.puts", ["hello", "world"])
79
91
  ```
80
92
 
81
- There is also the possibility to schedule a job at a specified time in the future. It will not be worked off before that specified time.
93
+ #### Scheduling for later
94
+ There is also the ability to schedule a job to run at a specified time in the future. The job will become processable after the specified time, and will be processed as-soon-as-possible.
82
95
 
83
96
  ```ruby
84
- # Specifying the job execution time exactly.
97
+ # Specify the job execution time exactly
85
98
  QC.enqueue_at(Time.new(2024,01,02,10,00), "Kernel.puts", "hello future")
86
99
 
87
- # Specifying the job execution time as an offset in seconds.
100
+ # Specify the job execution time as an offset in seconds
88
101
  QC.enqueue_in(60, "Kernel.puts", "hello from 1 minute later")
89
102
  ```
90
103
 
91
104
  ### Working Jobs
92
-
93
- There are two ways to work jobs. The first approach is to use the Rake task. The second approach is to use a custom executable.
105
+ There are two ways to work/process jobs. The first approach is to use the Rake task. The second approach is to use a custom executable.
94
106
 
95
107
  #### Rake Task
96
-
97
- Require queue_classic in your Rakefile.
108
+ Require queue_classic in your Rakefile:
98
109
 
99
110
  ```ruby
100
111
  require 'queue_classic'
101
112
  require 'queue_classic/tasks'
102
113
  ```
103
114
 
104
- Start the worker via the Rakefile.
115
+ ##### Work all queues
116
+ Start the worker via the Rakefile:
117
+
105
118
  ```bash
106
- $ bundle exec rake qc:work
119
+ bundle exec rake qc:work
107
120
  ```
108
121
 
109
- Setup a worker to work a non-default queue.
122
+ ##### Work a single specific queue
123
+ Setup a worker to work only a specific, non-default queue:
124
+
110
125
  ```bash
111
- $ QUEUE="priority_queue" bundle exec rake qc:work
126
+ QUEUE="priority_queue" bundle exec rake qc:work
112
127
  ```
113
128
 
114
- Setup a worker to work multiple queues.
129
+ ##### Work multiple queues
130
+ In this scenario, on each iteration of the worker's loop, it will look for jobs in the first queue prior to looking at the second queue. This means that the first queue must be empty before the worker will look at the second queue.
131
+
115
132
  ```bash
116
- $ QUEUES="priority_queue,secondary_queue" bundle exec rake qc:work
133
+ QUEUES="priority_queue,secondary_queue" bundle exec rake qc:work
117
134
  ```
118
- In this scenario, on each iteration of the worker's loop, it will look for jobs in the first queue prior to looking at the second queue. This means that the first queue must be empty before the worker will look at the second queue.
119
135
 
120
136
  #### Custom Worker
121
-
122
137
  This example is probably not production ready; however, it serves as an example of how to leverage the code in the Worker class to fit your non-default requirements.
123
138
 
124
139
  ```ruby
@@ -128,7 +143,6 @@ require 'queue_classic'
128
143
  FailedQueue = QC::Queue.new("failed_jobs")
129
144
 
130
145
  class MyWorker < QC::Worker
131
-
132
146
  # A job is a Hash containing these attributes:
133
147
  # :id Integer, the job id
134
148
  # :method String, containing the object and method
@@ -141,7 +155,7 @@ class MyWorker < QC::Worker
141
155
  # Do something with the job
142
156
  ...
143
157
  end
144
-
158
+
145
159
  # This method will be called when an exception
146
160
  # is raised during the execution of the job.
147
161
  # First argument is the job that failed.
@@ -149,7 +163,6 @@ class MyWorker < QC::Worker
149
163
  def handle_failure(job, e)
150
164
  FailedQueue.enqueue(job[:method], *job[:args])
151
165
  end
152
-
153
166
  end
154
167
 
155
168
  worker = MyWorker.new
@@ -158,164 +171,128 @@ trap('INT') { exit }
158
171
  trap('TERM') { worker.stop }
159
172
 
160
173
  loop do
161
- job = worker.lock_job
162
- Timeout::timeout(5) { worker.process(job) }
174
+ queue, job = worker.lock_job
175
+ Timeout::timeout(5) { worker.process(queue, job) }
163
176
  end
164
177
  ```
165
178
 
166
- The `qc:work` rake task uses `QC::Worker` by default. However, it's easy to
167
- inject your own worker class:
179
+ The `qc:work` rake task uses `QC::Worker` by default. However, it's easy to inject your own worker class:
168
180
 
169
181
  ```ruby
170
182
  QC.default_worker_class = MyWorker
171
183
  ```
172
184
 
173
185
  ## Setup
174
-
175
- In addition to installing the rubygem, you will need to prepare your database. Database preparation includes creating a table and loading PL/pgSQL functions. You can issue the database preparation commands using `PSQL(1)` or use a database migration script.
186
+ In addition to installing the rubygem, you will need to prepare your database. Database preparation includes creating a table and loading PL/pgSQL functions. You can issue the database preparation commands using `psql` or use a database migration script.
176
187
 
177
188
  ### Quick Start
178
-
179
- ```bash
180
- $ gem install queue_classic
181
- $ createdb queue_classic_test
182
- $ export QC_DATABASE_URL="postgres://username:password@localhost/queue_classic_test"
183
- $ ruby -r queue_classic -e "QC::Setup.create"
184
- $ ruby -r queue_classic -e "QC.enqueue('Kernel.puts', 'hello world')"
185
- $ ruby -r queue_classic -e "QC::Worker.new.work"
189
+ ```bash{:copy}
190
+ gem install queue_classic
191
+ createdb queue_classic_test
192
+ export QC_DATABASE_URL="postgres://username:password@localhost/queue_classic_test"
193
+ ruby -r queue_classic -e "QC::Setup.create"
194
+ ruby -r queue_classic -e "QC.enqueue('Kernel.puts', 'hello world')"
195
+ ruby -r queue_classic -e "QC::Worker.new.work"
186
196
  ```
187
197
 
188
198
  ### Ruby on Rails Setup
199
+ Declare dependencies in Gemfile:
189
200
 
190
- Declare dependencies in Gemfile.
191
- ```ruby
192
- source "https://rubygems.org"
193
- gem "queue_classic", "~> 3.0.0"
201
+ ```ruby{:copy}
202
+ source 'https://rubygems.org' do
203
+ gem 'queue_classic'
204
+ end
194
205
  ```
195
206
 
196
- Add the database tables and stored procedures.
207
+ Install queue_classic, which adds the needed migrations for the database tables and stored procedures:
197
208
 
198
- ```
209
+ ```bash
199
210
  rails generate queue_classic:install
200
211
  bundle exec rake db:migrate
201
212
  ```
202
213
 
203
- #### Active Job
214
+ #### Database connection
215
+ Starting with with queue_classic 3.1, Rails is automatically detected and its connection is used. If you don't want to use the automatic database connection, set this environment variable to false: `export QC_RAILS_DATABASE=false`.
204
216
 
205
- If you use Rails 4.2+, all you need to do is to set `config.active_job.queue_adapter = :queue_classic` in your `application.rb`. Everything else will be taken care for you. You can now use the Active Job functionality from now.
217
+ > **Note:** If you do not share the connection, you cannot enqueue in the same transaction as whatever you're doing in Rails.
206
218
 
207
- Just for your information, queue_classic detects your database connection and uses it.
219
+ **Note on using ActiveRecord migrations:** If you use the migration, and you wish to use commands that reset the database from the stored schema (e.g. `rake db:reset`), your application must be configured with `config.active_record.schema_format = :sql` in `config/application.rb`. If you don't do this, the PL/pgSQL function that queue_classic creates will be lost when you reset the database.
208
220
 
209
- ### Rake Task Setup
221
+ #### Active Job
222
+ If you use Rails 4.2+ and want to use Active Job, all you need to do is to set `config.active_job.queue_adapter = :queue_classic` in your `application.rb`. Everything else will be taken care for you. You can now use the Active Job functionality from now.
210
223
 
211
- Alternatively, you can use the Rake task to prepare your database.
224
+ ### Plain Ruby Setup
225
+ If you're not using Rails, you can use the Rake task to prepare your database:
212
226
 
213
- ```bash
227
+ ```bash{:copy}
214
228
  # Creating the table and functions
215
- $ bundle exec rake qc:create
229
+ bundle exec rake qc:create
216
230
 
217
231
  # Dropping the table and functions
218
- $ bundle exec rake qc:drop
232
+ bundle exec rake qc:drop
219
233
  ```
220
234
 
221
- ### Database connection
235
+ #### Database connection
236
+ By default, queue_classic will use the `QC_DATABASE_URL` falling back on `DATABASE_URL`. The URL must be in the following format: `postgres://username:password@localhost/database_name`. If you use Heroku's PostgreSQL service, this will already be set. If you don't want to set this variable, you can set the connection in an initializer. **QueueClassic will maintain its own connection to the database.** This may double the number of connections to your database.
222
237
 
223
- #### Ruby on Rails
224
-
225
- Starting with with queue_classic 3.1, Rails is automatically detected and its connection is used.
226
-
227
- If you don't want to use the automatic database connection, set this environment variable to false: `export QC_RAILS_DATABASE=false`
228
-
229
- **Note on using ActiveRecord migrations:** If you use the migration, and you wish to use commands that reset the database from the stored schema (e.g. `rake db:reset`), your application must be configured with `config.active_record.schema_format = :sql` in `config/application.rb`. If you don't do this, the PL/pgSQL function that queue_classic creates will be lost when you reset the database.
230
-
231
-
232
- #### Other Ruby apps
233
-
234
- By default, queue_classic will use the QC_DATABASE_URL falling back on DATABASE_URL. The URL must be in the following format: `postgres://username:password@localhost/database_name`. If you use Heroku's PostgreSQL service, this will already be set. If you don't want to set this variable, you can set the connection in an initializer. **QueueClassic will maintain its own connection to the database.** This may double the number of connections to your database.
235
-
236
- ## Upgrade from earlier versions
238
+ ## Upgrading from earlier versions
237
239
  If you are upgrading from a previous version of queue_classic, you might need some new database columns and/or functions. Luckily enough for you, it is easy to do so.
238
240
 
239
241
  ### Ruby on Rails
242
+ These two commands will add the newer migrations:
240
243
 
241
- You just need to run those lines, which will copy the new required migrations:
242
-
243
- ```
244
+ ```bash{:copy}
244
245
  rails generate queue_classic:install
245
246
  bundle exec rake db:migrate
246
247
  ```
248
+
247
249
  ### Rake Task
250
+ This rake task will update you to the latest version:
248
251
 
249
- This rake task will get you covered:
250
- ```bash
252
+ ```bash{:copy}
251
253
  # Updating the table and functions
252
- $ bundle exec rake qc:update
254
+ bundle exec rake qc:update
253
255
  ```
254
256
 
255
257
  ## Configuration
256
-
257
258
  All configuration takes place in the form of environment vars. See [queue_classic.rb](https://github.com/QueueClassic/queue_classic/blob/master/lib/queue_classic.rb#L23-62) for a list of options.
258
259
 
259
- ## JSON
260
-
261
- If you are running PostgreSQL 9.4 or higher, queue_classic will use the [jsonb](http://www.postgresql.org/docs/9.4/static/datatype-json.html) datatype for new tables. Versions 9.2 and 9.3 will use the `json` data type and versions 9.1 and lower will use the `text` data type.
262
- If you are updating queue_classic and are running PostgreSQL >= 9.4, run the following to switch to `jsonb`:
263
- ```
264
- alter table queue_classic_jobs alter column args type jsonb using (args::jsonb);
265
- ```
266
-
267
260
  ## Logging
268
-
269
- By default queue_classic does not talk very much.
270
- If you find yourself in a situation where you need to know what's happening inside QC, there are two different kind of logging you can enable: DEBUG and MEASURE.
261
+ By default queue_classic does not talk very much. If you find yourself in a situation where you need to know what's happening inside QC, there are two different kind of logging you can enable: `DEBUG` and `MEASURE`.
271
262
 
272
263
  ### Measure
273
- This will output the time to process and that kind of thing. To enable it, set the `QC_MEASURE`:
264
+ This will output the time to process and some more statistics. To enable it, set the `QC_MEASURE`:
274
265
 
275
- ```
266
+ ```bash{:copy}
276
267
  export QC_MEASURE="true"
277
268
  ```
278
269
 
279
270
  ### Debug
280
271
  You can enable the debug output by setting the `DEBUG` environment variable:
281
272
 
282
- ```
273
+ ```bash{:copy}
283
274
  export DEBUG="true"
284
275
  ```
285
276
 
286
277
  ## Support
287
-
288
278
  If you think you have found a bug, feel free to open an issue. Use the following template for the new issue:
289
279
 
290
- 1. List Versions: Ruby, PostgreSQL, queue_classic.
280
+ 1. List your versions: Ruby, PostgreSQL, queue_classic.
291
281
  2. Define what you would have expected to happen.
292
282
  3. List what actually happened.
293
283
  4. Provide sample codes & commands which will reproduce the problem.
294
284
 
295
- If you have general questions about how to use queue_classic, send a message to the mailing list:
296
-
297
- https://groups.google.com/d/forum/queue_classic
298
-
299
285
  ## Hacking on queue_classic
300
-
301
- ### Dependencies
302
-
303
- * Ruby 1.9.2
304
- * Postgres ~> 9.0
305
- * Rubygem: pg ~> 0.11.0
306
- * For JRuby, see [queue_classic_java](https://github.com/bdon/queue_classic_java)
307
-
308
286
  ### Running Tests
309
-
310
- ```bash
311
- $ bundle
312
- $ createdb queue_classic_test
313
- $ export QC_DATABASE_URL="postgres://username:pass@localhost/queue_classic_test"
314
- $ rake
287
+ ```bash{:copy}
288
+ bundle
289
+ createdb queue_classic_test
290
+ export QC_DATABASE_URL="postgres://username:pass@localhost/queue_classic_test"
291
+ bundle exec rake # run all tests
292
+ bundle exec ruby test/queue_test.rb # run a single test
315
293
  ```
316
294
 
317
295
  ## License
318
-
319
296
  Copyright (C) 2010 Ryan Smith
320
297
 
321
298
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  $:.unshift("lib")
2
4
 
3
5
  require "bundler/gem_tasks"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rails/generators'
2
4
  require 'rails/generators/migration'
3
5
  require 'active_record'
@@ -31,6 +33,10 @@ module QC
31
33
  if self.class.migration_exists?('db/migrate', 'update_queue_classic_3_1_0').nil?
32
34
  migration_template 'update_queue_classic_3_1_0.rb', 'db/migrate/update_queue_classic_3_1_0.rb'
33
35
  end
36
+
37
+ if self.class.migration_exists?('db/migrate', 'update_queue_classic_4_0_0').nil?
38
+ migration_template 'update_queue_classic_4_0_0.rb', 'db/migrate/update_queue_classic_4_0_0.rb'
39
+ end
34
40
  end
35
41
  end
36
42
  end
@@ -1,4 +1,6 @@
1
- class AddQueueClassic < ActiveRecord::Migration
1
+ # frozen_string_literal: true
2
+
3
+ class AddQueueClassic < ActiveRecord::Migration[4.2]
2
4
  def self.up
3
5
  QC::Setup.create
4
6
  end
@@ -1,4 +1,6 @@
1
- class UpdateQueueClassic300 < ActiveRecord::Migration
1
+ # frozen_string_literal: true
2
+
3
+ class UpdateQueueClassic300 < ActiveRecord::Migration[4.2]
2
4
  def self.up
3
5
  QC::Setup.update_to_3_0_0
4
6
  end
@@ -1,4 +1,6 @@
1
- class UpdateQueueClassic302 < ActiveRecord::Migration
1
+ # frozen_string_literal: true
2
+
3
+ class UpdateQueueClassic302 < ActiveRecord::Migration[4.2]
2
4
  def self.up
3
5
  QC::Setup.update_to_3_0_0
4
6
  end
@@ -1,4 +1,6 @@
1
- class UpdateQueueClassic310 < ActiveRecord::Migration
1
+ # frozen_string_literal: true
2
+
3
+ class UpdateQueueClassic310 < ActiveRecord::Migration[4.2]
2
4
  def self.up
3
5
  QC::Setup.update_to_3_1_0
4
6
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UpdateQueueClassic400 < ActiveRecord::Migration[4.2]
4
+ def self.up
5
+ QC::Setup.update_to_4_0_0
6
+ end
7
+
8
+ def self.down
9
+ QC::Setup.downgrade_from_4_0_0
10
+ end
11
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module QC
2
4
  module Config
3
5
  # You can use the APP_NAME to query for
@@ -58,7 +60,6 @@ module QC
58
60
 
59
61
  # The worker class instantiated by QC's rake tasks.
60
62
  def default_worker_class
61
-
62
63
  @worker_class ||= (ENV["QC_DEFAULT_WORKER_CLASS"] && Kernel.const_get(ENV["QC_DEFAULT_WORKER_CLASS"]) ||
63
64
  QC::Worker)
64
65
 
@@ -1,27 +1,37 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
  require 'pg'
3
5
 
4
6
  module QC
5
7
  class ConnAdapter
6
8
 
7
- attr_accessor :connection
8
- def initialize(c=nil)
9
- @connection = c.nil? ? establish_new : validate!(c)
9
+ def initialize(args={})
10
+ @active_record_connection_share = args[:active_record_connection_share]
11
+ @_connection = args[:connection]
10
12
  @mutex = Mutex.new
11
13
  end
12
14
 
15
+ def connection
16
+ if @active_record_connection_share && Object.const_defined?('ActiveRecord')
17
+ ActiveRecord::Base.connection.raw_connection
18
+ else
19
+ @_connection ||= establish_new
20
+ end
21
+ end
22
+
13
23
  def execute(stmt, *params)
14
24
  @mutex.synchronize do
15
25
  QC.log(:at => "exec_sql", :sql => stmt.inspect)
16
26
  begin
17
27
  params = nil if params.empty?
18
- r = @connection.exec(stmt, params)
28
+ r = connection.exec(stmt, params)
19
29
  result = []
20
30
  r.each {|t| result << t}
21
31
  result.length > 1 ? result : result.pop
22
- rescue PGError => e
32
+ rescue PG::Error => e
23
33
  QC.log(:error => e.inspect)
24
- @connection.reset
34
+ connection.reset
25
35
  raise
26
36
  end
27
37
  end
@@ -30,10 +40,10 @@ module QC
30
40
  def wait(time, *channels)
31
41
  @mutex.synchronize do
32
42
  listen_cmds = channels.map {|c| 'LISTEN "' + c.to_s + '"'}
33
- @connection.exec(listen_cmds.join(';'))
43
+ connection.exec(listen_cmds.join(';'))
34
44
  wait_for_notify(time)
35
45
  unlisten_cmds = channels.map {|c| 'UNLISTEN "' + c.to_s + '"'}
36
- @connection.exec(unlisten_cmds.join(';'))
46
+ connection.exec(unlisten_cmds.join(';'))
37
47
  drain_notify
38
48
  end
39
49
  end
@@ -41,7 +51,7 @@ module QC
41
51
  def disconnect
42
52
  @mutex.synchronize do
43
53
  begin
44
- @connection.close
54
+ connection.close
45
55
  rescue => e
46
56
  QC.log(:at => 'disconnect', :error => e.message)
47
57
  end
@@ -59,12 +69,12 @@ module QC
59
69
 
60
70
  def wait_for_notify(t)
61
71
  Array.new.tap do |msgs|
62
- @connection.wait_for_notify(t) {|event, pid, msg| msgs << msg}
72
+ connection.wait_for_notify(t) {|event, pid, msg| msgs << msg}
63
73
  end
64
74
  end
65
75
 
66
76
  def drain_notify
67
- until @connection.notifies.nil?
77
+ until connection.notifies.nil?
68
78
  QC.log(:at => "drain_notifications")
69
79
  end
70
80
  end
@@ -77,10 +87,15 @@ module QC
77
87
 
78
88
  def establish_new
79
89
  QC.log(:at => "establish_conn")
80
- conn = PGconn.connect(*normalize_db_url(db_url))
81
- if conn.status != PGconn::CONNECTION_OK
90
+ conn = PG.connect(*normalize_db_url(db_url))
91
+ if conn.status != PG::CONNECTION_OK
82
92
  QC.log(:error => conn.error)
83
93
  end
94
+
95
+ if conn.server_version < 90600
96
+ raise "This version of Queue Classic does not support Postgres older than 9.6 (90600). This version is #{conn.server_version}. If you need that support, please use an older version."
97
+ end
98
+
84
99
  conn.exec("SET application_name = '#{QC.app_name}'")
85
100
  conn
86
101
  end
@@ -92,7 +107,7 @@ module QC
92
107
  [
93
108
  host, # host or percent-encoded socket path
94
109
  url.port || 5432,
95
- nil, '', #opts, tty
110
+ nil, nil, #opts, tty
96
111
  url.path.gsub("/",""), # database name
97
112
  url.user,
98
113
  url.password
@@ -106,6 +121,5 @@ module QC
106
121
  raise(ArgumentError, "missing QC_DATABASE_URL or DATABASE_URL")
107
122
  @db_url = URI.parse(url)
108
123
  end
109
-
110
124
  end
111
125
  end