queue_classic 1.0.2 → 2.0.0rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/queue_classic.rb +67 -8
- data/lib/queue_classic/conn.rb +97 -0
- data/lib/queue_classic/okjson.rb +15 -40
- data/lib/queue_classic/queries.rb +56 -0
- data/lib/queue_classic/queue.rb +14 -49
- data/lib/queue_classic/tasks.rb +25 -14
- data/lib/queue_classic/worker.rb +37 -23
- data/readme.md +520 -31
- data/test/helper.rb +21 -17
- data/test/queue_test.rb +29 -60
- data/test/worker_test.rb +57 -25
- metadata +10 -19
- data/lib/queue_classic/database.rb +0 -188
- data/lib/queue_classic/durable_array.rb +0 -51
- data/lib/queue_classic/job.rb +0 -42
- data/lib/queue_classic/logger.rb +0 -17
- data/test/database_helpers.rb +0 -13
- data/test/database_test.rb +0 -73
- data/test/durable_array_test.rb +0 -94
- data/test/job_test.rb +0 -82
@@ -1,51 +0,0 @@
|
|
1
|
-
module QC
|
2
|
-
class DurableArray
|
3
|
-
|
4
|
-
def initialize(database)
|
5
|
-
@database = database
|
6
|
-
@table_name = @database.table_name
|
7
|
-
@top_boundary = @database.top_boundary
|
8
|
-
end
|
9
|
-
|
10
|
-
def <<(details)
|
11
|
-
execute("INSERT INTO #{@table_name} (details) VALUES ($1)", OkJson.encode(details))
|
12
|
-
@database.notify if ENV["QC_LISTENING_WORKER"] == "true"
|
13
|
-
end
|
14
|
-
|
15
|
-
def count
|
16
|
-
execute("SELECT COUNT(*) FROM #{@table_name}")[0]["count"].to_i
|
17
|
-
end
|
18
|
-
|
19
|
-
def delete(job)
|
20
|
-
execute("DELETE FROM #{@table_name} WHERE id = $1;", job.id)
|
21
|
-
job
|
22
|
-
end
|
23
|
-
|
24
|
-
def search_details_column(q)
|
25
|
-
find_many { ["SELECT * FROM #{@table_name} WHERE details LIKE $1;", "%#{q}%"] }
|
26
|
-
end
|
27
|
-
|
28
|
-
def first
|
29
|
-
find_one { ["SELECT * FROM lock_head($1, $2);", @table_name, @top_boundary] }
|
30
|
-
end
|
31
|
-
|
32
|
-
def each
|
33
|
-
execute("SELECT * FROM #{@table_name} ORDER BY id ASC;").each do |r|
|
34
|
-
yield Job.new(r)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def find_one(&blk)
|
39
|
-
find_many(&blk).pop
|
40
|
-
end
|
41
|
-
|
42
|
-
def find_many
|
43
|
-
execute(*yield).map { |r| Job.new(r) }
|
44
|
-
end
|
45
|
-
|
46
|
-
def execute(sql, *params)
|
47
|
-
@database.execute(sql, *params)
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
51
|
-
end
|
data/lib/queue_classic/job.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
module QC
|
2
|
-
class Job
|
3
|
-
attr_accessor :id, :details, :locked_at
|
4
|
-
|
5
|
-
def initialize(args={})
|
6
|
-
@id = args["id"]
|
7
|
-
@details = OkJson.decode(args["details"])
|
8
|
-
@locked_at = args["locked_at"]
|
9
|
-
end
|
10
|
-
|
11
|
-
def klass
|
12
|
-
eval(details["job"].split(".").first)
|
13
|
-
end
|
14
|
-
|
15
|
-
def method
|
16
|
-
details["job"].split(".").last
|
17
|
-
end
|
18
|
-
|
19
|
-
def signature
|
20
|
-
details["job"]
|
21
|
-
end
|
22
|
-
|
23
|
-
def params
|
24
|
-
return [] unless details["params"]
|
25
|
-
params = details["params"]
|
26
|
-
if params.length == 1
|
27
|
-
return params[0]
|
28
|
-
else
|
29
|
-
params
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def work
|
34
|
-
if params.class == Array
|
35
|
-
klass.send(method,*params)
|
36
|
-
else
|
37
|
-
klass.send(method,params)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
end
|
data/lib/queue_classic/logger.rb
DELETED
data/test/database_helpers.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
module DatabaseHelpers
|
2
|
-
|
3
|
-
def init_db(table_name="queue_classic_jobs")
|
4
|
-
database = QC::Database.new(table_name)
|
5
|
-
database.execute("SET client_min_messages TO 'warning'")
|
6
|
-
database.execute("DROP TABLE IF EXISTS #{table_name} CASCADE")
|
7
|
-
database.execute("CREATE TABLE #{table_name} (id serial, details text, locked_at timestamp)")
|
8
|
-
database.load_functions
|
9
|
-
database.disconnect
|
10
|
-
database
|
11
|
-
end
|
12
|
-
|
13
|
-
end
|
data/test/database_test.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
require File.expand_path("../helper.rb", __FILE__)
|
2
|
-
|
3
|
-
context "DatabaseTest" do
|
4
|
-
|
5
|
-
setup do
|
6
|
-
@database = init_db
|
7
|
-
end
|
8
|
-
|
9
|
-
teardown do
|
10
|
-
@database.disconnect
|
11
|
-
end
|
12
|
-
|
13
|
-
test "drain_notify clears all of the notifications" do
|
14
|
-
@database.listen
|
15
|
-
@database.execute("NOTIFY queue_classic_jobs, 'hello'")
|
16
|
-
|
17
|
-
assert ! @database.connection.notifies.nil?
|
18
|
-
assert @database.connection.notifies.nil?
|
19
|
-
|
20
|
-
@database.execute("NOTIFY queue_classic_jobs, 'hello'")
|
21
|
-
@database.execute("NOTIFY queue_classic_jobs, 'hello'")
|
22
|
-
@database.execute("NOTIFY queue_classic_jobs, 'hello'")
|
23
|
-
|
24
|
-
@database.drain_notify
|
25
|
-
assert @database.connection.notifies.nil?
|
26
|
-
end
|
27
|
-
|
28
|
-
test "execute should return rows" do
|
29
|
-
result = @database.execute 'SELECT 11 foo, 22 bar;'
|
30
|
-
assert_equal [{'foo'=>'11', 'bar'=>'22'}], result.to_a
|
31
|
-
end
|
32
|
-
|
33
|
-
test "should raise error on failure" do
|
34
|
-
assert_raises PGError do
|
35
|
-
@database.execute 'SELECT unknown FROM missing;'
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
test "execute should accept parameters" do
|
40
|
-
result = @database.execute 'SELECT $2::int b, $1::int a, $1::int + $2::int c;', 123, '456'
|
41
|
-
assert_equal [{"a"=>"123", "b"=>"456", "c"=>"579"}], result.to_a
|
42
|
-
end
|
43
|
-
|
44
|
-
def job_count
|
45
|
-
@database.execute('SELECT COUNT(*) FROM queue_classic_jobs')[0].values.first.to_i
|
46
|
-
end
|
47
|
-
|
48
|
-
test "transaction should commit" do
|
49
|
-
assert_equal true, @database.transaction_idle?
|
50
|
-
assert_equal 0, job_count
|
51
|
-
@database.transaction do
|
52
|
-
assert_equal false, @database.transaction_idle?
|
53
|
-
assert_equal 0, job_count
|
54
|
-
@database.execute "INSERT INTO queue_classic_jobs (details) VALUES ('test');"
|
55
|
-
assert_equal false, @database.transaction_idle?
|
56
|
-
assert_equal 1, job_count
|
57
|
-
end
|
58
|
-
assert_equal true, @database.transaction_idle?
|
59
|
-
assert_equal 1, job_count
|
60
|
-
end
|
61
|
-
|
62
|
-
test "transaction should rollback if there's an error" do
|
63
|
-
assert_raises RuntimeError do
|
64
|
-
@database.transaction do
|
65
|
-
@database.execute "INSERT INTO queue_classic_jobs (details) VALUES ('test');"
|
66
|
-
assert_equal 1, job_count
|
67
|
-
raise "force rollback"
|
68
|
-
end
|
69
|
-
end
|
70
|
-
assert_equal 0, job_count
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
data/test/durable_array_test.rb
DELETED
@@ -1,94 +0,0 @@
|
|
1
|
-
require File.expand_path("../helper.rb", __FILE__)
|
2
|
-
|
3
|
-
context "DurableArray" do
|
4
|
-
|
5
|
-
setup do
|
6
|
-
@database = init_db
|
7
|
-
@array = QC::DurableArray.new(@database)
|
8
|
-
end
|
9
|
-
|
10
|
-
teardown do
|
11
|
-
@database.disconnect
|
12
|
-
end
|
13
|
-
|
14
|
-
test "decode json into hash" do
|
15
|
-
@array << {"test" => "ok"}
|
16
|
-
assert_equal({"test" => "ok"}, @array.first.details)
|
17
|
-
end
|
18
|
-
|
19
|
-
test "count returns number of rows" do
|
20
|
-
@array << {"test" => "ok"}
|
21
|
-
assert_equal 1, @array.count
|
22
|
-
@array << {"test" => "ok"}
|
23
|
-
assert_equal 2, @array.count
|
24
|
-
end
|
25
|
-
|
26
|
-
test "first returns first job" do
|
27
|
-
job = {"job" => "one"}
|
28
|
-
@array << job
|
29
|
-
assert_equal job, @array.first.details
|
30
|
-
end
|
31
|
-
|
32
|
-
test "passes through strings with quotes" do
|
33
|
-
job = {"foo'bar\"baz" => 'abc\\def'}
|
34
|
-
@array << job
|
35
|
-
assert_equal job, @array.first.details
|
36
|
-
end
|
37
|
-
|
38
|
-
test "passes through newlines" do
|
39
|
-
job = {"word" => "line1\nline2\nline3\n"}
|
40
|
-
@array << job
|
41
|
-
assert_equal job, @array.first.details
|
42
|
-
end
|
43
|
-
|
44
|
-
test "first returns first job when many are in the array" do
|
45
|
-
@array << {"job" => "one"}
|
46
|
-
@array << {"job" => "two"}
|
47
|
-
assert_equal({"job" => "one"}, @array.first.details)
|
48
|
-
end
|
49
|
-
|
50
|
-
test "find_many returns empty array when nothing is found" do
|
51
|
-
assert_equal([], @array.find_many {"select * from queue_classic_jobs"})
|
52
|
-
end
|
53
|
-
|
54
|
-
test "delete removes job from the array" do
|
55
|
-
@array << {"job" => "one"}
|
56
|
-
job = @array.first
|
57
|
-
|
58
|
-
assert_equal( {"job" => "one"}, job.details)
|
59
|
-
|
60
|
-
assert_equal(1,@array.count)
|
61
|
-
@array.delete(job)
|
62
|
-
assert_equal(0,@array.count)
|
63
|
-
end
|
64
|
-
|
65
|
-
test "delete returns job after delete" do
|
66
|
-
@array << {"job" => "one"}
|
67
|
-
job = @array.first
|
68
|
-
|
69
|
-
assert_equal({"job" => "one"}, job.details)
|
70
|
-
|
71
|
-
res = @array.delete(job)
|
72
|
-
assert_equal({"job" => "one"}, res.details)
|
73
|
-
end
|
74
|
-
|
75
|
-
test "each yields the details for each job" do
|
76
|
-
@array << {"job" => "one"}
|
77
|
-
@array << {"job" => "two"}
|
78
|
-
results = []
|
79
|
-
@array.each {|v| results << v.details}
|
80
|
-
assert_equal([{"job" => "one"},{"job" => "two"}], results)
|
81
|
-
end
|
82
|
-
|
83
|
-
test "search" do
|
84
|
-
@array << {"job" => "A.signature"}
|
85
|
-
jobs = @array.search_details_column("A.signature")
|
86
|
-
assert_equal "A.signature", jobs.first.signature
|
87
|
-
end
|
88
|
-
|
89
|
-
test "search when data will not match" do
|
90
|
-
@array << {"job" => "A.signature"}
|
91
|
-
jobs = @array.search_details_column("B.signature")
|
92
|
-
assert_equal [], jobs
|
93
|
-
end
|
94
|
-
end
|
data/test/job_test.rb
DELETED
@@ -1,82 +0,0 @@
|
|
1
|
-
require File.expand_path("../helper.rb", __FILE__)
|
2
|
-
|
3
|
-
context "Job" do
|
4
|
-
|
5
|
-
test "initialize takes details as JSON" do
|
6
|
-
job = QC::Job.new(
|
7
|
-
"id" => 1,
|
8
|
-
"details" => "{\"arg\":1}",
|
9
|
-
"locked_at" => nil
|
10
|
-
)
|
11
|
-
assert_equal({"arg" => 1}, job.details)
|
12
|
-
end
|
13
|
-
|
14
|
-
test "signature returns the class and method" do
|
15
|
-
job = QC::Job.new(
|
16
|
-
"id" => 1,
|
17
|
-
"details" => QC::OkJson.encode({"job" => "Class.method", "params" => []}),
|
18
|
-
"locked_at" => nil
|
19
|
-
)
|
20
|
-
assert_equal "Class.method", job.signature
|
21
|
-
end
|
22
|
-
|
23
|
-
test "method returns the class method" do
|
24
|
-
job = QC::Job.new(
|
25
|
-
"id" => 1,
|
26
|
-
"details" => QC::OkJson.encode({"job" => "Class.method", "params" => []}),
|
27
|
-
"locked_at" => nil
|
28
|
-
)
|
29
|
-
assert_equal "method", job.method
|
30
|
-
end
|
31
|
-
|
32
|
-
test "klass returns the class" do
|
33
|
-
class WhoHa; end
|
34
|
-
job = QC::Job.new(
|
35
|
-
"id" => 1,
|
36
|
-
"details" => QC::OkJson.encode({"job" => "WhoHa.method", "params" => []}),
|
37
|
-
"locked_at" => nil
|
38
|
-
)
|
39
|
-
assert_equal WhoHa, job.klass
|
40
|
-
end
|
41
|
-
|
42
|
-
test "klass returns the class when scoped to module" do
|
43
|
-
module Mod
|
44
|
-
class K
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
job = QC::Job.new(
|
49
|
-
"id" => 1,
|
50
|
-
"details" => QC::OkJson.encode({"job" => "Mod::K.method", "params" => []}),
|
51
|
-
"locked_at" => nil
|
52
|
-
)
|
53
|
-
assert_equal Mod::K, job.klass
|
54
|
-
end
|
55
|
-
|
56
|
-
test "params returns empty array when nil" do
|
57
|
-
job = QC::Job.new(
|
58
|
-
"id" => 1,
|
59
|
-
"details" => QC::OkJson.encode({"job" => "Mod::K.method", "params" => nil}),
|
60
|
-
"locked_at" => nil
|
61
|
-
)
|
62
|
-
assert_equal [], job.params
|
63
|
-
end
|
64
|
-
|
65
|
-
test "params returns 1 items when there is 1 param" do
|
66
|
-
job = QC::Job.new(
|
67
|
-
"id" => 1,
|
68
|
-
"details" => QC::OkJson.encode({"job" => "Mod::K.method", "params" => ["arg"]}),
|
69
|
-
"locked_at" => nil
|
70
|
-
)
|
71
|
-
assert_equal "arg", job.params
|
72
|
-
end
|
73
|
-
|
74
|
-
test "params retuns many items when there are many params" do
|
75
|
-
job = QC::Job.new(
|
76
|
-
"id" => 1,
|
77
|
-
"details" => QC::OkJson.encode({"job" => "Mod::K.method", "params" => ["arg","arg"]}),
|
78
|
-
"locked_at" => nil
|
79
|
-
)
|
80
|
-
assert_equal ["arg","arg"], job.params
|
81
|
-
end
|
82
|
-
end
|