localjob 0.0.1
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 +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +57 -0
- data/Rakefile +9 -0
- data/bin/localjob +5 -0
- data/lib/localjob/channel.rb +25 -0
- data/lib/localjob/cli.rb +66 -0
- data/lib/localjob/version.rb +3 -0
- data/lib/localjob/worker.rb +65 -0
- data/lib/localjob.rb +48 -0
- data/localjob.gemspec +27 -0
- data/test/jobs.rb +11 -0
- data/test/localjob_test.rb +36 -0
- data/test/test_helper.rb +44 -0
- data/test/worker_test.rb +85 -0
- metadata +137 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: becc6c53c0de0692e654c0e4fd8b220b13baa424
|
4
|
+
data.tar.gz: 770a92796d0fedf97c3d66728e039b3d966e7f92
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f56f0b1ae32cda8650cd0e6375278ad34bf16c00db257a180d1070c980c7eee422f7e604afcbbe013c7da7c0ae403d2f0a7c795987fd52330f101fd19f3a985e
|
7
|
+
data.tar.gz: 3ecf92a571bd824625ea348b5f0ccdf8e4f5b7e3ba2fc3ab468a1915c90a768f5a250803d71a8a1caf41387c21d237320f605c250e6edcf4bdbcc035d4b1c90f
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Simon Eskildsen
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# Localjob
|
2
|
+
|
3
|
+
Localjob is a simple, self-contained background queue built on top of [POSIX
|
4
|
+
message queues][pmq]. Workers and the app pushing to the queue must reside on
|
5
|
+
the same machine. It's the sqlite of background queues (although sqlite scales
|
6
|
+
further than Localjob). Here's a post about [how it works][blog].
|
7
|
+
|
8
|
+
Localjob is for early-development situations where you don't need a
|
9
|
+
full-featured background queue, but just want to get started with something
|
10
|
+
simple that does not rely on any external services. A bigger goal with the
|
11
|
+
project is to be able to migrate to another background queue system by switching
|
12
|
+
adapter: `Localjob.adapter = Resque` to switch to Resque, without changes to
|
13
|
+
your own code.
|
14
|
+
|
15
|
+
The POSIX message queue is persistent till reboot. You will need to tune system
|
16
|
+
parameters for your application, please consult [posix-mqueue][pmq-gem]'s
|
17
|
+
documentation.
|
18
|
+
|
19
|
+
Localjob works on Ruby >= 2.0.0 and Linux.
|
20
|
+
|
21
|
+
WIP not everything works as advertised, but try it out and report anything that
|
22
|
+
doesn't work! It's not released as a gem yet, so add the following to your
|
23
|
+
Gemfile to use it:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
gem 'localjob', git: "git@github.com:Sirupsen/localjob.git"
|
27
|
+
```
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
Localjobs have the following format:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
class EmailJob
|
35
|
+
def initialize(user_id, email)
|
36
|
+
@user, @email = User.find(user_id), email
|
37
|
+
end
|
38
|
+
|
39
|
+
def perform
|
40
|
+
@email.deliver_to(@user)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
To queue a job, create an instance of it and push it to the queue:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
queue = Localjob.new
|
49
|
+
queue << EmailJob.new(current_user.id, welcome_email)
|
50
|
+
```
|
51
|
+
|
52
|
+
Then spawn a worker with `localjob work`. It takes a few arguments, like `-d` to
|
53
|
+
deamonize itself. `localjob help work` to list all options.
|
54
|
+
|
55
|
+
[pmq]: http://linux.die.net/man/7/mq_overview
|
56
|
+
[pmq-gem]: https://github.com/Sirupsen/posix-mqueue
|
57
|
+
[blog]: http://sirupsen.com/unix-background-queue/
|
data/Rakefile
ADDED
data/bin/localjob
ADDED
@@ -0,0 +1,25 @@
|
|
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
|
+
def shift
|
14
|
+
(queue,), = IO.select(@queues)
|
15
|
+
queue.shift
|
16
|
+
rescue POSIX::Mqueue::QueueEmpty
|
17
|
+
retry
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def queue_from_name(queue)
|
22
|
+
queue.instance_of?(Localjob) ? queue : Localjob.new(queue)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/localjob/cli.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
class Localjob
|
4
|
+
class CLI < Thor
|
5
|
+
option :queues, aliases: ["-q"], type: :string, default: "localjob"
|
6
|
+
option :require, aliases: ["-r"], type: :string, default: "."
|
7
|
+
option :pid_file, aliases: ["-p"], type: :string
|
8
|
+
option :daemon, aliases: ["-d"], type: :boolean
|
9
|
+
desc "work", "Start worker to process jobs"
|
10
|
+
def work
|
11
|
+
load_environment options[:require]
|
12
|
+
|
13
|
+
queues = options[:queues].split(",")
|
14
|
+
Localjob::Worker.new(queues, options.slice(:daemon, :pid_file)).work
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "size", "Outputs the size of queues"
|
18
|
+
option :queues, aliases: ["-q"], type: :string, default: "localjob"
|
19
|
+
def size
|
20
|
+
queues = options[:queues].split(",")
|
21
|
+
queues.each do |queue|
|
22
|
+
puts "Size of /#{queue}: #{Localjob.new(queue).size}/#{msg_max}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "destroy", "Destroys all queues passed"
|
27
|
+
option :queues, aliases: ["-q"], type: :string, default: "localjob"
|
28
|
+
def destroy
|
29
|
+
options[:queues].split(",").each do |queue|
|
30
|
+
Localjob.new(queue).destroy
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "list", "Lists all queues"
|
35
|
+
def list
|
36
|
+
unless File.exists?("/dev/mqueue")
|
37
|
+
system "mkdir /dev/mqueue"
|
38
|
+
system "mount -t mqueue none /dev/mqueue"
|
39
|
+
end
|
40
|
+
|
41
|
+
system "ls -l /dev/mqueue"
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def load_environment(file)
|
46
|
+
if rails?(file)
|
47
|
+
require 'rails'
|
48
|
+
require File.expand_path("#{file}/config/environment.rb")
|
49
|
+
::Rails.application.eager_load!
|
50
|
+
elsif File.file?(file)
|
51
|
+
require File.expand_path(file)
|
52
|
+
else
|
53
|
+
puts "No require path passed, requires -r if not in Rails"
|
54
|
+
exit
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def rails?(file)
|
59
|
+
File.exists?(File.expand_path("#{file}/config/environment.rb"))
|
60
|
+
end
|
61
|
+
|
62
|
+
def msg_max
|
63
|
+
@msg_max ||= File.read("/proc/sys/fs/mqueue/msg_max")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
class Localjob
|
2
|
+
class Worker
|
3
|
+
attr_accessor :logger, :channel
|
4
|
+
attr_reader :options
|
5
|
+
|
6
|
+
def initialize(queues, logger: Logger.new(STDOUT), **options)
|
7
|
+
@channel, @logger = Channel.new(queues), logger
|
8
|
+
@options = options
|
9
|
+
@shutdown = false
|
10
|
+
end
|
11
|
+
|
12
|
+
def process(job)
|
13
|
+
logger.info "Worker #{pid}: #{job.inspect}"
|
14
|
+
job.perform
|
15
|
+
end
|
16
|
+
|
17
|
+
def pid
|
18
|
+
Process.pid
|
19
|
+
end
|
20
|
+
|
21
|
+
def work
|
22
|
+
logger.info "Worker #{pid} now listening!"
|
23
|
+
trap_signals
|
24
|
+
create_pid_file(@options[:pid_file])
|
25
|
+
deamonize if @options[:deamon]
|
26
|
+
loop { shift_and_process }
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def shift_and_process
|
32
|
+
exit! if @shutdown
|
33
|
+
|
34
|
+
job = wait { @channel.shift }
|
35
|
+
process job
|
36
|
+
rescue Object => e
|
37
|
+
logger.error "Worker #{pid} job failed: #{job}"
|
38
|
+
logger.error "#{$!}\n#{$@.join("\n")}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def trap_signals
|
42
|
+
Signal.trap("QUIT") { graceful_shutdown }
|
43
|
+
end
|
44
|
+
|
45
|
+
def wait
|
46
|
+
@waiting = true
|
47
|
+
job = yield
|
48
|
+
@waiting = false
|
49
|
+
job
|
50
|
+
end
|
51
|
+
|
52
|
+
def deamonize
|
53
|
+
Process.daemon(true, true)
|
54
|
+
end
|
55
|
+
|
56
|
+
def create_pid_file(path)
|
57
|
+
File.open(path, 'w') { |f| f << self.pid } if path
|
58
|
+
end
|
59
|
+
|
60
|
+
def graceful_shutdown
|
61
|
+
exit! if @waiting
|
62
|
+
@shutdown = true
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/localjob.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'posix/mqueue'
|
2
|
+
require 'yaml'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
require "localjob/version"
|
6
|
+
require 'localjob/channel'
|
7
|
+
require 'localjob/worker'
|
8
|
+
|
9
|
+
class Localjob
|
10
|
+
attr_reader :queue_name
|
11
|
+
|
12
|
+
def initialize(queue = "localjob")
|
13
|
+
@queue_name = fix_queue_name(queue)
|
14
|
+
end
|
15
|
+
|
16
|
+
def serializer
|
17
|
+
YAML
|
18
|
+
end
|
19
|
+
|
20
|
+
def queue
|
21
|
+
@queue ||= POSIX::Mqueue.new(@queue_name)
|
22
|
+
end
|
23
|
+
|
24
|
+
def <<(object)
|
25
|
+
queue.timedsend serializer.dump(object)
|
26
|
+
end
|
27
|
+
|
28
|
+
def size
|
29
|
+
queue.size
|
30
|
+
end
|
31
|
+
|
32
|
+
def shift
|
33
|
+
serializer.load queue.timedreceive
|
34
|
+
end
|
35
|
+
|
36
|
+
def destroy
|
37
|
+
queue.unlink
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_io
|
41
|
+
queue.to_io
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def fix_queue_name(queue)
|
46
|
+
queue.start_with?('/') ? queue : "/#{queue}"
|
47
|
+
end
|
48
|
+
end
|
data/localjob.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'localjob/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "localjob"
|
8
|
+
spec.version = Localjob::VERSION
|
9
|
+
spec.authors = ["Simon Eskildsen"]
|
10
|
+
spec.email = ["sirup@sirupsen.com"]
|
11
|
+
spec.description = %q{Simple, self-contained background queue built on top of POSIX message queues.}
|
12
|
+
spec.summary = %q{Simple, self-contained background queue built on top of POSIX message queues. It only works on Linux.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "posix-mqueue", "0.0.9"
|
22
|
+
spec.add_dependency "thor", "0.18.1"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "mocha"
|
27
|
+
end
|
data/test/jobs.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class LocaljobTest < LocaljobTestCase
|
4
|
+
def setup
|
5
|
+
@localjob = queue
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_push_should_put_a_job_in_queue
|
9
|
+
@localjob << WalrusJob.new("move")
|
10
|
+
assert_equal 1, @localjob.size
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_pop_from_queue
|
14
|
+
@localjob << WalrusJob.new("move")
|
15
|
+
|
16
|
+
job = @localjob.shift
|
17
|
+
assert_instance_of WalrusJob, job
|
18
|
+
assert_equal "move", job.action
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_throws_error_if_message_is_too_large
|
22
|
+
assert_raises Errno::EMSGSIZE do
|
23
|
+
@localjob << AngryWalrusJob.new("f" * @localjob.queue.msgsize)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_handles_multiple_queues
|
28
|
+
@localjob << WalrusJob.new("move")
|
29
|
+
|
30
|
+
other = queue("other-queue")
|
31
|
+
other << WalrusJob.new("dance")
|
32
|
+
|
33
|
+
assert_equal 1, @localjob.size
|
34
|
+
assert_equal 1, other.size
|
35
|
+
end
|
36
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'minitest/unit'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
$:<< File.dirname(__FILE__) + "/../lib"
|
4
|
+
require 'localjob'
|
5
|
+
require "mocha/setup"
|
6
|
+
require 'jobs'
|
7
|
+
|
8
|
+
class LocaljobTestCase < MiniTest::Unit::TestCase
|
9
|
+
protected
|
10
|
+
# This is a method to make sure the logger is set right.
|
11
|
+
def worker(queues = ["/localjob-test"])
|
12
|
+
Localjob::Worker.new(queues, logger: logger)
|
13
|
+
end
|
14
|
+
|
15
|
+
# This is a method to make sure all queues are registred and destroyed after
|
16
|
+
# each teach run.
|
17
|
+
def queue(name = "/localjob-test")
|
18
|
+
@queues ||= []
|
19
|
+
queue = Localjob.new(name)
|
20
|
+
@queues << queue
|
21
|
+
queue
|
22
|
+
end
|
23
|
+
|
24
|
+
def teardown
|
25
|
+
clear_queue
|
26
|
+
end
|
27
|
+
|
28
|
+
def logger
|
29
|
+
return @logger if @logger
|
30
|
+
|
31
|
+
output_file = ENV["DEBUG"] ? STDOUT : "/dev/null"
|
32
|
+
@logger = Logger.new(output_file)
|
33
|
+
end
|
34
|
+
|
35
|
+
def clear_queue
|
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
|
+
end
|
data/test/worker_test.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class WorkerTest < LocaljobTestCase
|
4
|
+
def setup
|
5
|
+
@localjob = queue
|
6
|
+
@worker = worker
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_pop_and_send_to_worker
|
10
|
+
WalrusJob.any_instance.expects(:perform)
|
11
|
+
|
12
|
+
@localjob << WalrusJob.new("move")
|
13
|
+
|
14
|
+
job = @localjob.shift
|
15
|
+
@worker.process(job)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_working_off_queue_in_child
|
19
|
+
@localjob << WalrusJob.new("move")
|
20
|
+
|
21
|
+
fork do
|
22
|
+
job = @localjob.shift
|
23
|
+
@worker.process(job)
|
24
|
+
end
|
25
|
+
|
26
|
+
Process.wait
|
27
|
+
assert_equal 0, @localjob.size
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_sigquit_terminates_the_worker
|
31
|
+
@localjob << WalrusJob.new("move")
|
32
|
+
|
33
|
+
assert_equal 1, @localjob.size
|
34
|
+
|
35
|
+
pid = fork { @worker.work }
|
36
|
+
|
37
|
+
Process.kill("QUIT", pid)
|
38
|
+
Process.wait
|
39
|
+
|
40
|
+
assert_equal 0, @localjob.size
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_doesnt_stop_on_error
|
44
|
+
@localjob << AngryWalrusJob.new(100)
|
45
|
+
@localjob << WalrusJob.new("be happy")
|
46
|
+
|
47
|
+
pid = fork { @worker.work }
|
48
|
+
|
49
|
+
# Hack to account for race condition, 0.01s should be plenty
|
50
|
+
sleep 0.01
|
51
|
+
Process.kill("QUIT", pid)
|
52
|
+
Process.wait
|
53
|
+
|
54
|
+
assert_equal 0, @localjob.size
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_workers_listen_on_multiple_queues
|
58
|
+
@localjob << WalrusJob.new("move")
|
59
|
+
|
60
|
+
other = queue("other-queue")
|
61
|
+
other << WalrusJob.new("dance")
|
62
|
+
|
63
|
+
@worker.channel << 'other-queue'
|
64
|
+
|
65
|
+
pid = fork { @worker.work }
|
66
|
+
|
67
|
+
# Hack to account for race condition, 0.01s should be plenty
|
68
|
+
sleep 0.01
|
69
|
+
Process.kill("QUIT", pid)
|
70
|
+
Process.wait
|
71
|
+
|
72
|
+
assert_equal 0, @localjob.size
|
73
|
+
assert_equal 0, other.size
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_worker_doesnt_die_on_bad_serialization
|
77
|
+
@localjob.queue.timedsend "--- !ruby/object:Whatever {}\n"
|
78
|
+
|
79
|
+
pid = fork { @worker.work }
|
80
|
+
|
81
|
+
sleep 0.01
|
82
|
+
Process.kill("QUIT", pid)
|
83
|
+
Process.wait
|
84
|
+
end
|
85
|
+
end
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: localjob
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Simon Eskildsen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-09-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: posix-mqueue
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.0.9
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.0.9
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thor
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.18.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.18.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mocha
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
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
|
+
description: Simple, self-contained background queue built on top of POSIX message
|
84
|
+
queues.
|
85
|
+
email:
|
86
|
+
- sirup@sirupsen.com
|
87
|
+
executables:
|
88
|
+
- localjob
|
89
|
+
extensions: []
|
90
|
+
extra_rdoc_files: []
|
91
|
+
files:
|
92
|
+
- .gitignore
|
93
|
+
- Gemfile
|
94
|
+
- LICENSE.txt
|
95
|
+
- README.md
|
96
|
+
- Rakefile
|
97
|
+
- bin/localjob
|
98
|
+
- lib/localjob.rb
|
99
|
+
- lib/localjob/channel.rb
|
100
|
+
- lib/localjob/cli.rb
|
101
|
+
- lib/localjob/version.rb
|
102
|
+
- lib/localjob/worker.rb
|
103
|
+
- localjob.gemspec
|
104
|
+
- test/jobs.rb
|
105
|
+
- test/localjob_test.rb
|
106
|
+
- test/test_helper.rb
|
107
|
+
- test/worker_test.rb
|
108
|
+
homepage: ''
|
109
|
+
licenses:
|
110
|
+
- MIT
|
111
|
+
metadata: {}
|
112
|
+
post_install_message:
|
113
|
+
rdoc_options: []
|
114
|
+
require_paths:
|
115
|
+
- lib
|
116
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
requirements: []
|
127
|
+
rubyforge_project:
|
128
|
+
rubygems_version: 2.0.3
|
129
|
+
signing_key:
|
130
|
+
specification_version: 4
|
131
|
+
summary: Simple, self-contained background queue built on top of POSIX message queues.
|
132
|
+
It only works on Linux.
|
133
|
+
test_files:
|
134
|
+
- test/jobs.rb
|
135
|
+
- test/localjob_test.rb
|
136
|
+
- test/test_helper.rb
|
137
|
+
- test/worker_test.rb
|