tennis-jobs 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.markdown +38 -169
- data/examples/async_sum.rb +36 -0
- data/lib/tennis.rb +6 -11
- data/lib/tennis/action.rb +30 -0
- data/lib/tennis/actor.rb +49 -0
- data/lib/tennis/backend/abstract.rb +38 -0
- data/lib/tennis/backend/memory.rb +57 -0
- data/lib/tennis/{serializer/generic.rb → backend/serializer.rb} +30 -13
- data/lib/tennis/backend/task.rb +36 -0
- data/lib/tennis/cli.rb +21 -61
- data/lib/tennis/configuration.rb +9 -10
- data/lib/tennis/exceptions.rb +3 -0
- data/lib/tennis/fetcher.rb +36 -0
- data/lib/tennis/job.rb +30 -0
- data/lib/tennis/launcher.rb +38 -0
- data/lib/tennis/worker.rb +46 -0
- data/lib/tennis/worker_pool.rb +114 -0
- data/tennis-jobs.gemspec +4 -4
- metadata +19 -16
- data/examples/deferable.rb +0 -46
- data/examples/example.rb +0 -52
- data/examples/serializer.rb +0 -37
- data/lib/tennis/worker/deferable.rb +0 -55
- data/lib/tennis/worker/deferable/action.rb +0 -25
- data/lib/tennis/worker/generic.rb +0 -58
- data/lib/tennis/worker/generic/before_hook.rb +0 -17
- data/lib/tennis/worker/generic/options.rb +0 -19
- data/lib/tennis/worker/generic/serialize.rb +0 -26
data/tennis-jobs.gemspec
CHANGED
@@ -4,12 +4,12 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "tennis-jobs"
|
7
|
-
spec.version = "0.
|
7
|
+
spec.version = "0.4.0"
|
8
8
|
spec.authors = ["Nicolas ZERMATI"]
|
9
9
|
spec.email = ["nicoolas25@gmail.com"]
|
10
10
|
|
11
|
-
spec.summary = %q{A
|
12
|
-
spec.description = %q{A
|
11
|
+
spec.summary = %q{A backend agnostic, actor based, background jobs library.}
|
12
|
+
spec.description = %q{A backend agnostic, actor based, background jobs library.}
|
13
13
|
spec.homepage = "https://github.com/nicoolas25/tennis"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_runtime_dependency "
|
21
|
+
spec.add_runtime_dependency "celluloid"
|
22
22
|
|
23
23
|
spec.add_development_dependency "bundler", "~> 1.10"
|
24
24
|
spec.add_development_dependency "rake", "~> 10.0"
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tennis-jobs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicolas ZERMATI
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: celluloid
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
@@ -122,7 +122,7 @@ dependencies:
|
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
|
-
description: A
|
125
|
+
description: A backend agnostic, actor based, background jobs library.
|
126
126
|
email:
|
127
127
|
- nicoolas25@gmail.com
|
128
128
|
executables:
|
@@ -139,19 +139,22 @@ files:
|
|
139
139
|
- README.markdown
|
140
140
|
- Rakefile
|
141
141
|
- bin/tennis
|
142
|
-
- examples/
|
143
|
-
- examples/example.rb
|
144
|
-
- examples/serializer.rb
|
142
|
+
- examples/async_sum.rb
|
145
143
|
- lib/tennis.rb
|
144
|
+
- lib/tennis/action.rb
|
145
|
+
- lib/tennis/actor.rb
|
146
|
+
- lib/tennis/backend/abstract.rb
|
147
|
+
- lib/tennis/backend/memory.rb
|
148
|
+
- lib/tennis/backend/serializer.rb
|
149
|
+
- lib/tennis/backend/task.rb
|
146
150
|
- lib/tennis/cli.rb
|
147
151
|
- lib/tennis/configuration.rb
|
148
|
-
- lib/tennis/
|
149
|
-
- lib/tennis/
|
150
|
-
- lib/tennis/
|
151
|
-
- lib/tennis/
|
152
|
-
- lib/tennis/worker
|
153
|
-
- lib/tennis/
|
154
|
-
- lib/tennis/worker/generic/serialize.rb
|
152
|
+
- lib/tennis/exceptions.rb
|
153
|
+
- lib/tennis/fetcher.rb
|
154
|
+
- lib/tennis/job.rb
|
155
|
+
- lib/tennis/launcher.rb
|
156
|
+
- lib/tennis/worker.rb
|
157
|
+
- lib/tennis/worker_pool.rb
|
155
158
|
- tennis-jobs.gemspec
|
156
159
|
homepage: https://github.com/nicoolas25/tennis
|
157
160
|
licenses:
|
@@ -173,8 +176,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
176
|
version: '0'
|
174
177
|
requirements: []
|
175
178
|
rubyforge_project:
|
176
|
-
rubygems_version: 2.4.
|
179
|
+
rubygems_version: 2.4.8
|
177
180
|
signing_key:
|
178
181
|
specification_version: 4
|
179
|
-
summary: A
|
182
|
+
summary: A backend agnostic, actor based, background jobs library.
|
180
183
|
test_files: []
|
data/examples/deferable.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Create a client or a worker showing the serialization process.
|
3
|
-
#
|
4
|
-
# To run this example you should start a worker, then a client in a separate
|
5
|
-
# shell. Of course you'll also need a running RabbitMQ server.
|
6
|
-
#
|
7
|
-
# Use RABBITMQ_URL environment variable if you need to customize the RabbitMQ
|
8
|
-
# address.
|
9
|
-
#
|
10
|
-
|
11
|
-
$LOAD_PATH.unshift("./lib")
|
12
|
-
|
13
|
-
require "tennis"
|
14
|
-
|
15
|
-
require_relative "example"
|
16
|
-
|
17
|
-
class Model
|
18
|
-
include Tennis::Worker::Deferable
|
19
|
-
|
20
|
-
attr_reader :id
|
21
|
-
|
22
|
-
def initialize(id)
|
23
|
-
@id = id
|
24
|
-
end
|
25
|
-
|
26
|
-
def method(numbers)
|
27
|
-
puts "At #{Time.now}, Model##{id} run method with #{numbers.inspect}\n"
|
28
|
-
end
|
29
|
-
|
30
|
-
# Usually the ORM provides this method. Here we're just faking it.
|
31
|
-
def self.find(id)
|
32
|
-
new(id)
|
33
|
-
end
|
34
|
-
|
35
|
-
# Usually the ORM provides this method. Here we're faking it too.
|
36
|
-
def attributes
|
37
|
-
{ id: @id }
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
Example.new(__FILE__, Model).run do |i|
|
42
|
-
array = Array.new(5) { 1 + rand(5) }
|
43
|
-
print "Press enter to enqueue a random array..." ; gets
|
44
|
-
puts "Calling <Model##{i}>.method(#{array.inspect})"
|
45
|
-
Model.new(i).defer.method(array)
|
46
|
-
end
|
data/examples/example.rb
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
require "logger"
|
2
|
-
require "optparse"
|
3
|
-
require "sneakers/runner"
|
4
|
-
|
5
|
-
class Example
|
6
|
-
def initialize(filename, klass)
|
7
|
-
@filename = filename
|
8
|
-
@klass = klass
|
9
|
-
end
|
10
|
-
|
11
|
-
def run(&client_code)
|
12
|
-
configure_workers
|
13
|
-
parse_options
|
14
|
-
if @options[:client]
|
15
|
-
start_client(client_code)
|
16
|
-
elsif @options[:worker]
|
17
|
-
start_worker
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
protected
|
22
|
-
|
23
|
-
def configure_workers
|
24
|
-
Tennis.configure do |config|
|
25
|
-
config.async = true
|
26
|
-
config.exchange = "example"
|
27
|
-
config.workers = 1
|
28
|
-
config.logger = Logger.new(STDOUT)
|
29
|
-
config.logger.level = Logger::WARN
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def start_client(block, i = 1)
|
34
|
-
block.call(i)
|
35
|
-
start_client(block, i + 1)
|
36
|
-
rescue Interrupt
|
37
|
-
puts "Exiting the client"
|
38
|
-
end
|
39
|
-
|
40
|
-
def start_worker
|
41
|
-
Sneakers::Runner.new([@klass.worker]).run
|
42
|
-
end
|
43
|
-
|
44
|
-
def parse_options
|
45
|
-
@options = {}
|
46
|
-
OptionParser.new do |opts|
|
47
|
-
opts.banner = "Usage: #{@filename}"
|
48
|
-
opts.on("-c", "--client", "Run the client") { @options[:client] = true }
|
49
|
-
opts.on("-w", "--worker", "Run the worker") { @options[:worker] = true }
|
50
|
-
end.parse!
|
51
|
-
end
|
52
|
-
end
|
data/examples/serializer.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Create a client or a worker showing the serialization process.
|
3
|
-
#
|
4
|
-
# To run this example you should start a worker, then a client in a separate
|
5
|
-
# shell. Of course you'll also need a running RabbitMQ server.
|
6
|
-
#
|
7
|
-
# Use RABBITMQ_URL environment variable if you need to customize the RabbitMQ
|
8
|
-
# address.
|
9
|
-
#
|
10
|
-
|
11
|
-
$LOAD_PATH.unshift("./lib")
|
12
|
-
|
13
|
-
require "json"
|
14
|
-
require "tennis"
|
15
|
-
|
16
|
-
require_relative "example"
|
17
|
-
|
18
|
-
class SumWorker
|
19
|
-
include Tennis::Worker::Generic
|
20
|
-
|
21
|
-
serialize loader: ->(message){ JSON.parse(message) },
|
22
|
-
dumper: ->(message){ JSON.generate(message) }
|
23
|
-
|
24
|
-
work do |int_array|
|
25
|
-
sum = int_array.inject(0, &:+)
|
26
|
-
puts "At #{Time.now} I received an array. Sum of its elements is: #{sum}"
|
27
|
-
ack!
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
Example.new(__FILE__, SumWorker).run do
|
32
|
-
array = Array.new(5) { 1 + rand(5) }
|
33
|
-
print "Press enter to enqueue a random array..." ; gets
|
34
|
-
puts "Sending #{array.inspect} to the #{SumWorker::Worker.queue_name} queue!"
|
35
|
-
SumWorker.send_work(array)
|
36
|
-
end
|
37
|
-
|
@@ -1,55 +0,0 @@
|
|
1
|
-
module Tennis
|
2
|
-
module Worker
|
3
|
-
module Deferable
|
4
|
-
|
5
|
-
autoload :Action, "tennis/worker/deferable/action"
|
6
|
-
|
7
|
-
def self.included(base)
|
8
|
-
base.extend DSL
|
9
|
-
base.include Worker::Generic
|
10
|
-
base.serialize Serializer::Generic.new
|
11
|
-
define_work_broker(base)
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.define_work_broker(base)
|
15
|
-
base.work do |message|
|
16
|
-
begin
|
17
|
-
receiver, method, arguments = message
|
18
|
-
result = receiver.__send__(method, *arguments)
|
19
|
-
instance_exec(result, &base._on_success)
|
20
|
-
rescue => exception
|
21
|
-
instance_exec(exception, message, &base._on_error)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def defer
|
27
|
-
Action.new(self.class, self)
|
28
|
-
end
|
29
|
-
|
30
|
-
module DSL
|
31
|
-
|
32
|
-
def defer
|
33
|
-
Action.new(self, self)
|
34
|
-
end
|
35
|
-
|
36
|
-
def on_error(&block)
|
37
|
-
@_on_error = block
|
38
|
-
end
|
39
|
-
|
40
|
-
def on_success(&block)
|
41
|
-
@_on_success = block
|
42
|
-
end
|
43
|
-
|
44
|
-
def _on_error
|
45
|
-
@_on_error || ->(_, _){ reject! }
|
46
|
-
end
|
47
|
-
|
48
|
-
def _on_success
|
49
|
-
@_on_success || ->(_){ ack! }
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
class Tennis::Worker::Deferable::Action
|
2
|
-
def initialize(worker_class, receiver)
|
3
|
-
@worker_class = worker_class
|
4
|
-
@receiver = receiver
|
5
|
-
_create_methods!
|
6
|
-
end
|
7
|
-
|
8
|
-
private
|
9
|
-
|
10
|
-
def _create_methods!
|
11
|
-
_methods.each do |method|
|
12
|
-
self.define_singleton_method(method) do |*arguments|
|
13
|
-
@worker_class.send_work([@receiver, method, arguments])
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def _methods
|
19
|
-
if @receiver.kind_of?(Class)
|
20
|
-
@receiver.methods(false).map(&:to_s)
|
21
|
-
else
|
22
|
-
@receiver.class.instance_methods(false).map(&:to_s)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,58 +0,0 @@
|
|
1
|
-
module Tennis
|
2
|
-
module Worker
|
3
|
-
module Generic
|
4
|
-
|
5
|
-
autoload :BeforeHook, "tennis/worker/generic/before_hook"
|
6
|
-
autoload :Serialize, "tennis/worker/generic/serialize"
|
7
|
-
autoload :Options, "tennis/worker/generic/options"
|
8
|
-
|
9
|
-
def self.included(base)
|
10
|
-
base.extend BeforeHook
|
11
|
-
base.extend Serialize
|
12
|
-
base.extend Options
|
13
|
-
base.extend DSL
|
14
|
-
base.worker = Class.new do
|
15
|
-
@@parent = base
|
16
|
-
|
17
|
-
include Sneakers::Worker
|
18
|
-
from_queue @@parent.name
|
19
|
-
|
20
|
-
def work(message)
|
21
|
-
message = @@parent._apply_serializer(:load, message)
|
22
|
-
@@parent._process_before_hooks(message, self)
|
23
|
-
instance_exec(message, &@@parent._work)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
module DSL
|
29
|
-
|
30
|
-
attr_accessor :worker
|
31
|
-
|
32
|
-
def work(&block)
|
33
|
-
@_work = block
|
34
|
-
end
|
35
|
-
|
36
|
-
def _work
|
37
|
-
@_work ||= ->(_){ ack! }
|
38
|
-
end
|
39
|
-
|
40
|
-
def send_work(message)
|
41
|
-
message = _apply_serializer(:dump, message)
|
42
|
-
if Tennis.config.async
|
43
|
-
publisher_opts = worker.queue_opts.select do |opt_name, _|
|
44
|
-
opt_name == :exchange ||
|
45
|
-
opt_name == :exchange_type
|
46
|
-
end
|
47
|
-
publisher = Sneakers::Publisher.new(publisher_opts)
|
48
|
-
publisher.publish(message, to_queue: worker.queue_name)
|
49
|
-
publisher.instance_variable_get(:@bunny).close
|
50
|
-
else
|
51
|
-
worker.new.work(message)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module Tennis::Worker::Generic::BeforeHook
|
2
|
-
def before(&block)
|
3
|
-
if block_given?
|
4
|
-
_before_hooks << block
|
5
|
-
end
|
6
|
-
end
|
7
|
-
|
8
|
-
def _process_before_hooks(message, worker)
|
9
|
-
_before_hooks.each do |hook|
|
10
|
-
hook.call(message, worker)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def _before_hooks
|
15
|
-
@_before_hooks ||= []
|
16
|
-
end
|
17
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module Tennis::Worker::Generic::Options
|
2
|
-
SNEAKER_QUEUE_OPTIONS = %i(exchange).freeze
|
3
|
-
|
4
|
-
def set_option(symbol, value)
|
5
|
-
if symbol == :queue_name
|
6
|
-
worker.from_queue(value, worker.queue_opts)
|
7
|
-
else
|
8
|
-
options[symbol] = value
|
9
|
-
if SNEAKER_QUEUE_OPTIONS.include?(symbol)
|
10
|
-
worker.queue_opts[symbol] = value
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def options
|
16
|
-
@_options ||= {}
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module Tennis::Worker::Generic::Serialize
|
2
|
-
def serialize(object = nil, loader: nil, dumper: nil)
|
3
|
-
if object
|
4
|
-
_serializers[:load] = object if object.respond_to?(:load)
|
5
|
-
_serializers[:dump] = object if object.respond_to?(:dump)
|
6
|
-
else
|
7
|
-
_serializers[:load] = loader if loader
|
8
|
-
_serializers[:dump] = dumper if dumper
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def _apply_serializer(serializer_kind, message)
|
13
|
-
serializer = _serializers[serializer_kind]
|
14
|
-
if serializer.kind_of?(Proc)
|
15
|
-
serializer.call(message)
|
16
|
-
elsif serializer.respond_to?(serializer_kind)
|
17
|
-
serializer.__send__(serializer_kind, message)
|
18
|
-
else
|
19
|
-
fail "Unexpected (de)serializer, it must be a Proc or respond to ##{kind}"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def _serializers
|
24
|
-
@_serializers ||= Hash.new(->(message){ message })
|
25
|
-
end
|
26
|
-
end
|