tennis-jobs 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9ee6ec8dbc807f4cb3ade4eac1651624555239b1
4
- data.tar.gz: 73978213184591abc3a807957a31b76e81a23817
3
+ metadata.gz: 41fd5c9ff7ba286a975e7f6fd69b422564884783
4
+ data.tar.gz: 02f1abfb9d8045033ab9bc8203b0d05473d4736e
5
5
  SHA512:
6
- metadata.gz: 550aad703fa200b1f002ae8cfc84a9d22c55c39b0867885e4ee8a74d776d9241b65f5389fbe2133f31b601a3d49e53b0274d0391c2720d291d58e421931b7818
7
- data.tar.gz: aa3f869f0a540088090b4a574d88288bd554931c84a9d0c15e8cf0088e46db21474da52d800c1a8ce7552f16063072efd4681348c59da47be85f63b1dcba01d6
6
+ metadata.gz: 37dda9596db258dea9c2eb3787bf1b674cca4faa3b4467cca957bd646f7d6ab6e8e76ef3382d8ac9b29f3afa0d73524224094b9b32cd493106061f4e021672cc
7
+ data.tar.gz: 67dddffbe9393ca3051eea299dcb95974f3a147ba31403070663fe534fce849a68752d33adf28be4a73ffe8dc2ab59478e5a2b42aec383089dea056317b0dc21
@@ -1,9 +1,10 @@
1
1
  This small library is intended to help creating asynchronous jobs
2
2
  using Ruby and RabbitMQ via the Sneakers gem.
3
3
 
4
- <a href="https://travis-ci.org/nicoolas25/tennis"><img src="https://travis-ci.org/nicoolas25/tennis.svg?branch=master" /></a>
5
- <a href="https://codeclimate.com/github/nicoolas25/tennis"><img src="https://codeclimate.com/github/nicoolas25/tennis/badges/gpa.svg" /></a>
6
- <a href="https://codeclimate.com/github/nicoolas25/tennis/coverage"><img src="https://codeclimate.com/github/nicoolas25/tennis/badges/coverage.svg" /></a>
4
+ <a target="_blank" href="https://travis-ci.org/nicoolas25/tennis"><img src="https://travis-ci.org/nicoolas25/tennis.svg?branch=master" /></a>
5
+ <a target="_blank" href="https://codeclimate.com/github/nicoolas25/tennis"><img src="https://codeclimate.com/github/nicoolas25/tennis/badges/gpa.svg" /></a>
6
+ <a target="_blank" href="https://codeclimate.com/github/nicoolas25/tennis/coverage"><img src="https://codeclimate.com/github/nicoolas25/tennis/badges/coverage.svg" /></a>
7
+ <a target="_blank" href="https://rubygems.org/gems/tennis-jobs"><img src="https://badge.fury.io/rb/tennis-jobs.svg" /></a>
7
8
 
8
9
  ## Features
9
10
 
@@ -15,12 +16,70 @@ using Ruby and RabbitMQ via the Sneakers gem.
15
16
 
16
17
  - A `GenericSerializer` handling classes and ActiveRecord objects
17
18
 
19
+ ## Configuration
20
+
21
+ The background job require a group of processes to handle the tasks you want to
22
+ do asynchronously. Tennis uses YAML configuration file in order to launch thoses
23
+ processes.
24
+
25
+ ``` yaml
26
+ # tennis.conf.yml
27
+ group1:
28
+ exchange: "default"
29
+ workers: 1
30
+ classes:
31
+ - "Scope::MyClass"
32
+ - "Scope::Model"
33
+ group2:
34
+ exchange: "important"
35
+ workers: 10
36
+ classes:
37
+ - "Only::ImportantWorker"
38
+ ```
39
+
40
+ Here we see two groups of worker. Each group can be launch with the `tennis`
41
+ command:
42
+
43
+ $ bundle exec tennis group1
44
+
45
+ The `workers` options is directly given to sneakers, it will determine the
46
+ number of subprocesses that will handle the messages, the level of parallelism.
47
+
48
+ The classes are the classes that will receive your `execute` or `defer` calls
49
+ but we'll see that later...
50
+
51
+ Also it is possible to add options directly in your workers:
52
+
53
+ ``` ruby
54
+ module WorkerHelpers
55
+ BeforeFork = -> { ActiveRecord::Base.connection_pool.disconnect! rescue nil }
56
+ AfterFork = -> { ActiveRecord::Base.establish_connection }
57
+ end
58
+
59
+ class MyClass
60
+ include GenericWorker
61
+
62
+ set_option :before_fork, WorkerHelpers::BeforeFork
63
+ set_option :after_fork, WorkerHelpers::AfterFork
64
+ set_option :handler, Sneakers::Handlers::MaxretryWithoutErrors
65
+
66
+ work do |message|
67
+ MyActiveRecordModel.create(message: message)
68
+ end
69
+ end
70
+ ```
71
+
72
+ In this example I use constants to store the Proc options. This is because
73
+ having different options for the workers of a same group isn't possible. By
74
+ using this constant, I can have another worker with those same options and put
75
+ it in the same group.
76
+
18
77
  ## Examples
19
78
 
20
79
  Those examples are what we wish to achieve.
21
80
 
22
81
  The name of the queue is the name of the class by default and can be reset
23
- using sneakers' `.from_queue` method of the `YourClass::Worker`'s class.
82
+ using sneakers' `YourClass.worker.from_queue` method.
24
83
 
25
84
  ### Hooks
26
85
 
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "tennis"
4
+ require "tennis/cli"
5
+
6
+ Tennis::CLI.start
@@ -0,0 +1,102 @@
1
+ require "yaml"
2
+ require "optparse"
3
+ require "sneakers"
4
+ require "sneakers/runner"
5
+
6
+ module Tennis
7
+ class CLI
8
+
9
+ DEFAULT_OPTIONS = {
10
+ config: "./tennis.yml",
11
+ }.freeze
12
+
13
+ def self.start
14
+ options = DEFAULT_OPTIONS.dup
15
+ OptionParser.new do |opts|
16
+ opts.banner = "Usage: tennis [options] group"
17
+ opts.on("-c", "--config FILE", "Set the config file") do |file|
18
+ options[:config] = file
19
+ end
20
+ opts.on("-r", "--require PATH", "Require files before starting") do |path|
21
+ options[:require] ||= []
22
+ options[:require] << path
23
+ end
24
+ opts.on("-x", "--execute CODE", "Execute code before starting") do |code|
25
+ options[:execute] ||= []
26
+ options[:execute] << code
27
+ end
28
+ end.parse!
29
+ options[:group] = ARGV.first
30
+ new(options).start
31
+ end
32
+
33
+ def initialize(options)
34
+ @options = options
35
+ end
36
+
37
+ def start
38
+ do_require
39
+ execute_code
40
+ configure_tennis
41
+ start_group
42
+ end
43
+
44
+ private
45
+
46
+ def do_require
47
+ return unless requires = @options[:require]
48
+ requires.each { |path| require path } if @options[:require]
49
+ end
50
+
51
+ def execute_code
52
+ return unless codes = @options[:execute]
53
+ codes.each { |code| eval code }
54
+ end
55
+
56
+ def configure_tennis
57
+ Tennis.configure do |config|
58
+ config.async = true
59
+ config.exchange = group["exchange"]
60
+ config.workers = group["workers"].to_i
61
+ config.logger = Logger.new(STDOUT)
62
+ config.logger.level = Logger::WARN
63
+ config.sneakers_options = sneakers_options
64
+ end
65
+ end
66
+
67
+ def sneakers_options
68
+ classes.map(&:options).each_with_object({}) do |options, all_options|
69
+ merge_options(all_options, options)
70
+ end
71
+ end
72
+
73
+ def merge_options(target, options)
74
+ options.each do |name, value|
75
+ if target[name].nil?
76
+ target[name] = value
77
+ elsif target[name] != value
78
+ fail "Workers shouldn't have different '#{name}' options"
79
+ end
80
+ end
81
+ end
82
+
83
+ def start_group
84
+ Sneakers::Runner.new(classes.map(&:worker)).run
85
+ end
86
+
87
+ def classes
88
+ @classes ||= group["classes"].map do |name|
89
+ Object.const_get(name)
90
+ end
91
+ end
92
+
93
+ def group
94
+ @group ||= config[@options[:group]]
95
+ end
96
+
97
+ def config
98
+ YAML.load_file(@options[:config])
99
+ end
100
+
101
+ end
102
+ end
@@ -4,10 +4,12 @@ module Tennis
4
4
 
5
5
  autoload :BeforeHook, "tennis/worker/generic/before_hook"
6
6
  autoload :Serialize, "tennis/worker/generic/serialize"
7
+ autoload :Options, "tennis/worker/generic/options"
7
8
 
8
9
  def self.included(base)
9
10
  base.extend BeforeHook
10
11
  base.extend Serialize
12
+ base.extend Options
11
13
  base.extend DSL
12
14
  base.worker = Class.new do
13
15
  @@parent = base
@@ -0,0 +1,10 @@
1
+ module Tennis::Worker::Generic::Options
2
+ def set_option(symbol, value)
3
+ options[symbol] = value
4
+ end
5
+
6
+ def options
7
+ @_options ||= {}
8
+ end
9
+ end
10
+
@@ -4,7 +4,7 @@ $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.1.0"
7
+ spec.version = "0.2.0"
8
8
  spec.authors = ["Nicolas ZERMATI"]
9
9
  spec.email = ["nicoolas25@gmail.com"]
10
10
 
@@ -14,8 +14,8 @@ Gem::Specification.new do |spec|
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
- spec.bindir = "exe"
18
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
17
+ spec.bindir = "bin"
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_runtime_dependency "sneakers"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tennis-jobs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nicolas ZERMATI
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-02 00:00:00.000000000 Z
11
+ date: 2015-09-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sneakers
@@ -125,7 +125,8 @@ dependencies:
125
125
  description: A small background job library on top of sneakers.
126
126
  email:
127
127
  - nicoolas25@gmail.com
128
- executables: []
128
+ executables:
129
+ - tennis
129
130
  extensions: []
130
131
  extra_rdoc_files: []
131
132
  files:
@@ -137,16 +138,19 @@ files:
137
138
  - LICENSE.txt
138
139
  - README.markdown
139
140
  - Rakefile
141
+ - bin/tennis
140
142
  - examples/deferable.rb
141
143
  - examples/example.rb
142
144
  - examples/serializer.rb
143
145
  - lib/tennis.rb
146
+ - lib/tennis/cli.rb
144
147
  - lib/tennis/configuration.rb
145
148
  - lib/tennis/serializer/generic.rb
146
149
  - lib/tennis/worker/deferable.rb
147
150
  - lib/tennis/worker/deferable/action.rb
148
151
  - lib/tennis/worker/generic.rb
149
152
  - lib/tennis/worker/generic/before_hook.rb
153
+ - lib/tennis/worker/generic/options.rb
150
154
  - lib/tennis/worker/generic/serialize.rb
151
155
  - tennis-jobs.gemspec
152
156
  homepage: https://github.com/nicoolas25/tennis