localjob 0.1.1 → 0.2.0
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.
- checksums.yaml +4 -4
- data/README.md +16 -35
- data/lib/localjob/sysv_adapter.rb +15 -28
- data/lib/localjob/version.rb +1 -1
- data/lib/localjob/worker.rb +53 -24
- data/lib/localjob.rb +7 -17
- data/localjob.gemspec +2 -2
- data/test/localjob_test.rb +1 -9
- data/test/mock_adapter.rb +1 -0
- data/test/sysv_adapter_test.rb +23 -0
- data/test/test_helper.rb +5 -17
- data/test/worker_test.rb +29 -34
- metadata +34 -22
- data/ext/mkrf_conf.rb +0 -4
- data/lib/localjob/channel.rb +0 -18
- data/lib/localjob/linux_adapter.rb +0 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d66cdf9e9ef8c26230cc76e00a40964249c62db
|
4
|
+
data.tar.gz: cdb1b11bacb52f1d9cdc75dec508b4fbe61ee743
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9fbe02975d57dd69a328050f4f04a1f3e07312714f6bd5ac8a6fdcbddf02ba55905a11a4a82e677a49524e2b1552f0da0a16d0090f9fc2adf433d8a547f45c5d
|
7
|
+
data.tar.gz: 201974c4584b2c9c3c549ef07be74569b85500cdf7a307d1efd8d8079de9c63a79830a59a8c85a1bb3aa4f86264c23db1d6e5135311824a276401d839198e426
|
data/README.md
CHANGED
@@ -1,28 +1,22 @@
|
|
1
1
|
# Localjob
|
2
2
|
|
3
|
-
Localjob is a simple, self-contained background queue built on top of [
|
4
|
-
message queues][
|
5
|
-
the same machine. It's the sqlite of
|
6
|
-
it works][blog].
|
3
|
+
Localjob is a simple, self-contained background queue built on top of [System V
|
4
|
+
message queues][sysv] (SysV Message Queue => SysV MQ for short). Workers and the
|
5
|
+
app pushing to the queue must reside on the same machine. It's the sqlite of
|
6
|
+
background queues. Here's a post about [how it works][blog].
|
7
7
|
|
8
8
|
Localjob is for early-development situations where you don't need a
|
9
9
|
full-featured background queue, but just want to get started with something
|
10
|
-
simple that does not rely on any external services.
|
11
|
-
|
12
|
-
|
13
|
-
your own code.
|
10
|
+
simple that does not rely on any external services. The advantage of the SysV
|
11
|
+
queues is that your Rails app or worker can restart at any time, without loosing
|
12
|
+
any events.
|
14
13
|
|
15
|
-
|
16
|
-
parameters for your application**, please consult [posix-mqueue][pmq-gem]'s
|
17
|
-
documentation.
|
18
|
-
|
19
|
-
Localjob works on Ruby >= 2.0.0. On Linux, it will use the POSIX message queue.
|
20
|
-
On OS X it will use SysV message queues.
|
14
|
+
Localjob works on Ruby >= 2.0.0 on Linux and OS X.
|
21
15
|
|
22
16
|
Add it to your Gemfile:
|
23
17
|
|
24
18
|
```ruby
|
25
|
-
gem 'localjob', "0.
|
19
|
+
gem 'localjob', "~> 0.2"
|
26
20
|
```
|
27
21
|
|
28
22
|
## Usage
|
@@ -48,10 +42,11 @@ queue = Localjob.new
|
|
48
42
|
queue << EmailJob.new(current_user.id, welcome_email)
|
49
43
|
```
|
50
44
|
|
51
|
-
A job is serialized with YAML and pushed onto a persistent
|
45
|
+
A job is serialized with YAML and pushed onto a persistent SysV Message Queue.
|
52
46
|
This means a worker does not have to listen on the queue to push things to it.
|
53
|
-
|
54
|
-
|
47
|
+
Pops off the message queue are atomic, so only one will receive the queue. This
|
48
|
+
means you can run multiple workers on the same machine if you wish. The workers
|
49
|
+
will deserialize the message to create an instance of your object, and call
|
55
50
|
`#perform` on the object.
|
56
51
|
|
57
52
|
### Rails initializer
|
@@ -61,7 +56,7 @@ constant referencing each of your queues. This allows easy access anywhere in
|
|
61
56
|
your app. In `config/initializers/localjob.rb`:
|
62
57
|
|
63
58
|
```ruby
|
64
|
-
BackgroundQueue = Localjob.new
|
59
|
+
BackgroundQueue = Localjob.new
|
65
60
|
```
|
66
61
|
|
67
62
|
Then in your app you can simply reference the constant to push to the queue:
|
@@ -83,19 +78,6 @@ Gracefully shut down workers by sending `SIGQUIT` to them. This will make sure
|
|
83
78
|
the worker completes its current job before shutting down. Jobs can be sent to
|
84
79
|
the queue meanwhile, and the worker will process them once it starts again.
|
85
80
|
|
86
|
-
### Queues
|
87
|
-
|
88
|
-
Localjobs supports multiple queues, and workers can be assigned to queues. By
|
89
|
-
default everything is on a single queue. To push to a named queue:
|
90
|
-
|
91
|
-
```ruby
|
92
|
-
email = Localjob.new("email")
|
93
|
-
email << EmailJob.new(current_user.id, welcome_email)
|
94
|
-
```
|
95
|
-
|
96
|
-
The worker spawn command `localjob work` takes a `--queues` argument which is a
|
97
|
-
comma seperated list of queues to listen on, e.g. `localjob work --queues email,webhooks`.
|
98
|
-
|
99
81
|
### Testing
|
100
82
|
|
101
83
|
Create your instance of the queue as normal in your setup:
|
@@ -103,7 +85,7 @@ Create your instance of the queue as normal in your setup:
|
|
103
85
|
```ruby
|
104
86
|
def setup
|
105
87
|
@queue = Localjob.new("test-queue")
|
106
|
-
@worker = Localjob::Worker.new("test-queue")
|
88
|
+
@worker = Localjob::Worker.new("test-queue")
|
107
89
|
end
|
108
90
|
```
|
109
91
|
|
@@ -132,6 +114,5 @@ def test_pop_and_send_to_worker
|
|
132
114
|
end
|
133
115
|
```
|
134
116
|
|
135
|
-
[
|
136
|
-
[pmq-gem]: https://github.com/Sirupsen/posix-mqueue
|
117
|
+
[sysv]: http://man7.org/linux/man-pages/man7/svipc.7.html
|
137
118
|
[blog]: http://sirupsen.com/unix-background-queue/
|
@@ -1,47 +1,34 @@
|
|
1
|
-
require '
|
1
|
+
require 'sysvmq'
|
2
2
|
|
3
3
|
class Localjob
|
4
|
-
class Channel
|
5
|
-
def shift
|
6
|
-
raise "SysV adapter does not support multiple queues" if @queues.size > 1
|
7
|
-
@queues.first.shift
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
4
|
class SysvAdapter
|
12
|
-
|
5
|
+
RECEIVE_ALL_TYPES = 0
|
13
6
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
unless @mq
|
20
|
-
File.open(@filename, "w") { }
|
21
|
-
key = ftok(@filename, 0)
|
22
|
-
|
23
|
-
@mq = MessageQueue.new(key, IPC_CREAT | 0600)
|
24
|
-
end
|
25
|
-
|
26
|
-
@mq
|
7
|
+
attr_reader :queue
|
8
|
+
|
9
|
+
def initialize(key, size: 8192, flags: SysVMQ::IPC_CREAT | 0660)
|
10
|
+
@key = key
|
11
|
+
@queue = SysVMQ.new(key, size, flags)
|
27
12
|
end
|
28
13
|
|
29
14
|
def receive
|
30
|
-
|
15
|
+
queue.receive(RECEIVE_ALL_TYPES)
|
31
16
|
end
|
32
17
|
|
33
18
|
def send(message)
|
34
|
-
|
19
|
+
queue.send(message, 1)
|
35
20
|
end
|
36
21
|
|
37
22
|
def size
|
38
|
-
|
23
|
+
queue.stats[:count]
|
24
|
+
end
|
25
|
+
|
26
|
+
def stats
|
27
|
+
queue.stats
|
39
28
|
end
|
40
29
|
|
41
30
|
def destroy
|
42
|
-
|
43
|
-
@mq.rm
|
44
|
-
@mq = nil
|
31
|
+
queue.destroy
|
45
32
|
end
|
46
33
|
end
|
47
34
|
end
|
data/lib/localjob/version.rb
CHANGED
data/lib/localjob/worker.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
class Localjob
|
2
2
|
class Worker
|
3
|
-
|
4
|
-
attr_reader :options
|
3
|
+
TERMINATION_MESSAGE = "__TERMINATE__"
|
5
4
|
|
6
|
-
|
7
|
-
|
5
|
+
attr_accessor :logger
|
6
|
+
attr_reader :options, :queue
|
7
|
+
|
8
|
+
def initialize(queue, logger: Logger.new(STDOUT), **options)
|
9
|
+
@queue, @logger = queue, logger
|
8
10
|
@options = options
|
9
11
|
@shutdown = false
|
10
12
|
end
|
@@ -18,35 +20,67 @@ class Localjob
|
|
18
20
|
Process.pid
|
19
21
|
end
|
20
22
|
|
21
|
-
def work
|
23
|
+
def work(thread: false)
|
22
24
|
logger.info "Worker #{pid} now listening!"
|
23
25
|
trap_signals
|
26
|
+
|
27
|
+
return work_thread if thread
|
28
|
+
|
24
29
|
create_pid_file(@options[:pid_file])
|
25
30
|
deamonize if @options[:deamon]
|
26
|
-
|
31
|
+
|
32
|
+
loop { break unless shift_and_process }
|
33
|
+
end
|
34
|
+
|
35
|
+
def kill
|
36
|
+
if @thread
|
37
|
+
Thread.kill(@thread)
|
38
|
+
@thread.join
|
39
|
+
else
|
40
|
+
shutdown
|
41
|
+
end
|
27
42
|
end
|
28
43
|
|
29
44
|
private
|
30
45
|
|
31
|
-
def
|
32
|
-
|
46
|
+
def work_thread
|
47
|
+
@thread = Thread.new do
|
48
|
+
begin
|
49
|
+
loop do
|
50
|
+
shift_and_process
|
51
|
+
end
|
52
|
+
# Respond to Thread.kill by sending termination message
|
53
|
+
ensure
|
54
|
+
shutdown
|
55
|
+
work
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
33
59
|
|
34
|
-
|
35
|
-
|
36
|
-
|
60
|
+
def shutdown!
|
61
|
+
logger.info "Worker #{pid} shutting down.."
|
62
|
+
File.rm(@options[:pid_file]) if @options[:pid_file]
|
63
|
+
return false if @thread
|
64
|
+
exit!
|
65
|
+
end
|
66
|
+
|
67
|
+
def shutdown
|
68
|
+
@queue << TERMINATION_MESSAGE
|
69
|
+
end
|
70
|
+
|
71
|
+
def shift_and_process
|
72
|
+
job = queue.shift
|
73
|
+
return shutdown! if job == TERMINATION_MESSAGE || !job
|
74
|
+
process(job)
|
75
|
+
return true # Explicit return of true, job#perform may return nil
|
76
|
+
rescue Object
|
37
77
|
logger.error "Worker #{pid} job failed: #{job}"
|
38
78
|
logger.error "#{$!}\n#{$@.join("\n")}"
|
39
79
|
end
|
40
80
|
|
41
81
|
def trap_signals
|
42
|
-
Signal.trap("QUIT") {
|
43
|
-
|
44
|
-
|
45
|
-
def wait
|
46
|
-
@waiting = true
|
47
|
-
job = yield
|
48
|
-
@waiting = false
|
49
|
-
job
|
82
|
+
Signal.trap("QUIT") { shutdown }
|
83
|
+
Signal.trap("INT") { shutdown }
|
50
84
|
end
|
51
85
|
|
52
86
|
def deamonize
|
@@ -56,10 +90,5 @@ class Localjob
|
|
56
90
|
def create_pid_file(path)
|
57
91
|
File.open(path, 'w') { |f| f << self.pid } if path
|
58
92
|
end
|
59
|
-
|
60
|
-
def graceful_shutdown
|
61
|
-
exit! if @waiting
|
62
|
-
@shutdown = true
|
63
|
-
end
|
64
93
|
end
|
65
94
|
end
|
data/lib/localjob.rb
CHANGED
@@ -3,15 +3,8 @@ require 'logger'
|
|
3
3
|
require 'forwardable'
|
4
4
|
|
5
5
|
require "localjob/version"
|
6
|
-
require 'localjob/channel'
|
7
6
|
require 'localjob/worker'
|
8
|
-
|
9
|
-
case RUBY_PLATFORM
|
10
|
-
when /linux/
|
11
|
-
require 'localjob/linux_adapter'
|
12
|
-
else
|
13
|
-
require 'localjob/sysv_adapter'
|
14
|
-
end
|
7
|
+
require 'localjob/sysv_adapter'
|
15
8
|
|
16
9
|
class Localjob
|
17
10
|
extend Forwardable
|
@@ -21,7 +14,8 @@ class Localjob
|
|
21
14
|
|
22
15
|
def_delegators :queue, :to_io, :destroy, :size
|
23
16
|
|
24
|
-
|
17
|
+
# LOCALJOB in 1337speak
|
18
|
+
def initialize(name = 0x10CA110B)
|
25
19
|
@name = name
|
26
20
|
end
|
27
21
|
|
@@ -30,14 +24,7 @@ class Localjob
|
|
30
24
|
end
|
31
25
|
|
32
26
|
def queue
|
33
|
-
|
34
|
-
|
35
|
-
case RUBY_PLATFORM
|
36
|
-
when /linux/
|
37
|
-
@queue = LinuxAdapter.new(@name)
|
38
|
-
else
|
39
|
-
@queue = SysvAdapter.new(@name)
|
40
|
-
end
|
27
|
+
@queue ||= SysvAdapter.new(@name)
|
41
28
|
end
|
42
29
|
|
43
30
|
def <<(object)
|
@@ -46,5 +33,8 @@ class Localjob
|
|
46
33
|
|
47
34
|
def shift
|
48
35
|
serializer.load queue.receive
|
36
|
+
# Bad serialization
|
37
|
+
rescue Object
|
38
|
+
nil
|
49
39
|
end
|
50
40
|
end
|
data/localjob.gemspec
CHANGED
@@ -17,12 +17,12 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
|
-
spec.extensions = ["ext/mkrf_conf.rb"]
|
21
20
|
|
22
21
|
spec.add_dependency "thor", "0.18.1"
|
23
|
-
spec.add_dependency "
|
22
|
+
spec.add_dependency "sysvmq", "~> 0.1"
|
24
23
|
|
25
24
|
spec.add_development_dependency "bundler", "~> 1.3"
|
26
25
|
spec.add_development_dependency "rake"
|
27
26
|
spec.add_development_dependency "mocha"
|
27
|
+
spec.add_development_dependency "stackprof"
|
28
28
|
end
|
data/test/localjob_test.rb
CHANGED
@@ -21,18 +21,10 @@ class LocaljobTest < LocaljobTestCase
|
|
21
21
|
def test_handles_multiple_queues
|
22
22
|
@localjob << WalrusJob.new("move")
|
23
23
|
|
24
|
-
other = queue(
|
24
|
+
other = queue(0xDEADCAFE)
|
25
25
|
other << WalrusJob.new("dance")
|
26
26
|
|
27
27
|
assert_equal 1, @localjob.size
|
28
28
|
assert_equal 1, other.size
|
29
29
|
end
|
30
|
-
|
31
|
-
on_platform 'linux' do
|
32
|
-
def test_throws_error_if_message_is_too_large
|
33
|
-
assert_raises Errno::EMSGSIZE do
|
34
|
-
@localjob << AngryWalrusJob.new("f" * @localjob.queue.mqueue.msgsize)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
30
|
end
|
data/test/mock_adapter.rb
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class SysvAdapterTest < LocaljobTestCase
|
4
|
+
def setup
|
5
|
+
@localjob = queue
|
6
|
+
@localjob.queue = Localjob::SysvAdapter.new(0xDEADC0DE)
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
@localjob.destroy
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_send_and_receive
|
14
|
+
msg = "Hello World"
|
15
|
+
@localjob << msg
|
16
|
+
assert_equal msg, @localjob.shift
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_size
|
20
|
+
@localjob << "Hello World"
|
21
|
+
assert_equal 1, @localjob.size
|
22
|
+
end
|
23
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -8,13 +8,13 @@ require 'jobs'
|
|
8
8
|
class LocaljobTestCase < MiniTest::Unit::TestCase
|
9
9
|
protected
|
10
10
|
# This is a method to make sure the logger is set right.
|
11
|
-
def worker(
|
12
|
-
Localjob::Worker.new(
|
11
|
+
def worker(queue)
|
12
|
+
Localjob::Worker.new(queue, logger: logger)
|
13
13
|
end
|
14
14
|
|
15
15
|
# This is a method to make sure all queues are registred and destroyed after
|
16
16
|
# each teach run.
|
17
|
-
def queue(name =
|
17
|
+
def queue(name = 0x10CA110B)
|
18
18
|
@queues ||= []
|
19
19
|
queue = Localjob.new(name)
|
20
20
|
@queues << queue
|
@@ -22,7 +22,7 @@ class LocaljobTestCase < MiniTest::Unit::TestCase
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def teardown
|
25
|
-
|
25
|
+
clear_queues
|
26
26
|
end
|
27
27
|
|
28
28
|
def logger
|
@@ -32,19 +32,7 @@ class LocaljobTestCase < MiniTest::Unit::TestCase
|
|
32
32
|
@logger = Logger.new(output_file)
|
33
33
|
end
|
34
34
|
|
35
|
-
def
|
35
|
+
def clear_queues
|
36
36
|
@queues.each(&:destroy) if @queues
|
37
|
-
|
38
|
-
# This forces the GC to garbage collect, and thus close file descriptioners
|
39
|
-
# in POSIX::Mqueue. Otherwise we'll get flooded with warnings. This is to
|
40
|
-
# ensure a clean state everytime with a new message queue for each test.
|
41
|
-
# It's slower. But safe.
|
42
|
-
GC.start
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.on_platform(platform)
|
46
|
-
if RUBY_PLATFORM =~ /#{platform}/
|
47
|
-
yield
|
48
|
-
end
|
49
37
|
end
|
50
38
|
end
|
data/test/worker_test.rb
CHANGED
@@ -3,7 +3,7 @@ require 'test_helper'
|
|
3
3
|
class WorkerTest < LocaljobTestCase
|
4
4
|
def setup
|
5
5
|
@localjob = queue
|
6
|
-
@worker = worker
|
6
|
+
@worker = worker(@localjob)
|
7
7
|
end
|
8
8
|
|
9
9
|
def test_pop_and_send_to_worker
|
@@ -33,58 +33,53 @@ class WorkerTest < LocaljobTestCase
|
|
33
33
|
@localjob << AngryWalrusJob.new(100)
|
34
34
|
@localjob << WalrusJob.new("be happy")
|
35
35
|
|
36
|
-
|
36
|
+
@worker.work(thread: true)
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
a.kill
|
38
|
+
sleep 0.1
|
39
|
+
@worker.kill
|
41
40
|
|
42
41
|
assert_equal 0, @localjob.size
|
43
42
|
end
|
44
43
|
|
45
44
|
def test_worker_doesnt_die_on_bad_serialization
|
46
|
-
@localjob
|
45
|
+
@localjob << "--- !ruby/object:Whatever {}\n"
|
47
46
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
a.kill
|
47
|
+
@worker.work(thread: true)
|
48
|
+
sleep 0.1
|
49
|
+
@worker.kill
|
52
50
|
end
|
53
51
|
|
54
|
-
|
55
|
-
|
56
|
-
# interrupt syscalls to give us signals.
|
57
|
-
def test_sigquit_terminates_the_worker
|
58
|
-
@localjob << WalrusJob.new("move")
|
52
|
+
def test_sigquit_terminates_the_worker
|
53
|
+
@localjob << WalrusJob.new("move")
|
59
54
|
|
60
|
-
|
55
|
+
assert_equal 1, @localjob.size
|
61
56
|
|
62
|
-
|
57
|
+
pid = fork { @worker.work }
|
58
|
+
sleep 0.1
|
63
59
|
|
64
|
-
|
65
|
-
sleep 0.1
|
60
|
+
Process.kill("QUIT", pid)
|
66
61
|
|
67
|
-
|
68
|
-
|
62
|
+
assert_equal 0, @localjob.size
|
63
|
+
end
|
69
64
|
|
70
|
-
|
71
|
-
|
65
|
+
def test_sigquit_terminates_the_worker
|
66
|
+
@localjob << WalrusJob.new("move")
|
72
67
|
|
73
|
-
|
74
|
-
|
68
|
+
pid = fork { @worker.work }
|
69
|
+
sleep 0.1
|
75
70
|
|
76
|
-
|
77
|
-
|
71
|
+
Process.kill("INT", pid)
|
72
|
+
end
|
78
73
|
|
79
|
-
|
74
|
+
def test_thread_worker
|
75
|
+
@localjob << WalrusJob.new("move")
|
80
76
|
|
81
|
-
|
77
|
+
assert_equal 1, @localjob.size
|
82
78
|
|
83
|
-
|
84
|
-
|
79
|
+
@worker.work(thread: true)
|
80
|
+
sleep 0.1
|
81
|
+
@worker.kill
|
85
82
|
|
86
|
-
|
87
|
-
assert_equal 0, other.size
|
88
|
-
end
|
83
|
+
assert_equal 0, @localjob.size
|
89
84
|
end
|
90
85
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: localjob
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Simon Eskildsen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-02-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -25,59 +25,73 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.18.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: sysvmq
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
33
|
+
version: '0.1'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
40
|
+
version: '0.1'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '1.3'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.3'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: mocha
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: stackprof
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
74
88
|
- !ruby/object:Gem::Version
|
75
89
|
version: '0'
|
76
90
|
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
|
-
- -
|
94
|
+
- - ">="
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '0'
|
83
97
|
description: Simple, self-contained background queue built on top of POSIX message
|
@@ -86,21 +100,17 @@ email:
|
|
86
100
|
- sirup@sirupsen.com
|
87
101
|
executables:
|
88
102
|
- localjob
|
89
|
-
extensions:
|
90
|
-
- ext/mkrf_conf.rb
|
103
|
+
extensions: []
|
91
104
|
extra_rdoc_files: []
|
92
105
|
files:
|
93
|
-
- .gitignore
|
106
|
+
- ".gitignore"
|
94
107
|
- Gemfile
|
95
108
|
- LICENSE.txt
|
96
109
|
- README.md
|
97
110
|
- Rakefile
|
98
111
|
- bin/localjob
|
99
|
-
- ext/mkrf_conf.rb
|
100
112
|
- lib/localjob.rb
|
101
|
-
- lib/localjob/channel.rb
|
102
113
|
- lib/localjob/cli.rb
|
103
|
-
- lib/localjob/linux_adapter.rb
|
104
114
|
- lib/localjob/mock_adapter.rb
|
105
115
|
- lib/localjob/sysv_adapter.rb
|
106
116
|
- lib/localjob/version.rb
|
@@ -109,6 +119,7 @@ files:
|
|
109
119
|
- test/jobs.rb
|
110
120
|
- test/localjob_test.rb
|
111
121
|
- test/mock_adapter.rb
|
122
|
+
- test/sysv_adapter_test.rb
|
112
123
|
- test/test_helper.rb
|
113
124
|
- test/worker_test.rb
|
114
125
|
homepage: ''
|
@@ -121,17 +132,17 @@ require_paths:
|
|
121
132
|
- lib
|
122
133
|
required_ruby_version: !ruby/object:Gem::Requirement
|
123
134
|
requirements:
|
124
|
-
- -
|
135
|
+
- - ">="
|
125
136
|
- !ruby/object:Gem::Version
|
126
137
|
version: '0'
|
127
138
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
139
|
requirements:
|
129
|
-
- -
|
140
|
+
- - ">="
|
130
141
|
- !ruby/object:Gem::Version
|
131
142
|
version: '0'
|
132
143
|
requirements: []
|
133
144
|
rubyforge_project:
|
134
|
-
rubygems_version: 2.0
|
145
|
+
rubygems_version: 2.2.0
|
135
146
|
signing_key:
|
136
147
|
specification_version: 4
|
137
148
|
summary: Simple, self-contained background queue built on top of POSIX message queues.
|
@@ -140,5 +151,6 @@ test_files:
|
|
140
151
|
- test/jobs.rb
|
141
152
|
- test/localjob_test.rb
|
142
153
|
- test/mock_adapter.rb
|
154
|
+
- test/sysv_adapter_test.rb
|
143
155
|
- test/test_helper.rb
|
144
156
|
- test/worker_test.rb
|
data/ext/mkrf_conf.rb
DELETED
data/lib/localjob/channel.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
class Localjob
|
2
|
-
class Channel
|
3
|
-
attr_accessor :queues
|
4
|
-
|
5
|
-
def initialize(queues)
|
6
|
-
@queues = [queues].flatten.map { |q| queue_from_name(q) }
|
7
|
-
end
|
8
|
-
|
9
|
-
def <<(queue)
|
10
|
-
@queues << queue_from_name(queue)
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
def queue_from_name(queue)
|
15
|
-
queue.instance_of?(Localjob) ? queue : Localjob.new(queue)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'posix/mqueue'
|
2
|
-
|
3
|
-
class Localjob
|
4
|
-
class Channel
|
5
|
-
def shift
|
6
|
-
(queue,), = IO.select(@queues)
|
7
|
-
queue.shift
|
8
|
-
rescue POSIX::Mqueue::QueueEmpty
|
9
|
-
retry
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class LinuxAdapter
|
14
|
-
attr_reader :mqueue
|
15
|
-
|
16
|
-
def initialize(name)
|
17
|
-
@mqueue = POSIX::Mqueue.new(fix_queue_name(name))
|
18
|
-
end
|
19
|
-
|
20
|
-
def receive
|
21
|
-
@mqueue.timedreceive
|
22
|
-
end
|
23
|
-
|
24
|
-
def send(message)
|
25
|
-
@mqueue.timedsend message
|
26
|
-
end
|
27
|
-
|
28
|
-
def size
|
29
|
-
@mqueue.size
|
30
|
-
end
|
31
|
-
|
32
|
-
def destroy
|
33
|
-
@mqueue.unlink
|
34
|
-
end
|
35
|
-
|
36
|
-
def to_io
|
37
|
-
@mqueue.to_io
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
def fix_queue_name(name)
|
42
|
-
name.start_with?('/') ? name : "/#{name}"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|