beez 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,13 @@
1
+ require 'beez/configuration'
2
+
3
+ module Beez
4
+ module Configurable
5
+ def config
6
+ @config ||= ::Beez::Configuration.new
7
+ end
8
+
9
+ def configure
10
+ yield config if block_given?
11
+ end
12
+ end
13
+ end
@@ -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,15 @@
1
+ module Beez
2
+ module Loggable
3
+ def logger
4
+ @logger || setup_logger
5
+ end
6
+
7
+ def logger=(logger)
8
+ @logger = logger
9
+ end
10
+
11
+ def setup_logger
12
+ @logger = Beez.config.logger
13
+ end
14
+ end
15
+ 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
@@ -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
@@ -0,0 +1,3 @@
1
+ module Beez
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -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: []