qc-additions 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/README.md +30 -0
- data/lib/qc-additions.rb +4 -0
- data/lib/qc-additions/queries.rb +22 -0
- data/lib/qc-additions/queue.rb +17 -0
- data/test/additions_test.rb +36 -0
- data/test/benchmark_test.rb +38 -0
- data/test/conn_test.rb +22 -0
- data/test/helper.rb +66 -0
- data/test/queue_test.rb +103 -0
- data/test/worker_test.rb +125 -0
- metadata +73 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZjQ0ZWQ3OGM2OWY2ZjVkYmVmZThkNmM4ZTg0NTE1OTMzZDBjNzQ1OQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YzUxYmNmNWJmNTU0Y2U2NWQ1ZmI0ZWRhNGIwNWFiY2YxY2QyMWM4ZQ==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MzczZTc2MTE2ZTM0ZTlmMzAyMjc3MjMwMTkwNGUzMzcxOTU0ZTIxYWNhODNj
|
10
|
+
OTk2ZWNkNmU3ODdmYWY0NDZjYmMwNjcyYTU0N2U3YmEzNmJmMWY4NTE0MWUy
|
11
|
+
NWZjODMyOGM0NjMxZDhmOTVmMGY4ZjVkNzdiMzI2YmY3NmExYWI=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZDEwYTAyN2NkYWI1ZmU1ZTM5ZjRjZmRhNmNmM2E3NzUxMTRkMDA5ZDIzOThi
|
14
|
+
NmUwYzBmNjE4YWMyZmVhODM0ODRiYjJiNjIyYTkyMDIwMTg1MzExZjYzZTEx
|
15
|
+
MTc1MzI0OTYzZWJhZDQwOTBkZDgxZDk1YmY5MGU2ZTNkNjJhMjY=
|
data/README.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# qc-additions
|
2
|
+
|
3
|
+
|
4
|
+
This gem adds some methods to [queue_classic](https://github.com/ryandotsmith/queue_classic) queues that I found helpful:
|
5
|
+
|
6
|
+
* `enqueue_if_not_queued(method, *args)`
|
7
|
+
* `job_count(method, *args)`
|
8
|
+
* `job_exists?(method, *args)`
|
9
|
+
|
10
|
+
|
11
|
+
An index might help to speed up the `job_count` and `job_exists?` queries. Although, I haven't really tested if there is much to gain by adding this:
|
12
|
+
|
13
|
+
```SQL
|
14
|
+
CREATE INDEX idx_qc_unlocked_job_count ON queue_classic_jobs (q_name, method, args) WHERE locked_at IS NULL;
|
15
|
+
```
|
16
|
+
|
17
|
+
|
18
|
+
## Caveats when comparing args column
|
19
|
+
|
20
|
+
The method arguments are serialized to JSON. However, the comparison performed when looking for jobs in the database is a string comparison. Results might be incorrect if there is more than one way to serialize the arguments to a JSON string. It should be safe for simple things like passing a numeric id.
|
21
|
+
|
22
|
+
|
23
|
+
---
|
24
|
+
|
25
|
+
|
26
|
+
I have some of the original code from there:
|
27
|
+
|
28
|
+
* https://github.com/ryandotsmith/queue_classic/pull/92
|
29
|
+
|
30
|
+
* https://github.com/GreenplumChorus/queue_classic/commit/2719301c2813717692169c1eeab42d317df0ac59
|
data/lib/qc-additions.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module QC
|
2
|
+
module Queries
|
3
|
+
extend self
|
4
|
+
|
5
|
+
# TODO:
|
6
|
+
# Once PostgreSQL supports JSON comparison, use it.
|
7
|
+
# But older versions should be supported too (at least >= 9.0).
|
8
|
+
|
9
|
+
def job_count(q_name, method, args)
|
10
|
+
s = "SELECT COUNT(*) FROM #{TABLE_NAME} WHERE q_name = $1 AND method = $2 AND args::text = $3 AND locked_at IS NULL"
|
11
|
+
r = Conn.execute(s, q_name, method, JSON.dump(args))
|
12
|
+
r["count"].to_i
|
13
|
+
end
|
14
|
+
|
15
|
+
def job_exists?(q_name, method, args)
|
16
|
+
s = "SELECT 1 AS one FROM #{TABLE_NAME} WHERE q_name = $1 AND method = $2 AND args::text = $3 AND locked_at IS NULL LIMIT 1"
|
17
|
+
r = Conn.execute(s, q_name, method, JSON.dump(args))
|
18
|
+
!r.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module QC
|
2
|
+
class Queue
|
3
|
+
|
4
|
+
def enqueue_if_not_queued(method, *args)
|
5
|
+
enqueue(method, *args) unless job_exists?(method, *args)
|
6
|
+
end
|
7
|
+
|
8
|
+
def job_count(method, *args)
|
9
|
+
Queries.job_count(name, method, args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def job_exists?(method, *args)
|
13
|
+
Queries.job_exists?(name, method, args)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.expand_path("../helper.rb", __FILE__)
|
2
|
+
|
3
|
+
class QueueTest < QCTest
|
4
|
+
|
5
|
+
def test_enqueue_if_not_queued
|
6
|
+
QC.enqueue_if_not_queued("Klass.method", "arg1", "arg2")
|
7
|
+
QC.enqueue_if_not_queued("Klass.method", "arg1", "arg2")
|
8
|
+
QC.lock
|
9
|
+
QC.enqueue_if_not_queued("Klass.method", "arg1", "arg2")
|
10
|
+
assert_equal(1, QC.job_count("Klass.method", "arg1", "arg2"))
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_job_count
|
14
|
+
#Should return the count of unstarted jobs that match both method and arguments
|
15
|
+
QC.enqueue("Klass.method", "arg1", "arg2")
|
16
|
+
QC.enqueue("Klass.method", "arg1", "arg2")
|
17
|
+
QC.enqueue("Klass.method", "arg1", "arg2")
|
18
|
+
QC.enqueue("Klass.method", "arg3", "arg4")
|
19
|
+
QC.enqueue("Klass.other_method", "arg1", "arg2")
|
20
|
+
QC.lock #start the first job
|
21
|
+
assert_equal(2, QC.job_count("Klass.method", "arg1", "arg2"))
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_job_exists
|
25
|
+
# Should return true if an unstarted job with same method and arguments exists
|
26
|
+
assert_equal(false, QC.job_exists?("Klass.method"))
|
27
|
+
QC.enqueue("Klass.method")
|
28
|
+
assert_equal(true, QC.job_exists?("Klass.method"))
|
29
|
+
assert_equal(false, QC.job_exists?("Klass.method", "arg1"))
|
30
|
+
assert_equal(false, QC.job_exists?("Klass.other_method"))
|
31
|
+
assert_equal(false, QC.job_exists?("Klass.other_method", "arg1"))
|
32
|
+
QC.lock # start the job
|
33
|
+
assert_equal(false, QC.job_exists?("Klass.method"))
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.expand_path("../helper.rb", __FILE__)
|
2
|
+
|
3
|
+
if ENV["QC_BENCHMARK"]
|
4
|
+
class BenchmarkTest < QCTest
|
5
|
+
|
6
|
+
def test_enqueue
|
7
|
+
n = 10_000
|
8
|
+
start = Time.now
|
9
|
+
n.times do
|
10
|
+
QC.enqueue("1.odd?", [])
|
11
|
+
end
|
12
|
+
assert_equal(n, QC.count)
|
13
|
+
|
14
|
+
elapsed = Time.now - start
|
15
|
+
assert_in_delta(4, elapsed, 1)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_dequeue
|
19
|
+
worker = QC::Worker.new
|
20
|
+
worker.running = true
|
21
|
+
n = 10_000
|
22
|
+
n.times do
|
23
|
+
QC.enqueue("1.odd?", [])
|
24
|
+
end
|
25
|
+
assert_equal(n, QC.count)
|
26
|
+
|
27
|
+
start = Time.now
|
28
|
+
n.times do
|
29
|
+
worker.work
|
30
|
+
end
|
31
|
+
elapsed = Time.now - start
|
32
|
+
|
33
|
+
assert_equal(0, QC.count)
|
34
|
+
assert_in_delta(10, elapsed, 3)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
data/test/conn_test.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.expand_path("../helper.rb", __FILE__)
|
2
|
+
|
3
|
+
class ConnTest < QCTest
|
4
|
+
|
5
|
+
def test_extracts_the_segemnts_to_connect
|
6
|
+
database_url = "postgres://ryan:secret@localhost:1234/application_db"
|
7
|
+
normalized = QC::Conn.normalize_db_url(URI.parse(database_url))
|
8
|
+
assert_equal ["localhost",
|
9
|
+
1234,
|
10
|
+
nil, "",
|
11
|
+
"application_db",
|
12
|
+
"ryan",
|
13
|
+
"secret"], normalized
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_regression_database_url_without_host
|
17
|
+
database_url = "postgres:///my_db"
|
18
|
+
normalized = QC::Conn.normalize_db_url(URI.parse(database_url))
|
19
|
+
assert_equal [nil, 5432, nil, "", "my_db", nil, nil], normalized
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
$: << File.expand_path("lib")
|
2
|
+
$: << File.expand_path("test")
|
3
|
+
|
4
|
+
ENV["DATABASE_URL"] ||= "postgres:///queue_classic_test"
|
5
|
+
|
6
|
+
require "queue_classic"
|
7
|
+
require "qc-additions"
|
8
|
+
require "stringio"
|
9
|
+
require "minitest/autorun"
|
10
|
+
|
11
|
+
class QCTest < Minitest::Test
|
12
|
+
|
13
|
+
def setup
|
14
|
+
init_db
|
15
|
+
end
|
16
|
+
|
17
|
+
def teardown
|
18
|
+
QC.delete_all
|
19
|
+
end
|
20
|
+
|
21
|
+
def init_db(table_name="queue_classic_jobs")
|
22
|
+
QC::Conn.execute("SET client_min_messages TO 'warning'")
|
23
|
+
QC::Setup.drop
|
24
|
+
QC::Setup.create
|
25
|
+
QC::Conn.execute(<<EOS)
|
26
|
+
DO $$
|
27
|
+
-- Set initial sequence to a large number to test the entire toolchain
|
28
|
+
-- works on integers with higher bits set.
|
29
|
+
DECLARE
|
30
|
+
quoted_name text;
|
31
|
+
quoted_size text;
|
32
|
+
BEGIN
|
33
|
+
-- Find the name of the relevant sequence.
|
34
|
+
--
|
35
|
+
-- pg_get_serial_sequence quotes identifiers as part of its
|
36
|
+
-- behavior.
|
37
|
+
SELECT name
|
38
|
+
INTO STRICT quoted_name
|
39
|
+
FROM pg_get_serial_sequence('queue_classic_jobs', 'id') AS name;
|
40
|
+
|
41
|
+
-- Don't quote, because ALTER SEQUENCE RESTART doesn't like
|
42
|
+
-- general literals, only unquoted numeric literals.
|
43
|
+
SELECT pow(2, 34)::text AS size
|
44
|
+
INTO STRICT quoted_size;
|
45
|
+
|
46
|
+
EXECUTE 'ALTER SEQUENCE ' || quoted_name ||
|
47
|
+
' RESTART ' || quoted_size || ';';
|
48
|
+
END;
|
49
|
+
$$;
|
50
|
+
EOS
|
51
|
+
end
|
52
|
+
|
53
|
+
def capture_debug_output
|
54
|
+
original_debug = ENV['DEBUG']
|
55
|
+
original_stdout = $stdout
|
56
|
+
|
57
|
+
ENV['DEBUG'] = "true"
|
58
|
+
$stdout = StringIO.new
|
59
|
+
yield
|
60
|
+
$stdout.string
|
61
|
+
ensure
|
62
|
+
ENV['DEBUG'] = original_debug
|
63
|
+
$stdout = original_stdout
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
data/test/queue_test.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
require File.expand_path("../helper.rb", __FILE__)
|
2
|
+
|
3
|
+
class QueueTest < QCTest
|
4
|
+
|
5
|
+
def test_enqueue
|
6
|
+
QC.enqueue("Klass.method")
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_respond_to
|
10
|
+
assert_equal(true, QC.respond_to?(:enqueue))
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_lock
|
14
|
+
QC.enqueue("Klass.method")
|
15
|
+
|
16
|
+
# See helper.rb for more information about the large initial id
|
17
|
+
# number.
|
18
|
+
expected = {:id=>(2**34).to_s, :method=>"Klass.method", :args=>[]}
|
19
|
+
assert_equal(expected, QC.lock)
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_lock_when_empty
|
23
|
+
assert_nil(QC.lock)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_count
|
27
|
+
QC.enqueue("Klass.method")
|
28
|
+
assert_equal(1, QC.count)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_delete
|
32
|
+
QC.enqueue("Klass.method")
|
33
|
+
assert_equal(1, QC.count)
|
34
|
+
QC.delete(QC.lock[:id])
|
35
|
+
assert_equal(0, QC.count)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_delete_all
|
39
|
+
QC.enqueue("Klass.method")
|
40
|
+
QC.enqueue("Klass.method")
|
41
|
+
assert_equal(2, QC.count)
|
42
|
+
QC.delete_all
|
43
|
+
assert_equal(0, QC.count)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_delete_all_by_queue_name
|
47
|
+
p_queue = QC::Queue.new("priority_queue")
|
48
|
+
s_queue = QC::Queue.new("secondary_queue")
|
49
|
+
p_queue.enqueue("Klass.method")
|
50
|
+
s_queue.enqueue("Klass.method")
|
51
|
+
assert_equal(1, p_queue.count)
|
52
|
+
assert_equal(1, s_queue.count)
|
53
|
+
p_queue.delete_all
|
54
|
+
assert_equal(0, p_queue.count)
|
55
|
+
assert_equal(1, s_queue.count)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_queue_instance
|
59
|
+
queue = QC::Queue.new("queue_classic_jobs", false)
|
60
|
+
queue.enqueue("Klass.method")
|
61
|
+
assert_equal(1, queue.count)
|
62
|
+
queue.delete(queue.lock[:id])
|
63
|
+
assert_equal(0, queue.count)
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_repair_after_error
|
67
|
+
queue = QC::Queue.new("queue_classic_jobs", false)
|
68
|
+
queue.enqueue("Klass.method")
|
69
|
+
assert_equal(1, queue.count)
|
70
|
+
connection = QC::Conn.connection
|
71
|
+
saved_method = connection.method(:exec)
|
72
|
+
def connection.exec(*args)
|
73
|
+
raise PGError
|
74
|
+
end
|
75
|
+
assert_raises(PG::Error) { queue.enqueue("Klass.other_method") }
|
76
|
+
assert_equal(1, queue.count)
|
77
|
+
queue.enqueue("Klass.other_method")
|
78
|
+
assert_equal(2, queue.count)
|
79
|
+
rescue PG::Error
|
80
|
+
QC::Conn.disconnect
|
81
|
+
assert false, "Expected to QC repair after connection error"
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_custom_default_queue
|
85
|
+
queue_class = Class.new do
|
86
|
+
attr_accessor :jobs
|
87
|
+
def enqueue(method, *args)
|
88
|
+
@jobs ||= []
|
89
|
+
@jobs << method
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
queue_instance = queue_class.new
|
94
|
+
QC.default_queue = queue_instance
|
95
|
+
|
96
|
+
QC.enqueue("Klass.method1")
|
97
|
+
QC.enqueue("Klass.method2")
|
98
|
+
|
99
|
+
assert_equal ["Klass.method1", "Klass.method2"], queue_instance.jobs
|
100
|
+
ensure
|
101
|
+
QC.default_queue = nil
|
102
|
+
end
|
103
|
+
end
|
data/test/worker_test.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
require File.expand_path("../helper.rb", __FILE__)
|
2
|
+
|
3
|
+
module TestObject
|
4
|
+
extend self
|
5
|
+
def no_args; return nil; end
|
6
|
+
def one_arg(a); return a; end
|
7
|
+
def two_args(a,b); return [a,b]; end
|
8
|
+
end
|
9
|
+
|
10
|
+
# This not only allows me to test what happens
|
11
|
+
# when a failure occurs but it also demonstrates
|
12
|
+
# how to override the worker to handle failures the way
|
13
|
+
# you want.
|
14
|
+
class TestWorker < QC::Worker
|
15
|
+
attr_accessor :failed_count
|
16
|
+
|
17
|
+
def initialize(*args)
|
18
|
+
super(*args)
|
19
|
+
@failed_count = 0
|
20
|
+
end
|
21
|
+
|
22
|
+
def handle_failure(job,e)
|
23
|
+
@failed_count += 1
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class WorkerTest < QCTest
|
28
|
+
|
29
|
+
def test_work
|
30
|
+
QC.enqueue("TestObject.no_args")
|
31
|
+
worker = TestWorker.new
|
32
|
+
assert_equal(1, QC.count)
|
33
|
+
worker.work
|
34
|
+
assert_equal(0, QC.count)
|
35
|
+
assert_equal(0, worker.failed_count)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_failed_job
|
39
|
+
QC.enqueue("TestObject.not_a_method")
|
40
|
+
worker = TestWorker.new
|
41
|
+
worker.work
|
42
|
+
assert_equal(1, worker.failed_count)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_failed_job_is_logged
|
46
|
+
output = capture_debug_output do
|
47
|
+
QC.enqueue("TestObject.not_a_method")
|
48
|
+
QC::Worker.new.work
|
49
|
+
end
|
50
|
+
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>/
|
51
|
+
assert_match(expected_output, output, "=== debug output ===\n #{output}")
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_log_yield
|
55
|
+
output = capture_debug_output do
|
56
|
+
QC.log_yield(:action => "test") do
|
57
|
+
0 == 1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
expected_output = /lib=queue-classic action=test elapsed=\d*/
|
61
|
+
assert_match(expected_output, output, "=== debug output ===\n #{output}")
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_log
|
65
|
+
output = capture_debug_output do
|
66
|
+
QC.log(:action => "test")
|
67
|
+
end
|
68
|
+
expected_output = /lib=queue-classic action=test/
|
69
|
+
assert_match(expected_output, output, "=== debug output ===\n #{output}")
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_work_with_no_args
|
73
|
+
QC.enqueue("TestObject.no_args")
|
74
|
+
worker = TestWorker.new
|
75
|
+
r = worker.work
|
76
|
+
assert_nil(r)
|
77
|
+
assert_equal(0, worker.failed_count)
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_work_with_one_arg
|
81
|
+
QC.enqueue("TestObject.one_arg", "1")
|
82
|
+
worker = TestWorker.new
|
83
|
+
r = worker.work
|
84
|
+
assert_equal("1", r)
|
85
|
+
assert_equal(0, worker.failed_count)
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_work_with_two_args
|
89
|
+
QC.enqueue("TestObject.two_args", "1", 2)
|
90
|
+
worker = TestWorker.new
|
91
|
+
r = worker.work
|
92
|
+
assert_equal(["1", 2], r)
|
93
|
+
assert_equal(0, worker.failed_count)
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_work_custom_queue
|
97
|
+
p_queue = QC::Queue.new("priority_queue")
|
98
|
+
p_queue.enqueue("TestObject.two_args", "1", 2)
|
99
|
+
worker = TestWorker.new(q_name: "priority_queue")
|
100
|
+
r = worker.work
|
101
|
+
assert_equal(["1", 2], r)
|
102
|
+
assert_equal(0, worker.failed_count)
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_worker_listens_on_chan
|
106
|
+
p_queue = QC::Queue.new("priority_queue")
|
107
|
+
p_queue.enqueue("TestObject.two_args", "1", 2)
|
108
|
+
worker = TestWorker.new(q_name: "priority_queue", listening_worker: true)
|
109
|
+
r = worker.work
|
110
|
+
assert_equal(["1", 2], r)
|
111
|
+
assert_equal(0, worker.failed_count)
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_worker_ueses_one_conn
|
115
|
+
QC.enqueue("TestObject.no_args")
|
116
|
+
worker = TestWorker.new
|
117
|
+
worker.work
|
118
|
+
assert_equal(
|
119
|
+
1,
|
120
|
+
QC::Conn.execute("SELECT count(*) from pg_stat_activity where datname = current_database()")["count"].to_i,
|
121
|
+
"Multiple connections found -- are there open connections to #{ QC::Conn.db_url } in other terminals?"
|
122
|
+
)
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: qc-additions
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jakob Rath
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-07-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: queue_classic
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.2.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.2.0
|
27
|
+
description: Add some methods to queue_classic to determine whether a job exists or
|
28
|
+
how many times a given job is already queued.
|
29
|
+
email: mail@jakobrath.eu
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- README.md
|
35
|
+
- lib/qc-additions/queries.rb
|
36
|
+
- lib/qc-additions/queue.rb
|
37
|
+
- lib/qc-additions.rb
|
38
|
+
- test/additions_test.rb
|
39
|
+
- test/benchmark_test.rb
|
40
|
+
- test/conn_test.rb
|
41
|
+
- test/helper.rb
|
42
|
+
- test/queue_test.rb
|
43
|
+
- test/worker_test.rb
|
44
|
+
homepage: https://github.com/JakobR/qc-additions
|
45
|
+
licenses: []
|
46
|
+
metadata: {}
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 2.0.3
|
64
|
+
signing_key:
|
65
|
+
specification_version: 4
|
66
|
+
summary: Add some methods to queue_classic.
|
67
|
+
test_files:
|
68
|
+
- test/additions_test.rb
|
69
|
+
- test/benchmark_test.rb
|
70
|
+
- test/conn_test.rb
|
71
|
+
- test/queue_test.rb
|
72
|
+
- test/worker_test.rb
|
73
|
+
has_rdoc:
|