queue_classic 3.0.0rc → 3.0.0

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: 549f3341849e84bc2068f82448e39e98c0ef2051
4
- data.tar.gz: 0746db47bbe386bd31e348b9d925985e8b185c04
3
+ metadata.gz: 3558784567b56e6d75e1c872aaecf392e2bbfcf7
4
+ data.tar.gz: e4f6f925b2db3333b93216b4caee0ebe76ee0662
5
5
  SHA512:
6
- metadata.gz: 5d9d9f8e660d294671ef3fd6d99f96fa2e092049920f72b754c62fa59857466978e6a7f10544fd35de9e52e6d72d99fb51dadb08cc2c0b8b002906f6628fe672
7
- data.tar.gz: 3174b46493945c6b126323fa20dbaa1bf53bfd40a6ff07926a934ea4820e5e67276331d872d77e182fc57127e590f916a2042b48df9e9bee63965cd4d0f20f26
6
+ metadata.gz: c82dbc205598a39eb6d0d35dec8accaeb5a7cf3b0dea45cd76a9a9b55c4fab6802b0eb86720b9805f0a37abe23919873706386063b4ec52f3050ea2d22c9ed1f
7
+ data.tar.gz: d14075365a1c02a36350ce9c6fc986772425abda40e8ce45bdf97eb55e91979d970b57339c735cf135ec6878aaa353790b7fda9c1cebca2e9124ec9c1000bed4
@@ -16,7 +16,13 @@ module QC
16
16
  end
17
17
 
18
18
  def create_migration_file
19
- migration_template 'add_queue_classic.rb', 'db/migrate/add_queue_classic.rb'
19
+ if self.class.migration_exists?('db/migrate', 'add_queue_classic').nil?
20
+ migration_template 'add_queue_classic.rb', 'db/migrate/add_queue_classic.rb'
21
+ end
22
+
23
+ if self.class.migration_exists?('db/migrate', 'update_queue_classic_3_0_0').nil?
24
+ migration_template 'update_queue_classic_3_0_0.rb', 'db/migrate/update_queue_classic_3_0_0.rb'
25
+ end
20
26
  end
21
27
  end
22
28
  end
@@ -0,0 +1,9 @@
1
+ class UpdateQueueClassic300 < ActiveRecord::Migration
2
+ def self.up
3
+ QC::Setup.update_to_3_0_0
4
+ end
5
+
6
+ def self.down
7
+ QC::Setup.downgrade_from_3_0_0
8
+ end
9
+ end
@@ -52,10 +52,18 @@ module QC
52
52
  end
53
53
  end
54
54
 
55
+ def self.has_connection?
56
+ !@conn_adapter.nil?
57
+ end
58
+
55
59
  def self.default_conn_adapter
56
60
  @conn_adapter ||= ConnAdapter.new
57
61
  end
58
62
 
63
+ def self.default_conn_adapter=(conn)
64
+ @conn_adapter = conn
65
+ end
66
+
59
67
  def self.log_yield(data)
60
68
  begin
61
69
  t0 = Time.now
@@ -83,9 +91,21 @@ module QC
83
91
  puts(out) if ENV["DEBUG"]
84
92
  return result
85
93
  end
94
+
95
+ def self.measure(data)
96
+ if ENV['QC_MEASURE']
97
+ $stdout.puts("measure#qc.#{data}")
98
+ end
99
+ end
100
+
101
+ # This will unlock all jobs any postgres' PID that is not existing anymore
102
+ # to prevent any infinitely locked jobs
103
+ def self.unlock_jobs_of_dead_workers
104
+ @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);")
105
+ end
86
106
  end
87
107
 
88
- require "queue_classic/queue"
89
- require "queue_classic/worker"
90
- require "queue_classic/setup"
91
- require "queue_classic/railtie" if defined?(Rails)
108
+ require_relative "queue_classic/queue"
109
+ require_relative "queue_classic/worker"
110
+ require_relative "queue_classic/setup"
111
+ require_relative "queue_classic/railtie" if defined?(Rails)
@@ -30,10 +30,10 @@ module QC
30
30
 
31
31
  def wait(time, *channels)
32
32
  @mutex.synchronize do
33
- listen_cmds = channels.map {|c| 'LISTEN "' + c + '"'}
33
+ listen_cmds = channels.map {|c| 'LISTEN "' + c.to_s + '"'}
34
34
  @connection.exec(listen_cmds.join(';'))
35
35
  wait_for_notify(time)
36
- unlisten_cmds = channels.map {|c| 'UNLISTEN "' + c +'"'}
36
+ unlisten_cmds = channels.map {|c| 'UNLISTEN "' + c.to_s + '"'}
37
37
  @connection.exec(unlisten_cmds.join(';'))
38
38
  drain_notify
39
39
  end
@@ -1,6 +1,6 @@
1
- require 'queue_classic'
2
- require 'queue_classic/conn_adapter'
1
+ require_relative 'conn_adapter'
3
2
  require 'json'
3
+ require 'time'
4
4
 
5
5
  module QC
6
6
  # The queue class maps a queue abstraction onto a database table.
@@ -45,9 +45,17 @@ module QC
45
45
  QC.log_yield(:measure => 'queue.lock') do
46
46
  s = "SELECT * FROM lock_head($1, $2)"
47
47
  if r = conn_adapter.execute(s, name, top_bound)
48
- {:id => r["id"],
49
- :method => r["method"],
50
- :args => JSON.parse(r["args"])}
48
+ {}.tap do |job|
49
+ job[:id] = r["id"]
50
+ job[:q_name] = r["q_name"]
51
+ job[:method] = r["method"]
52
+ job[:args] = JSON.parse(r["args"])
53
+ if r["created_at"]
54
+ job[:created_at] = Time.parse(r["created_at"])
55
+ ttl = Integer((Time.now - job[:created_at]) * 1000)
56
+ QC.measure("time-to-lock=#{ttl}ms source=#{name}")
57
+ end
58
+ end
51
59
  end
52
60
  end
53
61
  end
@@ -4,19 +4,40 @@ module QC
4
4
  SqlFunctions = File.join(Root, "/sql/ddl.sql")
5
5
  CreateTable = File.join(Root, "/sql/create_table.sql")
6
6
  DropSqlFunctions = File.join(Root, "/sql/drop_ddl.sql")
7
+ UpgradeTo_3_0_0 = File.join(Root, "/sql/update_to_3_0_0.sql")
8
+ DowngradeTo_3_0_0 = File.join(Root, "/sql/downgrade_from_3_0_0.sql")
7
9
 
8
- def self.create(c=nil)
10
+ def self.create(c = QC::default_conn_adapter.connection)
9
11
  conn = QC::ConnAdapter.new(c)
10
12
  conn.execute(File.read(CreateTable))
11
13
  conn.execute(File.read(SqlFunctions))
12
14
  conn.disconnect if c.nil? #Don't close a conn we didn't create.
13
15
  end
14
16
 
15
- def self.drop(c=nil)
17
+ def self.drop(c = QC::default_conn_adapter.connection)
16
18
  conn = QC::ConnAdapter.new(c)
17
19
  conn.execute("DROP TABLE IF EXISTS queue_classic_jobs CASCADE")
18
20
  conn.execute(File.read(DropSqlFunctions))
19
21
  conn.disconnect if c.nil? #Don't close a conn we didn't create.
20
22
  end
23
+
24
+ def self.update(c = QC::default_conn_adapter.connection)
25
+ conn = QC::ConnAdapter.new(c)
26
+ conn.execute(File.read(UpgradeTo_3_0_0))
27
+ conn.execute(File.read(DropSqlFunctions))
28
+ conn.execute(File.read(SqlFunctions))
29
+ end
30
+
31
+ def self.update_to_3_0_0(c = QC::default_conn_adapter.connection)
32
+ conn = QC::ConnAdapter.new(c)
33
+ conn.execute(File.read(UpgradeTo_3_0_0))
34
+ conn.execute(File.read(DropSqlFunctions))
35
+ conn.execute(File.read(SqlFunctions))
36
+ end
37
+
38
+ def self.downgrade_from_3_0_0(c = QC::default_conn_adapter.connection)
39
+ conn = QC::ConnAdapter.new(c)
40
+ conn.execute(File.read(DowngradeTo_3_0_0))
41
+ end
21
42
  end
22
43
  end
@@ -41,4 +41,9 @@ namespace :qc do
41
41
  task :drop => :environment do
42
42
  QC::Setup.drop
43
43
  end
44
+
45
+ desc "Update queue_classic tables and functions in database"
46
+ task :update => :environment do
47
+ QC::Setup.update
48
+ end
44
49
  end
@@ -1,6 +1,5 @@
1
- require 'queue_classic'
2
- require 'queue_classic/queue'
3
- require 'queue_classic/conn_adapter'
1
+ require_relative 'queue'
2
+ require_relative 'conn_adapter'
4
3
 
5
4
  module QC
6
5
  # A Worker object can process jobs from one or many queues.
@@ -19,7 +18,13 @@ module QC
19
18
  def initialize(args={})
20
19
  @fork_worker = args[:fork_worker] || QC::FORK_WORKER
21
20
  @wait_interval = args[:wait_interval] || QC::WAIT_TIME
22
- @conn_adapter = ConnAdapter.new(args[:connection])
21
+
22
+ if args[:connection]
23
+ @conn_adapter = ConnAdapter.new(args[:connection])
24
+ elsif QC.has_connection?
25
+ @conn_adapter = QC.default_conn_adapter
26
+ end
27
+
23
28
  @queues = setup_queues(@conn_adapter,
24
29
  (args[:q_name] || QC::QUEUE),
25
30
  (args[:q_names] || QC::QUEUES),
@@ -34,6 +39,8 @@ module QC
34
39
  # The canonical example of starting a worker is as follows:
35
40
  # QC::Worker.new.start
36
41
  def start
42
+ QC.unlock_jobs_of_dead_workers
43
+
37
44
  while @running
38
45
  @fork_worker ? fork_and_work : work
39
46
  end
@@ -97,6 +104,7 @@ module QC
97
104
  # If the job is not finished and an INT signal is traped,
98
105
  # this method will unlock the job in the queue.
99
106
  def process(queue, job)
107
+ start = Time.now
100
108
  finished = false
101
109
  begin
102
110
  call(job).tap do
@@ -110,6 +118,8 @@ module QC
110
118
  if !finished
111
119
  queue.unlock(job[:id])
112
120
  end
121
+ ttp = Integer((Time.now - start) * 1000)
122
+ QC.measure("time-to-process=#{ttp} source=#{queue.name}")
113
123
  end
114
124
  end
115
125
 
@@ -126,7 +136,7 @@ module QC
126
136
  # This method will be called when an exception
127
137
  # is raised during the execution of the job.
128
138
  def handle_failure(job,e)
129
- log(:at => "handle_failure", :job => job, :error => e.inspect)
139
+ $stderr.puts("count#qc.job-error=1 job=#{job} error=#{e.inspect}")
130
140
  end
131
141
 
132
142
  # This method should be overriden if
data/readme.md CHANGED
@@ -1,7 +1,10 @@
1
1
  # queue_classic
2
2
 
3
+ [![Build Status](https://travis-ci.org/ryandotsmith/queue_classic.svg?branch=master)](https://travis-ci.org/ryandotsmith/queue_classic)
4
+ [![Code Climate](https://codeclimate.com/github/ryandotsmith/queue_classic.png)](https://codeclimate.com/github/ryandotsmith/queue_classic)
5
+
3
6
  Stable: [v2.2.3](https://github.com/ryandotsmith/queue_classic/tree/v2.2.3)
4
- Latest: v3.0.0beta
7
+ Latest: v3.0.0rc
5
8
 
6
9
  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.
7
10
 
@@ -19,7 +22,10 @@ Contents:
19
22
  * [Documentation](http://rubydoc.info/gems/queue_classic/2.2.3/frames)
20
23
  * [Usage](#usage)
21
24
  * [Setup](#setup)
25
+ * [Upgrade from V2 to V3](#upgrade-from-v2-to-v3)
22
26
  * [Configuration](#configuration)
27
+ * [JSON](#json)
28
+ * [Logging](#logging)
23
29
  * [Support](#support)
24
30
  * [Hacking](#hacking-on-queue_classic)
25
31
  * [License](#license)
@@ -165,6 +171,25 @@ $ bundle exec rake qc:create
165
171
  $ bundle exec rake qc:drop
166
172
  ```
167
173
 
174
+ ## Upgrade from V2 to V3
175
+ 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.
176
+
177
+ ### Ruby on Rails
178
+
179
+ You just need to run those lines, which will copy the new required migrations:
180
+
181
+ ```
182
+ rails generate queue_classic:install
183
+ rake db:migrate
184
+ ```
185
+ ### Rake Task
186
+
187
+ This rake task will get you covered:
188
+ ```bash
189
+ # Updating the table and functions
190
+ $ bundle exec rake qc:update
191
+ ```
192
+
168
193
  ## Configuration
169
194
 
170
195
  All configuration takes place in the form of environment vars. See [queue_classic.rb](https://github.com/ryandotsmith/queue_classic/blob/master/lib/queue_classic.rb#L23-62) for a list of options.
@@ -179,8 +204,17 @@ alter table queue_classic_jobs alter column args type json using (args::json);
179
204
  ## Logging
180
205
 
181
206
  By default queue_classic does not talk very much.
182
- If you find yourself in a situation where you need to know what's happening inside QC,
183
- you can enable the debug output by setting the `DEBUG` environment variable:
207
+ 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.
208
+
209
+ ### Measure
210
+ This will output the time to process and that kind of thing. To enable it, set the `QC_MEASURE`:
211
+
212
+ ```
213
+ export QC_MEASURE="true"
214
+ ```
215
+
216
+ ### Debug
217
+ You can enable the debug output by setting the `DEBUG` environment variable:
184
218
 
185
219
  ```
186
220
  export DEBUG="true"
@@ -201,7 +235,8 @@ https://groups.google.com/d/forum/queue_classic
201
235
 
202
236
  ## Hacking on queue_classic
203
237
 
204
- [![Build Status](https://drone.io/github.com/ryandotsmith/queue_classic/status.png)](https://drone.io/github.com/ryandotsmith/queue_classic/latest)
238
+ [![Build Status](https://travis-ci.org/ryandotsmith/queue_classic.svg?branch=master)](https://travis-ci.org/ryandotsmith/queue_classic)
239
+ [![Code Climate](https://codeclimate.com/github/ryandotsmith/queue_classic.png)](https://codeclimate.com/github/ryandotsmith/queue_classic)
205
240
 
206
241
  ### Dependencies
207
242
 
@@ -5,7 +5,9 @@ CREATE TABLE queue_classic_jobs (
5
5
  q_name text not null check (length(q_name) > 0),
6
6
  method text not null check (length(method) > 0),
7
7
  args text not null,
8
- locked_at timestamptz
8
+ locked_at timestamptz,
9
+ locked_by integer,
10
+ created_at timestamptz default now()
9
11
  );
10
12
 
11
13
  -- If json type is available, use it for the args column.
@@ -15,7 +15,9 @@ BEGIN
15
15
  -- for more workers. Would love to see some optimization here...
16
16
 
17
17
  EXECUTE 'SELECT count(*) FROM '
18
- || '(SELECT * FROM queue_classic_jobs WHERE q_name = '
18
+ || '(SELECT * FROM queue_classic_jobs '
19
+ || ' WHERE locked_at IS NULL'
20
+ || ' AND q_name = '
19
21
  || quote_literal(q_name)
20
22
  || ' LIMIT '
21
23
  || quote_literal(top_boundary)
@@ -48,7 +50,8 @@ BEGIN
48
50
  END LOOP;
49
51
 
50
52
  RETURN QUERY EXECUTE 'UPDATE queue_classic_jobs '
51
- || ' SET locked_at = (CURRENT_TIMESTAMP)'
53
+ || ' SET locked_at = (CURRENT_TIMESTAMP),'
54
+ || ' locked_by = (select pg_backend_pid())'
52
55
  || ' WHERE id = $1'
53
56
  || ' AND locked_at is NULL'
54
57
  || ' RETURNING *'
@@ -0,0 +1,2 @@
1
+ ALTER TABLE queue_classic_jobs DROP COLUMN locked_by;
2
+ ALTER TABLE queue_classic_jobs DROP COLUMN created_at;
@@ -0,0 +1,17 @@
1
+ DO $$DECLARE r record;
2
+ BEGIN
3
+ BEGIN
4
+ ALTER TABLE queue_classic_jobs ADD COLUMN created_at timestamptz default now();
5
+ EXCEPTION
6
+ WHEN duplicate_column THEN RAISE NOTICE 'column created_at already exists in queue_classic_jobs.';
7
+ END;
8
+ END$$;
9
+
10
+ DO $$DECLARE r record;
11
+ BEGIN
12
+ BEGIN
13
+ ALTER TABLE queue_classic_jobs ADD COLUMN locked_by integer;
14
+ EXCEPTION
15
+ WHEN duplicate_column THEN RAISE NOTICE 'column locked_by already exists in queue_classic_jobs.';
16
+ END;
17
+ END$$;
@@ -26,6 +26,15 @@ class QCTest < Minitest::Test
26
26
  c.disconnect
27
27
  end
28
28
 
29
+ def capture_stderr_output
30
+ original_stderr = $stderr
31
+ $stderr = StringIO.new
32
+ yield
33
+ $stderr.string
34
+ ensure
35
+ $stderr = original_stderr
36
+ end
37
+
29
38
  def capture_debug_output
30
39
  original_debug = ENV['DEBUG']
31
40
  original_stdout = $stdout
@@ -0,0 +1,32 @@
1
+ require File.expand_path("../../helper.rb", __FILE__)
2
+
3
+ class QueueClassicTest < QCTest
4
+ def test_default_conn_adapter_default_value
5
+ assert(QC.default_conn_adapter.is_a?(QC::ConnAdapter))
6
+ end
7
+
8
+ def test_default_conn_adapter=
9
+ connection = QC::ConnAdapter.new
10
+ QC.default_conn_adapter = connection
11
+ assert_equal(QC.default_conn_adapter, connection)
12
+ end
13
+
14
+ def test_unlock_jobs_of_dead_workers
15
+ # Insert a locked job
16
+ adapter = QC::ConnAdapter.new
17
+ query = "INSERT INTO #{QC::TABLE_NAME} (q_name, method, args, locked_by, locked_at) VALUES ('whatever', 'Kernel.puts', '[\"ok?\"]', 0, (CURRENT_TIMESTAMP))"
18
+ adapter.execute(query)
19
+
20
+ # We should have no unlocked jobs
21
+ query_locked_jobs = "SELECT * FROM #{QC::TABLE_NAME} WHERE locked_at IS NULL"
22
+ res = adapter.connection.exec(query_locked_jobs)
23
+ assert_equal(0, res.count)
24
+
25
+ # Unlock the job
26
+ QC.unlock_jobs_of_dead_workers
27
+
28
+ # We should have an unlocked job now
29
+ res = adapter.connection.exec(query_locked_jobs)
30
+ assert_equal(1, res.count)
31
+ end
32
+ end
@@ -13,12 +13,14 @@ class QueueTest < QCTest
13
13
  end
14
14
 
15
15
  def test_lock
16
- QC.enqueue("Klass.method")
17
-
18
- # See helper.rb for more information about the large initial id
19
- # number.
20
- expected = {:id=>(2**34).to_s, :method=>"Klass.method", :args=>[]}
21
- assert_equal(expected, QC.lock)
16
+ queue = QC::Queue.new("queue_classic_jobs")
17
+ queue.enqueue("Klass.method")
18
+ job = queue.lock
19
+ # See helper.rb for more information about the large initial id number.
20
+ assert_equal((2**34).to_s, job[:id])
21
+ assert_equal("queue_classic_jobs", job[:q_name])
22
+ assert_equal("Klass.method", job[:method])
23
+ assert_equal([], job[:args])
22
24
  end
23
25
 
24
26
  def test_lock_when_empty
@@ -45,12 +45,11 @@ class WorkerTest < QCTest
45
45
  end
46
46
 
47
47
  def test_failed_job_is_logged
48
- output = capture_debug_output do
48
+ output = capture_stderr_output do
49
49
  QC.enqueue("TestObject.not_a_method")
50
50
  TestWorker.new.work
51
51
  end
52
- expected_output = /lib=queue-classic at=handle_failure job={:id=>"\d+", :method=>"TestObject.not_a_method", :args=>\[\]} error=#<NoMethodError: undefined method `not_a_method' for TestObject:Module>/
53
- assert_match(expected_output, output, "=== debug output ===\n #{output}")
52
+ assert(output.include?("#<NoMethodError: undefined method `not_a_method'"))
54
53
  end
55
54
 
56
55
  def test_log_yield
@@ -175,5 +174,4 @@ class WorkerTest < QCTest
175
174
  assert_equal(42, r)
176
175
  assert_equal(0, worker.failed_count)
177
176
  end
178
-
179
177
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: queue_classic
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0rc
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Smith (♠ ace hacker)
@@ -14,14 +14,14 @@ dependencies:
14
14
  name: pg
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.17.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.17.0
27
27
  description: queue_classic is a queueing library for Ruby apps. (Rails, Sinatra, Etc...)
@@ -32,21 +32,25 @@ executables: []
32
32
  extensions: []
33
33
  extra_rdoc_files: []
34
34
  files:
35
- - readme.md
36
- - sql/create_table.sql
37
- - sql/ddl.sql
38
- - sql/drop_ddl.sql
39
35
  - lib/generators/queue_classic/install_generator.rb
40
36
  - lib/generators/queue_classic/templates/add_queue_classic.rb
37
+ - lib/generators/queue_classic/templates/update_queue_classic_3_0_0.rb
38
+ - lib/queue_classic.rb
41
39
  - lib/queue_classic/conn_adapter.rb
42
40
  - lib/queue_classic/queue.rb
43
41
  - lib/queue_classic/railtie.rb
44
42
  - lib/queue_classic/setup.rb
45
43
  - lib/queue_classic/tasks.rb
46
44
  - lib/queue_classic/worker.rb
47
- - lib/queue_classic.rb
45
+ - readme.md
46
+ - sql/create_table.sql
47
+ - sql/ddl.sql
48
+ - sql/downgrade_from_3_0_0.sql
49
+ - sql/drop_ddl.sql
50
+ - sql/update_to_3_0_0.sql
48
51
  - test/benchmark_test.rb
49
52
  - test/helper.rb
53
+ - test/lib/queue_classic_test.rb
50
54
  - test/queue_test.rb
51
55
  - test/worker_test.rb
52
56
  homepage: http://github.com/ryandotsmith/queue_classic
@@ -59,21 +63,22 @@ require_paths:
59
63
  - lib
60
64
  required_ruby_version: !ruby/object:Gem::Requirement
61
65
  requirements:
62
- - - '>='
66
+ - - ">="
63
67
  - !ruby/object:Gem::Version
64
68
  version: '0'
65
69
  required_rubygems_version: !ruby/object:Gem::Requirement
66
70
  requirements:
67
- - - '>'
71
+ - - ">="
68
72
  - !ruby/object:Gem::Version
69
- version: 1.3.1
73
+ version: '0'
70
74
  requirements: []
71
75
  rubyforge_project:
72
- rubygems_version: 2.0.3
76
+ rubygems_version: 2.2.2
73
77
  signing_key:
74
78
  specification_version: 4
75
79
  summary: Simple, efficient worker queue for Ruby & PostgreSQL.
76
80
  test_files:
77
81
  - test/benchmark_test.rb
82
+ - test/lib/queue_classic_test.rb
78
83
  - test/queue_test.rb
79
84
  - test/worker_test.rb