beez 0.1.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 +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +3 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +173 -0
- data/LICENSE.txt +21 -0
- data/README.md +139 -0
- data/Rakefile +6 -0
- data/beez.gemspec +36 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bpmn/order-process.bpmn +139 -0
- data/examples/workers.rb +49 -0
- data/exe/beez +14 -0
- data/lib/beez.rb +26 -0
- data/lib/beez/cli.rb +143 -0
- data/lib/beez/client.rb +97 -0
- data/lib/beez/configurable.rb +13 -0
- data/lib/beez/configuration.rb +14 -0
- data/lib/beez/launcher.rb +35 -0
- data/lib/beez/loggable.rb +15 -0
- data/lib/beez/processor.rb +103 -0
- data/lib/beez/rails.rb +29 -0
- data/lib/beez/supervisor.rb +38 -0
- data/lib/beez/version.rb +3 -0
- data/lib/beez/worker.rb +163 -0
- metadata +146 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
module Beez
|
2
|
+
class Configuration
|
3
|
+
|
4
|
+
attr_accessor :env, :logger, :require, :timeout, :zeebe_url
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@env = ENV["APP_ENV"] || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
|
8
|
+
@logger = Logger.new($stdout)
|
9
|
+
@require = "."
|
10
|
+
@timeout = 30
|
11
|
+
@zeebe_url = ENV['ZEEBE_URL'] || 'localhost:26500'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'beez/supervisor'
|
2
|
+
|
3
|
+
module Beez
|
4
|
+
class Launcher
|
5
|
+
|
6
|
+
attr_reader :supervisor
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@supervisor = ::Beez::Supervisor.new
|
10
|
+
end
|
11
|
+
|
12
|
+
# Starts the supervisor and job processors.
|
13
|
+
def start
|
14
|
+
supervisor.start
|
15
|
+
end
|
16
|
+
|
17
|
+
# Tells the supervisor to stop processing any more jobs.
|
18
|
+
def quiet
|
19
|
+
supervisor.quiet
|
20
|
+
end
|
21
|
+
|
22
|
+
# Tells the supervisor to stop job processors. This method blocks until
|
23
|
+
# all processors are complete and stopped. It can take up to configurable
|
24
|
+
# timeout.
|
25
|
+
def stop
|
26
|
+
supervisor.stop
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def client
|
32
|
+
::Beez.client
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Beez
|
2
|
+
class Processor
|
3
|
+
|
4
|
+
attr_reader :client, :worker_class, :busy_count, :timer
|
5
|
+
|
6
|
+
def initialize(client: ::Beez.client, worker_class:)
|
7
|
+
@client = client
|
8
|
+
@worker_class = worker_class
|
9
|
+
@busy_count = ::Concurrent::AtomicFixnum.new(0)
|
10
|
+
@timer = ::Concurrent::TimerTask.new(
|
11
|
+
run_now: true,
|
12
|
+
execution_interval: worker_poll_interval,
|
13
|
+
timeout_interval: worker_timeout
|
14
|
+
) { run }
|
15
|
+
end
|
16
|
+
|
17
|
+
def start
|
18
|
+
timer.execute
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def stop
|
23
|
+
timer.shutdown
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def should_activate_jobs?
|
28
|
+
busy_count.value <= worker_max_jobs_to_activate
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def run
|
34
|
+
fetch if should_activate_jobs?
|
35
|
+
end
|
36
|
+
|
37
|
+
def fetch
|
38
|
+
activate_jobs_request.each do |response|
|
39
|
+
busy_count.increment(response.jobs.count)
|
40
|
+
response.jobs.each do |job|
|
41
|
+
::Concurrent::Future.execute do
|
42
|
+
process(job)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def process(job)
|
49
|
+
worker = worker_class.new(client)
|
50
|
+
begin
|
51
|
+
worker.process(job)
|
52
|
+
worker.complete_job(job)
|
53
|
+
rescue => exception
|
54
|
+
worker.fail_job(job, reason: exception.message)
|
55
|
+
raise exception
|
56
|
+
ensure
|
57
|
+
busy_count.decrement
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def activate_jobs_request
|
62
|
+
client.activate_jobs(
|
63
|
+
type: worker_type,
|
64
|
+
worker: worker_name,
|
65
|
+
timeout: worker_timeout * 1000,
|
66
|
+
maxJobsToActivate: max_jobs_to_activate,
|
67
|
+
fetchVariable: worker_variables_to_fetch,
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
def worker_type
|
72
|
+
worker_class.get_type
|
73
|
+
end
|
74
|
+
|
75
|
+
def worker_name
|
76
|
+
worker_class.get_name
|
77
|
+
end
|
78
|
+
|
79
|
+
def worker_max_jobs_to_activate
|
80
|
+
worker_class.get_max_jobs_to_activate
|
81
|
+
end
|
82
|
+
|
83
|
+
def worker_timeout
|
84
|
+
worker_class.get_timeout
|
85
|
+
end
|
86
|
+
|
87
|
+
def worker_variables_to_fetch
|
88
|
+
worker_class.get_variables_to_fetch
|
89
|
+
end
|
90
|
+
|
91
|
+
def worker_poll_interval
|
92
|
+
worker_class.get_poll_interval
|
93
|
+
end
|
94
|
+
|
95
|
+
def max_jobs_to_activate
|
96
|
+
worker_max_jobs_to_activate - busy_count.value
|
97
|
+
end
|
98
|
+
|
99
|
+
def logger
|
100
|
+
::Beez.logger
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/beez/rails.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
module Beez
|
2
|
+
class Rails < ::Rails::Engine
|
3
|
+
class Reloader
|
4
|
+
def initialize(app = ::Rails.application)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call
|
9
|
+
@app.reloader.wrap do
|
10
|
+
yield
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def inspect
|
15
|
+
"#<Beez::Rails::Reloader @app=#{@app.class.name}>"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# This hook happens after all initializers are run, just before returning
|
20
|
+
# from config/environment.rb back to beez/cli.rb.
|
21
|
+
#
|
22
|
+
# None of this matters on the client-side, only within the Beez process itself.
|
23
|
+
config.after_initialize do
|
24
|
+
Beez.configure_server do |_|
|
25
|
+
Beez.options[:reloader] = Beez::Rails::Reloader.new
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'beez/processor'
|
2
|
+
|
3
|
+
module Beez
|
4
|
+
class Supervisor
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@processors = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def start
|
11
|
+
@processors = workers.map do |worker_class|
|
12
|
+
processor = ::Beez::Processor.new(worker_class: worker_class)
|
13
|
+
processor.start
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def quiet
|
18
|
+
logger.info "Terminating workers"
|
19
|
+
@processors.each(&:stop)
|
20
|
+
end
|
21
|
+
|
22
|
+
def stop(timeout: ::Beez.config.timeout)
|
23
|
+
quiet
|
24
|
+
logger.info "Pausing #{timeout}s to allow workers to finish..."
|
25
|
+
sleep timeout
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def workers
|
31
|
+
::Beez.workers.to_a
|
32
|
+
end
|
33
|
+
|
34
|
+
def logger
|
35
|
+
::Beez.logger
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/beez/version.rb
ADDED
data/lib/beez/worker.rb
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Beez
|
4
|
+
module Worker
|
5
|
+
attr_accessor :client, :type, :max_jobs_to_activate, :poll_interval, :timeout, :variables
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
Beez.register_worker(base)
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(client)
|
13
|
+
@client = client
|
14
|
+
end
|
15
|
+
|
16
|
+
def complete_job(job, variables: {})
|
17
|
+
logger.info "Completed processing job #{job.type} #{job.key}"
|
18
|
+
client.complete_job(
|
19
|
+
jobKey: job.key,
|
20
|
+
variables: Hash(variables).to_json,
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
def fail_job(job, reason: "")
|
25
|
+
logger.error "Failed processing job #{job.type} #{job.key}: #{reason}"
|
26
|
+
client.fail_job(
|
27
|
+
jobKey: job.key,
|
28
|
+
retries: job.retries - 1,
|
29
|
+
errorMessage: reason,
|
30
|
+
)
|
31
|
+
rescue => e
|
32
|
+
logger.error e.message
|
33
|
+
end
|
34
|
+
|
35
|
+
def logger
|
36
|
+
::Beez.logger
|
37
|
+
end
|
38
|
+
|
39
|
+
module ClassMethods
|
40
|
+
# Sets the type of service task the worker should subscribe to.
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# class MyWorker
|
44
|
+
# include ::Beez::Worker
|
45
|
+
# type "some-service-task-type"
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# @param [String] type
|
49
|
+
# @return [String]
|
50
|
+
def type(type)
|
51
|
+
@type = type
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns the type of service task the worker should subscribe to.
|
55
|
+
#
|
56
|
+
# @return [String]
|
57
|
+
def get_type
|
58
|
+
@type
|
59
|
+
end
|
60
|
+
|
61
|
+
# Sets the maximum number of jobs to send to the worker for processing at once.
|
62
|
+
# As jobs get completed by the worker, more jobs will be sent to the worker
|
63
|
+
# but always within this limit.
|
64
|
+
#
|
65
|
+
# @example
|
66
|
+
# class MyWorker
|
67
|
+
# include ::Beez::Worker
|
68
|
+
# max_jobs_to_activate 5
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# @param [Integer] max_jobs_to_activate
|
72
|
+
# @return [Integer]
|
73
|
+
def max_jobs_to_activate(max_jobs_to_activate)
|
74
|
+
@max_jobs_to_activate = max_jobs_to_activate
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns the maximum number of jobs to send to the worker for processing at once.
|
78
|
+
# As jobs get completed by the worker, more jobs will be sent to the worker
|
79
|
+
# but always within this limit.
|
80
|
+
#
|
81
|
+
# @return [Integer]
|
82
|
+
def get_max_jobs_to_activate
|
83
|
+
@max_jobs_to_activate || 1
|
84
|
+
end
|
85
|
+
|
86
|
+
# Sets the interval duration in seconds between polls to the broker.
|
87
|
+
#
|
88
|
+
# @example
|
89
|
+
# class MyWorker
|
90
|
+
# include ::Beez::Worker
|
91
|
+
# poll_interval 5
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
# @param [Integer] poll_interval
|
95
|
+
# @return [Integer]
|
96
|
+
def poll_interval(poll_interval)
|
97
|
+
@poll_interval = poll_interval
|
98
|
+
end
|
99
|
+
|
100
|
+
# Returns the interval duration in seconds between polls to the broker.
|
101
|
+
#
|
102
|
+
# @return [Integer]
|
103
|
+
def get_poll_interval
|
104
|
+
@poll_interval || 5
|
105
|
+
end
|
106
|
+
|
107
|
+
# Sets the time in seconds the worker has to process the job before
|
108
|
+
# the broker consider it as expired and can schedule it to another worker.
|
109
|
+
#
|
110
|
+
# @example
|
111
|
+
# class MyWorker
|
112
|
+
# include ::Beez::Worker
|
113
|
+
# timeout 30
|
114
|
+
# end
|
115
|
+
#
|
116
|
+
# @param [Integer] timeout
|
117
|
+
# @return [Integer]
|
118
|
+
def timeout(timeout)
|
119
|
+
@timeout = timeout
|
120
|
+
end
|
121
|
+
|
122
|
+
# Returns the time in seconds the worker has to process the job before
|
123
|
+
# the broker consider it as expired and can schedule it to another worker.
|
124
|
+
#
|
125
|
+
# @return [Integer]
|
126
|
+
def get_timeout
|
127
|
+
@timeout || 30
|
128
|
+
end
|
129
|
+
|
130
|
+
# Sets the worker's variables to fetch from the broker when polling for new
|
131
|
+
# jobs.
|
132
|
+
#
|
133
|
+
# @example
|
134
|
+
# class MyWorker
|
135
|
+
# include ::Beez::Worker
|
136
|
+
# variables [:foo, :bar]
|
137
|
+
# end
|
138
|
+
#
|
139
|
+
# @param [Array<String, Symbol>] variables
|
140
|
+
# @return [Array<String, Symbol>]
|
141
|
+
def variables(variables)
|
142
|
+
@variables = variables
|
143
|
+
end
|
144
|
+
|
145
|
+
# Returns the worker's variables to fetch from the broker when polling for new
|
146
|
+
# jobs.
|
147
|
+
#
|
148
|
+
# @return [Array<String, Symbol>]
|
149
|
+
def get_variables_to_fetch
|
150
|
+
@variables.to_a
|
151
|
+
end
|
152
|
+
|
153
|
+
# Returns the worker's name.
|
154
|
+
#
|
155
|
+
# @return [String]
|
156
|
+
def get_name
|
157
|
+
name = self.name.gsub(/::/, ':')
|
158
|
+
name.gsub!(/([^A-Z:])([A-Z])/) { "#{$1}_#{$2}" }
|
159
|
+
name.downcase
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
metadata
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: beez
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pierre-Louis Gottfrois
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-07-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: zeebe-client
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.7'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: concurrent-ruby
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
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: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
83
|
+
description: Simple, efficient ruby workers for Zeebe business processes.
|
84
|
+
email:
|
85
|
+
- pierrelouis.gottfrois@gmail.com
|
86
|
+
executables:
|
87
|
+
- beez
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- ".gitignore"
|
92
|
+
- ".rspec"
|
93
|
+
- ".ruby-version"
|
94
|
+
- CHANGELOG.md
|
95
|
+
- CODE_OF_CONDUCT.md
|
96
|
+
- Gemfile
|
97
|
+
- Gemfile.lock
|
98
|
+
- LICENSE.txt
|
99
|
+
- README.md
|
100
|
+
- Rakefile
|
101
|
+
- beez.gemspec
|
102
|
+
- bin/console
|
103
|
+
- bin/setup
|
104
|
+
- bpmn/order-process.bpmn
|
105
|
+
- examples/workers.rb
|
106
|
+
- exe/beez
|
107
|
+
- lib/beez.rb
|
108
|
+
- lib/beez/cli.rb
|
109
|
+
- lib/beez/client.rb
|
110
|
+
- lib/beez/configurable.rb
|
111
|
+
- lib/beez/configuration.rb
|
112
|
+
- lib/beez/launcher.rb
|
113
|
+
- lib/beez/loggable.rb
|
114
|
+
- lib/beez/processor.rb
|
115
|
+
- lib/beez/rails.rb
|
116
|
+
- lib/beez/supervisor.rb
|
117
|
+
- lib/beez/version.rb
|
118
|
+
- lib/beez/worker.rb
|
119
|
+
homepage: https://github.com/gottfrois/beez
|
120
|
+
licenses:
|
121
|
+
- MIT
|
122
|
+
metadata:
|
123
|
+
allowed_push_host: https://rubygems.org
|
124
|
+
homepage_uri: https://github.com/gottfrois/beez
|
125
|
+
source_code_uri: https://github.com/gottfrois/beez
|
126
|
+
changelog_uri: https://github.com/gottfrois/beez/CHANGELOG.md
|
127
|
+
post_install_message:
|
128
|
+
rdoc_options: []
|
129
|
+
require_paths:
|
130
|
+
- lib
|
131
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - ">="
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: 2.3.0
|
136
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
requirements: []
|
142
|
+
rubygems_version: 3.0.8
|
143
|
+
signing_key:
|
144
|
+
specification_version: 4
|
145
|
+
summary: Simple, efficient ruby workers for Zeebe business processes.
|
146
|
+
test_files: []
|