queue_classic 3.1.0 → 3.2.0.RC1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 88e26c8a7314c7ffca4aac79bf29fac181a304f4
4
- data.tar.gz: 9d92ce5e8c313ea9a81c66b769b77a1c80265745
3
+ metadata.gz: 173f9534b0c2b7318cccdf7de96b762ee63306d3
4
+ data.tar.gz: c808e6bc17371a57e997c13800ba803666be969e
5
5
  SHA512:
6
- metadata.gz: 8fa62030bb04d3464d2772a6b68c2b9d0d698d2ed146125b69b2a72b2bdb5a2d79f63424e4a676f13e2f981b980e53d8534caf01f906ed575e5c31630b9da1f4
7
- data.tar.gz: 8f257e023700a47ff33f4b449f5df73fdb37f06dbbf338583ba244196f1883ff1670484cd4267f3e081526a504552aba5b9aebcda72de8cc951a0d3b6f83d572
6
+ metadata.gz: 7065d297515c3cd9bc40ac5f93a36f164d124f812dc2c53a649b163aceecf9995ebc07bee273660a4540defd08b95afc5b0b69f7b6af1491fd25f8c61cdbb927
7
+ data.tar.gz: 9f4abe2f2f6c58a5bc4f049b0851d63e730c2922dcf8141a14222e01e2900c7993db939033925ebb684c88b6452e689269c3bbccb2e7386a60a4eacf24308aed
@@ -0,0 +1,9 @@
1
+ .db
2
+ .ruby-version
3
+ .bundle
4
+ .rvmrc
5
+ etc/
6
+ *.gem
7
+ .env
8
+ Gemfile.lock
9
+ tips-and-tricks.md
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ before_script:
3
+ - psql -c 'create database queue_classic_test;' -U postgres
4
+ env:
5
+ global:
6
+ - QC_DATABASE_URL="postgres://postgres@localhost/queue_classic_test"
7
+ - QC_BENCHMARK=true
8
+ - QC_BENCHMARK_MAX_TIME_DEQUEUE=60
9
+ rvm:
10
+ - 2.2
11
+ - 2.1
12
+ - 2.0.0
13
+ - 1.9.3
14
+ addons:
15
+ postgresql: 9.3
@@ -0,0 +1,17 @@
1
+ queue_classic is a volunteer effort. We encourage you to pitch in.
2
+
3
+ 1. Fork queue_classic
4
+ 2. Create a topic branch - `git checkout -b my_branch`
5
+ 3. Push to your branch - `git push origin my_branch`
6
+ 4. Send us a pull-request for your topic branch
7
+ 5. That's it!
8
+
9
+ If you make code changes, please check that your patch:
10
+
11
+ 1. has tests
12
+ 2. works on Rails and non-Rails projects
13
+ 3. updates documentation
14
+
15
+ Thanks! :heart:
16
+
17
+ queue_classic Team
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rake"
4
+
5
+ gemspec
6
+
7
+ group :test do
8
+ gem 'minitest', '~> 5.5.1'
9
+ end
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -13,8 +13,9 @@
13
13
 
14
14
  **IMPORTANT NOTE REGARDING VERSIONS**
15
15
 
16
- **This README is representing the current work for queue_classic 3.1. You can find the README for other versions:**
16
+ **This README is representing the current work for queue_classic edge [unstable]. You can find the README for other versions:**
17
17
 
18
+ - current release candidate: [v3.1.X](https://github.com/QueueClassic/queue_classic/tree/3-1-stable)
18
19
  - latest stable can be found: [v3.0.X](https://github.com/QueueClassic/queue_classic/tree/3-0-stable)
19
20
  - older stable: [v2.2.3](https://github.com/QueueClassic/queue_classic/tree/v2.2.3)
20
21
 
@@ -127,15 +128,34 @@ require 'queue_classic'
127
128
  FailedQueue = QC::Queue.new("failed_jobs")
128
129
 
129
130
  class MyWorker < QC::Worker
131
+
132
+ # A job is a Hash containing these attributes:
133
+ # :id Integer, the job id
134
+ # :method String, containing the object and method
135
+ # :args String, the arguments
136
+ # :q_name String, the queue name
137
+ # :scheduled_at Time, the scheduled time if the job was scheduled
138
+
139
+ # Execute the job using the methods and arguments
140
+ def call(job)
141
+ # Do something with the job
142
+ ...
143
+ end
144
+
145
+ # This method will be called when an exception
146
+ # is raised during the execution of the job.
147
+ # First argument is the job that failed.
148
+ # Second argument is the exception.
130
149
  def handle_failure(job, e)
131
150
  FailedQueue.enqueue(job[:method], *job[:args])
132
151
  end
152
+
133
153
  end
134
154
 
135
155
  worker = MyWorker.new
136
156
 
137
- trap('INT') {exit}
138
- trap('TERM') {worker.stop}
157
+ trap('INT') { exit }
158
+ trap('TERM') { worker.stop }
139
159
 
140
160
  loop do
141
161
  job = worker.lock_job
@@ -143,6 +163,13 @@ loop do
143
163
  end
144
164
  ```
145
165
 
166
+ The `qc:work` rake task uses `QC::Worker` by default. However, it's easy to
167
+ inject your own worker class:
168
+
169
+ ```ruby
170
+ QC.default_worker_class = MyWorker
171
+ ```
172
+
146
173
  ## Setup
147
174
 
148
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.
@@ -162,7 +189,7 @@ $ ruby -r queue_classic -e "QC::Worker.new.work"
162
189
 
163
190
  Declare dependencies in Gemfile.
164
191
  ```ruby
165
- source "http://rubygems.org"
192
+ source "https://rubygems.org"
166
193
  gem "queue_classic", "~> 3.0.0"
167
194
  ```
168
195
 
@@ -231,9 +258,10 @@ All configuration takes place in the form of environment vars. See [queue_classi
231
258
 
232
259
  ## JSON
233
260
 
234
- If you are running PostgreSQL 9.2 or higher, queue_classic will use the [json](http://www.postgresql.org/docs/9.2/static/datatype-json.html) datatype for storing arguments. Versions 9.1 and lower will use the 'text' column. If you have installed queue_classic prior to version 2.1.4 and are running PostgreSQL >= 9.2, run the following to switch to using the json type:
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`:
235
263
  ```
236
- alter table queue_classic_jobs alter column args type json using (args::json);
264
+ alter table queue_classic_jobs alter column args type jsonb using (args::jsonb);
237
265
  ```
238
266
 
239
267
  ## Logging
@@ -272,7 +300,7 @@ https://groups.google.com/d/forum/queue_classic
272
300
 
273
301
  ### Dependencies
274
302
 
275
- * Ruby 1.9.2 (tests work in 1.8.7 but compatibility is not guaranteed or supported)
303
+ * Ruby 1.9.2
276
304
  * Postgres ~> 9.0
277
305
  * Rubygem: pg ~> 0.11.0
278
306
  * For JRuby, see [queue_classic_java](https://github.com/bdon/queue_classic_java)
@@ -0,0 +1,14 @@
1
+ $:.unshift("lib")
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+ require "./lib/queue_classic"
6
+ require "./lib/queue_classic/tasks"
7
+
8
+ task :default => ['test']
9
+ Rake::TestTask.new do |t|
10
+ t.libs << 'test'
11
+ t.test_files = FileList['test/**/*_test.rb']
12
+ t.verbose = true
13
+ t.warning = true
14
+ end
@@ -0,0 +1,146 @@
1
+ Unreleased
2
+ - Fixed a bug in the offset calculation of `.enqueue_at`.
3
+ - Use the jsonb type for the args column from now on. If not available, fall back to json or text.
4
+ - `enqueue`, `enqueue_at`, `enqueue_in` return job hash with id.
5
+ - Fixed unlock query for versions below Postgres 9.2
6
+
7
+ Version 3.0.0rc
8
+ - Improved signal handling
9
+
10
+ Version 3.0.0beta
11
+ - Workers can process many queues.
12
+
13
+ Version 2.2.3
14
+ - Update pg dependency to 0.17.0
15
+
16
+ Version 2.3.0beta [YANKED]
17
+ - Concurrent job processing.
18
+
19
+ Version 2.2.2
20
+ - Update pg dependency to 0.16.0
21
+
22
+ Version 2.2.1
23
+ - Force listen/notify on worker
24
+ - Notifications happen inside PostgreSQL trigger
25
+ - Add rake task for generating rails migrations
26
+ - Fix bug related to listening worker
27
+
28
+ Version 2.2.0
29
+ - Use json from the stdlib in place of MultiJson.
30
+ - Use postgresql's json type for the args column if json type is available
31
+ - QC::Worker#handle_failure logs the job and the error
32
+ - QC.default_queue= to set your own default queue. (can be used
33
+ in testing to configure a mock queue)
34
+ - QC.log now reports time elapsed in milliseconds.
35
+
36
+ Version 2.1.4
37
+ - Update pg dependency to 0.15.1
38
+ - Document logging behaviour
39
+
40
+ Version 2.1.3
41
+ - Use MultiJson (Ezekiel Templin: #106)
42
+
43
+ Version 2.1.2
44
+ - Use 64bit ints as default data types in PostgreSQL
45
+ - Add process method in worker
46
+ - Allow percent-encoded socket paths in DATABASE_URL
47
+
48
+ Version 2.1.1
49
+ - Update pg gem version
50
+
51
+ Version 2.1.0
52
+ - Wrap connection execution in mutex making it thread safe
53
+ - Cleanup logging
54
+ - Refactor worker class making it more extensible
55
+ - Added rdoc style docs for worker class
56
+
57
+ Version 2.0.5
58
+ - Allow term signal to halt the lock_job function
59
+
60
+ Version 2.0.4
61
+ - Provider a connection setter.
62
+
63
+ Version 2.0.3
64
+ - Fix typo :(
65
+
66
+ Version 2.0.2
67
+ - Remove scrolls dependency
68
+ - Fix issue with notify not working on non-default queues
69
+
70
+ Version 2.0.1
71
+
72
+ Version 2.0.0
73
+ - Simpler setup via QC::Setup.create (rake qc:create) & QC::Setup.drop (rake
74
+ qc:drop)
75
+ - Simpler abstractions in implementation
76
+ - Better support for instrumentation via log_yield hook in QC module
77
+ - Multiple queues use one table with a queue_name column
78
+
79
+ Version 1.0.2
80
+ - Update to latest okjson as the current has bugs
81
+
82
+ Version 1.0.1
83
+ - Using OkJson instead of any sort of rubygem
84
+ - Remove html from docs
85
+ - Use parameterised queries
86
+ - Don't set application name by default
87
+ - Injection attack bug fixed in lock_head()
88
+ - Notificaiton get sent on seperate chans for disjoint queues
89
+
90
+ Version 1.0.0rc1
91
+ - Removed json gem and relying on ruby 1.9.2's stdlib
92
+ - Added better documentation
93
+
94
+ Version 0.3.6pre
95
+ - Added listen/notify support configured by $QC_LISTENING_WORKER otherwise uses Kernel.sleep()
96
+
97
+ Version 0.3.5pre
98
+ - Removed debug statement. Mistake!
99
+
100
+ Version 0.3.4pre
101
+ - Added logging configured by $VERBOSE or $QC_VERBOSE.
102
+ - Added a method setup_child that gets called right after a worker forks.
103
+ - Removed database helper methods: create_table, drop_table, silence_warnings.
104
+ - Removed queue connection helper methods. Status should be discoverd by psql or the likes.
105
+
106
+ Version 0.3.3pre
107
+ - Removed PUB/SUB
108
+ - Added GC after working a job
109
+ - Added support for a database_url other than $DATABASE_URL. $QC_DATABASE_URL
110
+ - Added exp backoff configured by $QC_MAX_LOCK_ATTEMPTS (default = 5)
111
+ - Added option for forking worker configured by $QC_FORK_WORKER (default = false)
112
+
113
+ Version 0.3.2
114
+ - Fixed bug which caused workers to consume 2 connections. Now they only consume 1
115
+ - Added a rake file for tests
116
+ - Added support for postgres:///db_name DATABASE_URLs
117
+
118
+ Version 0.3.1
119
+ - Added query interface for introspection success
120
+ - Moved the locking of jobs into the DB as a PG function. SELECT lock_head()
121
+ - Added requirement for DB connection. MUST BE URI i.e. DATABASE_URL=postgres://user:pass@localhost/db_name
122
+ - Added rake qc:create_queue. This task will add a new table. Use this for multiple queues.
123
+ - Added a bit of randomness to the lock_head() function. Helps you scale to a hilarious number of workers.
124
+ - Added support for trapping INT and TERM signals in the worker. ^C to stop after finished and ^C^C to kill.
125
+ - Renamed the jobs table to queue_classic_jobs
126
+ - Renamed the jobs channel to queue_classic_jobs
127
+ - Added support for multiple queues
128
+
129
+ Version 0.2.2
130
+ - Fixed problems with enqueueing a list of parameters.
131
+
132
+ Version 0.2.1
133
+ - Added method for handling errors.
134
+ - Added ability to enqueue a Job instance. Makes retrying jobs easier.
135
+ - Added delete_all.
136
+ - Fixed connection algorithm. 1 connection per process.
137
+ - Fixed API for enqueue. Now accepting 1 arg or many args.
138
+
139
+ Version 0.2.0
140
+ - Beta Release
141
+ - Added method for handling failed jobs
142
+ - Added Benchmarks
143
+ - Removed logging
144
+ - Moved the Job class into it's own file
145
+
146
+ 0.1.6
@@ -1,40 +1,42 @@
1
+ require_relative "queue_classic/config"
2
+
1
3
  module QC
2
- # You can use the APP_NAME to query for
3
- # postgres related process information in the
4
- # pg_stat_activity table.
5
- APP_NAME = ENV["QC_APP_NAME"] || "queue_classic"
6
-
7
- # Number of seconds to block on the listen chanel for new jobs.
8
- WAIT_TIME = (ENV["QC_LISTEN_TIME"] || 5).to_i
9
-
10
- # Why do you want to change the table name?
11
- # Just deal with the default OK?
12
- # If you do want to change this, you will
13
- # need to update the PL/pgSQL lock_head() function.
14
- # Come on. Don't do it.... Just stick with the default.
15
- TABLE_NAME = "queue_classic_jobs"
16
-
17
- # Each row in the table will have a column that
18
- # notes the queue. You can point your workers
19
- # at different queues but only one at a time.
20
- QUEUE = ENV["QUEUE"] || "default"
21
- QUEUES = (ENV["QUEUES"] && ENV["QUEUES"].split(",")) || []
22
-
23
- # Set this to 1 for strict FIFO.
24
- # There is nothing special about 9....
25
- TOP_BOUND = (ENV["QC_TOP_BOUND"] || 9).to_i
26
-
27
- # Set this variable if you wish for
28
- # the worker to fork a UNIX process for
29
- # each locked job. Remember to re-establish
30
- # any database connections. See the worker
31
- # for more details.
32
- FORK_WORKER = !ENV["QC_FORK_WORKER"].nil?
4
+ extend QC::Config
5
+
6
+ # Assign constants for backwards compatibility.
7
+ # They should no longer be used. Prefer the corresponding methods.
8
+ # See +QC::Config+ for more details.
9
+ DEPRECATED_CONSTANTS = {
10
+ :APP_NAME => :app_name,
11
+ :WAIT_TIME => :wait_time,
12
+ :TABLE_NAME => :table_name,
13
+ :QUEUE => :queue,
14
+ :QUEUES => :queues,
15
+ :TOP_BOUND => :top_bound,
16
+ :FORK_WORKER => :fork_worker?,
17
+ }
18
+
19
+ def self.const_missing(const_name)
20
+ if DEPRECATED_CONSTANTS.key? const_name
21
+ config_method = DEPRECATED_CONSTANTS[const_name]
22
+ $stderr.puts <<-MSG
23
+ The constant QC::#{const_name} is deprecated and will be removed in the future.
24
+ Please use the method QC.#{config_method} instead.
25
+ MSG
26
+ QC.public_send config_method
27
+ else
28
+ super
29
+ end
30
+ end
33
31
 
34
32
  # Defer method calls on the QC module to the
35
33
  # default queue. This facilitates QC.enqueue()
36
34
  def self.method_missing(sym, *args, &block)
37
- default_queue.send(sym, *args, &block)
35
+ if default_queue.respond_to? sym
36
+ default_queue.public_send(sym, *args, &block)
37
+ else
38
+ super
39
+ end
38
40
  end
39
41
 
40
42
  # Ensure QC.respond_to?(:enqueue) equals true (ruby 1.9 only)
@@ -42,37 +44,29 @@ module QC
42
44
  default_queue.respond_to?(method_name)
43
45
  end
44
46
 
45
- def self.default_queue=(queue)
46
- @default_queue = queue
47
- end
48
-
49
- def self.default_queue
50
- @default_queue ||= begin
51
- Queue.new(QUEUE)
52
- end
53
- end
54
-
55
47
  def self.has_connection?
56
48
  !default_conn_adapter.nil?
57
49
  end
58
50
 
59
51
  def self.default_conn_adapter
60
- return @conn_adapter if defined?(@conn_adapter) && @conn_adapter
61
- if rails_connection_sharing_enabled?
62
- @conn_adapter = ConnAdapter.new(ActiveRecord::Base.connection.raw_connection)
52
+ t = Thread.current
53
+ return t[:qc_conn_adapter] if t[:qc_conn_adapter]
54
+ adapter = if rails_connection_sharing_enabled?
55
+ ConnAdapter.new(ActiveRecord::Base.connection.raw_connection)
63
56
  else
64
- @conn_adapter = ConnAdapter.new
57
+ ConnAdapter.new
65
58
  end
66
- @conn_adapter
59
+
60
+ t[:qc_conn_adapter] = adapter
67
61
  end
68
62
 
69
63
  def self.default_conn_adapter=(conn)
70
- @conn_adapter = conn
64
+ Thread.current[:qc_conn_adapter] = conn
71
65
  end
72
66
 
73
67
  def self.log_yield(data)
68
+ t0 = Time.now
74
69
  begin
75
- t0 = Time.now
76
70
  yield
77
71
  rescue => e
78
72
  log({:at => "error", :error => e.inspect}.merge(data))
@@ -106,7 +100,8 @@ module QC
106
100
  # This will unlock all jobs any postgres' PID that is not existing anymore
107
101
  # to prevent any infinitely locked jobs
108
102
  def self.unlock_jobs_of_dead_workers
109
- default_conn_adapter.execute("UPDATE #{QC::TABLE_NAME} SET locked_at = NULL, locked_by = NULL WHERE locked_by NOT IN (SELECT pid FROM pg_stat_activity);")
103
+ pid_column = default_conn_adapter.server_version < 90200 ? "procpid" : "pid"
104
+ default_conn_adapter.execute("UPDATE #{QC.table_name} SET locked_at = NULL, locked_by = NULL WHERE locked_by NOT IN (SELECT #{pid_column} FROM pg_stat_activity);")
110
105
  end
111
106
 
112
107
  # private class methods