wamp-worker 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 +13 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +204 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bin/wamp-worker +46 -0
- data/lib/wamp/worker.rb +132 -0
- data/lib/wamp/worker/config.rb +184 -0
- data/lib/wamp/worker/handler.rb +196 -0
- data/lib/wamp/worker/proxy/backgrounder.rb +38 -0
- data/lib/wamp/worker/proxy/base.rb +101 -0
- data/lib/wamp/worker/proxy/dispatcher.rb +115 -0
- data/lib/wamp/worker/proxy/requestor.rb +91 -0
- data/lib/wamp/worker/queue.rb +135 -0
- data/lib/wamp/worker/rails.rb +28 -0
- data/lib/wamp/worker/runner.rb +240 -0
- data/lib/wamp/worker/ticker.rb +30 -0
- data/lib/wamp/worker/version.rb +5 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/support/client_stub.rb +47 -0
- data/spec/support/handler_stub.rb +105 -0
- data/spec/support/redis_stub.rb +89 -0
- data/spec/support/session_stub.rb +101 -0
- data/spec/wamp/worker/config_spec.rb +90 -0
- data/spec/wamp/worker/handler_spec.rb +162 -0
- data/spec/wamp/worker/proxy_spec.rb +153 -0
- data/spec/wamp/worker/queue_spec.rb +49 -0
- data/spec/wamp/worker/runner_spec.rb +108 -0
- data/spec/wamp/worker_spec.rb +8 -0
- data/test/app_test.rb +124 -0
- data/test/hello.py +50 -0
- data/test/sidekiq.yml +5 -0
- data/test/wamp_test/.generators +8 -0
- data/test/wamp_test/.ruby-version +1 -0
- data/test/wamp_test/Gemfile +65 -0
- data/test/wamp_test/Gemfile.lock +246 -0
- data/test/wamp_test/README.md +24 -0
- data/test/wamp_test/Rakefile +6 -0
- data/test/wamp_test/app/assets/config/manifest.js +3 -0
- data/test/wamp_test/app/assets/images/.keep +0 -0
- data/test/wamp_test/app/assets/javascripts/application.js +16 -0
- data/test/wamp_test/app/assets/javascripts/cable.js +13 -0
- data/test/wamp_test/app/assets/javascripts/channels/.keep +0 -0
- data/test/wamp_test/app/assets/stylesheets/application.css +15 -0
- data/test/wamp_test/app/channels/application_cable/channel.rb +4 -0
- data/test/wamp_test/app/channels/application_cable/connection.rb +4 -0
- data/test/wamp_test/app/controllers/add_controller.rb +11 -0
- data/test/wamp_test/app/controllers/application_controller.rb +3 -0
- data/test/wamp_test/app/controllers/concerns/.keep +0 -0
- data/test/wamp_test/app/controllers/ping_controller.rb +7 -0
- data/test/wamp_test/app/handlers/add_handler.rb +9 -0
- data/test/wamp_test/app/handlers/back_add_handler.rb +26 -0
- data/test/wamp_test/app/handlers/back_ping_handler.rb +10 -0
- data/test/wamp_test/app/handlers/ping_handler.rb +10 -0
- data/test/wamp_test/app/helpers/application_helper.rb +2 -0
- data/test/wamp_test/app/jobs/application_job.rb +2 -0
- data/test/wamp_test/app/mailers/application_mailer.rb +4 -0
- data/test/wamp_test/app/models/application_record.rb +3 -0
- data/test/wamp_test/app/models/concerns/.keep +0 -0
- data/test/wamp_test/app/views/layouts/application.html.erb +15 -0
- data/test/wamp_test/app/views/layouts/mailer.html.erb +13 -0
- data/test/wamp_test/app/views/layouts/mailer.text.erb +1 -0
- data/test/wamp_test/bin/bundle +3 -0
- data/test/wamp_test/bin/rails +9 -0
- data/test/wamp_test/bin/rake +9 -0
- data/test/wamp_test/bin/setup +36 -0
- data/test/wamp_test/bin/spring +17 -0
- data/test/wamp_test/bin/update +31 -0
- data/test/wamp_test/bin/yarn +11 -0
- data/test/wamp_test/config.ru +5 -0
- data/test/wamp_test/config/application.rb +19 -0
- data/test/wamp_test/config/boot.rb +4 -0
- data/test/wamp_test/config/cable.yml +10 -0
- data/test/wamp_test/config/credentials.yml.enc +1 -0
- data/test/wamp_test/config/database.yml +25 -0
- data/test/wamp_test/config/environment.rb +5 -0
- data/test/wamp_test/config/environments/development.rb +61 -0
- data/test/wamp_test/config/environments/production.rb +94 -0
- data/test/wamp_test/config/environments/test.rb +46 -0
- data/test/wamp_test/config/initializers/application_controller_renderer.rb +8 -0
- data/test/wamp_test/config/initializers/assets.rb +14 -0
- data/test/wamp_test/config/initializers/backtrace_silencers.rb +7 -0
- data/test/wamp_test/config/initializers/content_security_policy.rb +25 -0
- data/test/wamp_test/config/initializers/cookies_serializer.rb +5 -0
- data/test/wamp_test/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/wamp_test/config/initializers/inflections.rb +16 -0
- data/test/wamp_test/config/initializers/mime_types.rb +4 -0
- data/test/wamp_test/config/initializers/wamp-worker.rb +8 -0
- data/test/wamp_test/config/initializers/wrap_parameters.rb +14 -0
- data/test/wamp_test/config/locales/en.yml +33 -0
- data/test/wamp_test/config/master.key +1 -0
- data/test/wamp_test/config/puma.rb +34 -0
- data/test/wamp_test/config/routes.rb +4 -0
- data/test/wamp_test/config/sidekiq.yml +6 -0
- data/test/wamp_test/config/spring.rb +6 -0
- data/test/wamp_test/config/storage.yml +34 -0
- data/test/wamp_test/db/development.sqlite3 +0 -0
- data/test/wamp_test/db/seeds.rb +7 -0
- data/test/wamp_test/lib/assets/.keep +0 -0
- data/test/wamp_test/lib/tasks/.keep +0 -0
- data/test/wamp_test/package.json +5 -0
- data/test/wamp_test/public/404.html +67 -0
- data/test/wamp_test/public/422.html +67 -0
- data/test/wamp_test/public/500.html +66 -0
- data/test/wamp_test/public/apple-touch-icon-precomposed.png +0 -0
- data/test/wamp_test/public/apple-touch-icon.png +0 -0
- data/test/wamp_test/public/favicon.ico +0 -0
- data/test/wamp_test/public/robots.txt +1 -0
- data/test/wamp_test/storage/.keep +0 -0
- data/test/wamp_test/test/application_system_test_case.rb +5 -0
- data/test/wamp_test/test/controllers/.keep +0 -0
- data/test/wamp_test/test/fixtures/.keep +0 -0
- data/test/wamp_test/test/fixtures/files/.keep +0 -0
- data/test/wamp_test/test/helpers/.keep +0 -0
- data/test/wamp_test/test/integration/.keep +0 -0
- data/test/wamp_test/test/mailers/.keep +0 -0
- data/test/wamp_test/test/models/.keep +0 -0
- data/test/wamp_test/test/system/.keep +0 -0
- data/test/wamp_test/test/test_helper.rb +10 -0
- data/test/wamp_test/vendor/.keep +0 -0
- data/test/web/index.html +101 -0
- data/wamp-worker.gemspec +32 -0
- metadata +395 -0
@@ -0,0 +1,184 @@
|
|
1
|
+
require "redis"
|
2
|
+
|
3
|
+
module Wamp
|
4
|
+
module Worker
|
5
|
+
DEFAULT = :default
|
6
|
+
|
7
|
+
#region Storage Objects
|
8
|
+
class Handle
|
9
|
+
attr_reader :klass, :method, :options
|
10
|
+
|
11
|
+
def initialize(klass, method, options)
|
12
|
+
@klass = klass
|
13
|
+
@method = method
|
14
|
+
@options = options
|
15
|
+
|
16
|
+
unless klass.ancestors.include? BaseHandler
|
17
|
+
raise(ArgumentError, "'klass' must be a Wamp::Worker::Handler type")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Registration < Handle
|
23
|
+
attr_reader :procedure
|
24
|
+
|
25
|
+
def initialize(procedure, klass, method, options)
|
26
|
+
super klass, method, options
|
27
|
+
@procedure = procedure
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Subscription < Handle
|
32
|
+
attr_reader :topic
|
33
|
+
|
34
|
+
def initialize(topic, klass, method, options)
|
35
|
+
super klass, method, options
|
36
|
+
@topic = topic
|
37
|
+
end
|
38
|
+
end
|
39
|
+
#endregion
|
40
|
+
|
41
|
+
# This class is a config proxy that lets you specify the name globally
|
42
|
+
#
|
43
|
+
class ConfigProxy
|
44
|
+
attr_reader :name, :config
|
45
|
+
|
46
|
+
def initialize(config, name=nil)
|
47
|
+
@name = name || DEFAULT
|
48
|
+
@config = config
|
49
|
+
end
|
50
|
+
|
51
|
+
# Sets the timeout value
|
52
|
+
#
|
53
|
+
def timeout(seconds)
|
54
|
+
self[:timeout] = seconds
|
55
|
+
end
|
56
|
+
|
57
|
+
# Sets the Redis connection
|
58
|
+
#
|
59
|
+
def redis(connection)
|
60
|
+
self[:redis] = connection
|
61
|
+
end
|
62
|
+
|
63
|
+
# Connection options
|
64
|
+
#
|
65
|
+
def connection(**options)
|
66
|
+
self[:connection] = options
|
67
|
+
end
|
68
|
+
|
69
|
+
# Subscribe the handler to a topic
|
70
|
+
#
|
71
|
+
# @param topic [String] - The topic to subscribe to
|
72
|
+
# @param klass [Wamp::Worker::Handler] - The class to use
|
73
|
+
# @param method [Symbol] - The name of the method to execute
|
74
|
+
# @param options [Hash] - Options for the subscription
|
75
|
+
def subscribe(topic, klass, method, **options)
|
76
|
+
subscriptions = self[:subscriptions] || []
|
77
|
+
subscriptions << Subscription.new(topic, klass, method, options)
|
78
|
+
self[:subscriptions] = subscriptions
|
79
|
+
end
|
80
|
+
|
81
|
+
# Register the handler for a procedure
|
82
|
+
#
|
83
|
+
# @param procedure [String] - The procedure to register for
|
84
|
+
# @param klass [Wamp::Worker::Handler] - The class to use
|
85
|
+
# @param method [Symbol] - The name of the method to execute
|
86
|
+
# @param options [Hash] - Options for the subscription
|
87
|
+
def register(procedure, klass, method, **options)
|
88
|
+
registrations = self[:registrations] || []
|
89
|
+
registrations << Registration.new(procedure, klass, method, options)
|
90
|
+
self[:registrations] = registrations
|
91
|
+
end
|
92
|
+
|
93
|
+
# Allows the user to configure without typing "config."
|
94
|
+
#
|
95
|
+
def configure(&callback)
|
96
|
+
self.instance_eval(&callback)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Sets the attribute using the name
|
100
|
+
#
|
101
|
+
# @param attribute [Symbol] - The attribute
|
102
|
+
# @param value - The value for the attribute
|
103
|
+
def []=(attribute, value)
|
104
|
+
self.config[self.name][attribute] = value
|
105
|
+
end
|
106
|
+
|
107
|
+
# Gets the attribute using the name
|
108
|
+
#
|
109
|
+
# @param attribute [Symbol] - The attribute
|
110
|
+
def [](attribute)
|
111
|
+
self.config[self.name][attribute]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# This class is used to store the configuration of the worker
|
116
|
+
#
|
117
|
+
class Config
|
118
|
+
attr_reader :settings
|
119
|
+
|
120
|
+
def initialize
|
121
|
+
@settings = {}
|
122
|
+
end
|
123
|
+
|
124
|
+
# Returns the connection options
|
125
|
+
#
|
126
|
+
# @param name [Symbol] - The name of the connection
|
127
|
+
def connection(name=nil)
|
128
|
+
name ||= DEFAULT
|
129
|
+
self[name][:connection] || {}
|
130
|
+
end
|
131
|
+
|
132
|
+
# Returns the timeout value
|
133
|
+
#
|
134
|
+
# @param name [Symbol] - The name of the connection
|
135
|
+
def timeout(name=nil)
|
136
|
+
name ||= DEFAULT
|
137
|
+
self[name][:timeout] || 60
|
138
|
+
end
|
139
|
+
|
140
|
+
# Returns the redis value
|
141
|
+
#
|
142
|
+
# @param name [Symbol] - The name of the connection
|
143
|
+
def redis(name=nil)
|
144
|
+
name ||= DEFAULT
|
145
|
+
redis = self[name][:redis]
|
146
|
+
|
147
|
+
# If it is not a redis object, create one using it as the options
|
148
|
+
if redis == nil
|
149
|
+
redis = ::Redis.new
|
150
|
+
elsif not redis.is_a? ::Redis
|
151
|
+
redis = ::Redis.new(redis)
|
152
|
+
end
|
153
|
+
|
154
|
+
redis
|
155
|
+
end
|
156
|
+
|
157
|
+
# Returns the subscriptions
|
158
|
+
#
|
159
|
+
# @param name [Symbol] - The name of the connection
|
160
|
+
def subscriptions(name=nil)
|
161
|
+
name ||= DEFAULT
|
162
|
+
self[name][:subscriptions] || []
|
163
|
+
end
|
164
|
+
|
165
|
+
# Returns the registrations
|
166
|
+
#
|
167
|
+
# @param name [Symbol] - The name of the connection
|
168
|
+
def registrations(name=nil)
|
169
|
+
name ||= DEFAULT
|
170
|
+
self[name][:registrations] || []
|
171
|
+
end
|
172
|
+
|
173
|
+
# Returns the settings for a particular connection
|
174
|
+
#
|
175
|
+
# @param name [Symbol] - The name of the connection
|
176
|
+
def [](name)
|
177
|
+
settings = self.settings[name] || {}
|
178
|
+
self.settings[name] = settings
|
179
|
+
settings
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
require_relative "proxy/backgrounder"
|
2
|
+
require 'wamp/client/response'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Wamp
|
6
|
+
module Worker
|
7
|
+
|
8
|
+
module BaseHandler
|
9
|
+
def self.included(base)
|
10
|
+
attr_reader :proxy, :command, :args, :kwargs, :details, :background
|
11
|
+
|
12
|
+
base.extend(ClassMethods)
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
|
17
|
+
# Instantiates the object
|
18
|
+
#
|
19
|
+
def create(proxy, command, args, kwargs, details)
|
20
|
+
handler = self.new
|
21
|
+
handler.configure(proxy, command, args, kwargs, details)
|
22
|
+
handler
|
23
|
+
end
|
24
|
+
|
25
|
+
# Subscribe the handler to a topic
|
26
|
+
#
|
27
|
+
# @param topic [String] - The topic to subscribe to
|
28
|
+
# @param method [Symbol] - The name of the method to execute
|
29
|
+
# @param options [Hash] - Options for the subscription
|
30
|
+
def subscribe(topic, method, name: nil, **options)
|
31
|
+
klass = self
|
32
|
+
Wamp::Worker::configure name do
|
33
|
+
subscribe topic, klass, method, **options
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Register the handler for a procedure
|
38
|
+
#
|
39
|
+
# @param procedure [String] - The procedure to register for
|
40
|
+
# @param method [Symbol] - The name of the method to execute
|
41
|
+
# @param options [Hash] - Options for the subscription
|
42
|
+
def register(procedure, method, name: nil, **options)
|
43
|
+
klass = self
|
44
|
+
Wamp::Worker::configure name do
|
45
|
+
register procedure, klass, method, **options
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Configures the handler
|
51
|
+
#
|
52
|
+
def configure(proxy, command, args, kwargs, details, background=false)
|
53
|
+
@proxy = proxy
|
54
|
+
@command = command
|
55
|
+
@args = args || []
|
56
|
+
@kwargs = kwargs || {}
|
57
|
+
@details = details || {}
|
58
|
+
@background = background
|
59
|
+
end
|
60
|
+
|
61
|
+
# This method will send progress of the call to the caller
|
62
|
+
#
|
63
|
+
# @param result - The value you would like to send to the caller for progress
|
64
|
+
def progress(result)
|
65
|
+
|
66
|
+
# Only allow progress if it is a procedure and the client set "receive_progress"
|
67
|
+
if command.to_sym == :procedure and self.details[:receive_progress]
|
68
|
+
|
69
|
+
# Get the request ID
|
70
|
+
request = self.details[:request]
|
71
|
+
|
72
|
+
# Send the data back to the
|
73
|
+
self.session.yield request, result, { progress: true }, self.background
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
module Handler
|
81
|
+
|
82
|
+
def self.included(base)
|
83
|
+
base.class_eval do
|
84
|
+
include BaseHandler
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns the session for the call
|
89
|
+
#
|
90
|
+
# @return [Wamp::Client::Session, Wamp::Worker::Proxy::Requestor]
|
91
|
+
def session
|
92
|
+
self.proxy.session
|
93
|
+
end
|
94
|
+
|
95
|
+
# Method that invokes the handler
|
96
|
+
#
|
97
|
+
def invoke(method)
|
98
|
+
self.send(method)
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
module BackgroundHandler
|
104
|
+
|
105
|
+
def self.included(base)
|
106
|
+
base.class_eval do
|
107
|
+
include BaseHandler
|
108
|
+
|
109
|
+
# Use Sidekiq
|
110
|
+
require 'sidekiq'
|
111
|
+
include ::Sidekiq::Worker
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Returns the session for the call
|
116
|
+
#
|
117
|
+
# @return [Wamp::Client::Session, Wamp::Worker::Proxy::Requestor]
|
118
|
+
def session
|
119
|
+
self.proxy
|
120
|
+
end
|
121
|
+
|
122
|
+
# Override the invoke method to push the process to the background
|
123
|
+
#
|
124
|
+
def invoke(method)
|
125
|
+
|
126
|
+
# Also need to remove the session since it is not serializable.
|
127
|
+
# Will add a new one in the background handler
|
128
|
+
self.details.delete(:session)
|
129
|
+
|
130
|
+
# Send the task to Sidekiq
|
131
|
+
#
|
132
|
+
# Note: We are explicitly serializing the args, kwargs, details
|
133
|
+
# so that we can deserialize and have them appear as symbols in
|
134
|
+
# the handler.
|
135
|
+
self.class.perform_async(
|
136
|
+
method,
|
137
|
+
self.proxy.name,
|
138
|
+
self.proxy.background_res_queue,
|
139
|
+
self.command,
|
140
|
+
self.args.to_json,
|
141
|
+
self.kwargs.to_json,
|
142
|
+
details.to_json)
|
143
|
+
|
144
|
+
# If it is a procedure, return a defer
|
145
|
+
if self.command.to_sym == :procedure
|
146
|
+
Wamp::Client::Response::CallDefer.new
|
147
|
+
else
|
148
|
+
nil
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
# Method that is run when the process is invoked on the worker
|
154
|
+
#
|
155
|
+
# @param method [Symbol] - The name of the method to execute
|
156
|
+
# @param command [Symbol] - The command that is being backgrounded
|
157
|
+
# @param args [Array] - The arguments for the handler
|
158
|
+
# @param kwargs [Hash] - The keyword arguments for the handler
|
159
|
+
# @param details [Hash] - Other details about the call
|
160
|
+
def perform(method, proxy_name, proxy_handle, command, args, kwargs, details)
|
161
|
+
|
162
|
+
# Create a proxy to act like the session. Use a backgrounder so we also
|
163
|
+
# get the "yield" method
|
164
|
+
proxy = Proxy::Backgrounder.new(proxy_name, proxy_handle)
|
165
|
+
|
166
|
+
# Deserialize the arguments as symbols
|
167
|
+
args = JSON.parse(args, :symbolize_names => true)
|
168
|
+
kwargs = JSON.parse(kwargs, :symbolize_names => true)
|
169
|
+
details = JSON.parse(details, :symbolize_names => true)
|
170
|
+
|
171
|
+
# Get the request ID
|
172
|
+
request = details[:request]
|
173
|
+
|
174
|
+
# Add the proxy to the details as a "session"
|
175
|
+
details[:session] = self.session
|
176
|
+
|
177
|
+
# Configure the handler
|
178
|
+
self.configure(proxy, command, args, kwargs, details, true)
|
179
|
+
|
180
|
+
# Call the user code and make sure to catch exceptions
|
181
|
+
result = Wamp::Client::Response.invoke_handler do
|
182
|
+
self.send(method)
|
183
|
+
end
|
184
|
+
|
185
|
+
# Only return the response if it is a procedure
|
186
|
+
if command.to_sym == :procedure
|
187
|
+
|
188
|
+
# Send the data back to the
|
189
|
+
self.session.yield request, result, {}, true
|
190
|
+
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative "requestor"
|
2
|
+
|
3
|
+
module Wamp
|
4
|
+
module Worker
|
5
|
+
module Proxy
|
6
|
+
|
7
|
+
class Backgrounder < Requestor
|
8
|
+
attr_reader :handle
|
9
|
+
|
10
|
+
# Constructor
|
11
|
+
#
|
12
|
+
def initialize(name, handle, uuid: nil)
|
13
|
+
super name, uuid: uuid
|
14
|
+
@handle = handle
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the response to the dispatcher
|
18
|
+
#
|
19
|
+
# @param request [Int] - The ID of the request
|
20
|
+
# @param result [CallResult,CallError] - The result or error for us to serialize
|
21
|
+
# @param options [Hash] - Options for the yield
|
22
|
+
# @param check_defer [Bool] - 'true' is this is linked to a defer call
|
23
|
+
def yield(request, result, options={}, check_defer=false)
|
24
|
+
|
25
|
+
# Create the response object
|
26
|
+
result = Wamp::Client::Response::CallResult.ensure(result, allow_error: true)
|
27
|
+
|
28
|
+
# Create the params
|
29
|
+
params = { request: request, result: result.to_hash, options: options, check_defer: check_defer }
|
30
|
+
|
31
|
+
# Push to the worker who requested the result
|
32
|
+
self.queue.push self.handle, :yield, params
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require "wamp/client/response"
|
2
|
+
require_relative "../ticker"
|
3
|
+
require_relative "../queue"
|
4
|
+
|
5
|
+
module Wamp
|
6
|
+
module Worker
|
7
|
+
module Proxy
|
8
|
+
|
9
|
+
class Base
|
10
|
+
attr_reader :queue, :ticker, :name, :uuid
|
11
|
+
|
12
|
+
# Constructor
|
13
|
+
#
|
14
|
+
# @param name [Symbol] - The name of the connection
|
15
|
+
# @param uuid [String] - The uuid for the proxy. This can be passed in as
|
16
|
+
# well to allow it to be initialized for hte entire worker
|
17
|
+
def initialize(name, uuid: nil)
|
18
|
+
@name = name
|
19
|
+
@queue = Wamp::Worker::Queue.new(name)
|
20
|
+
@ticker = Wamp::Worker::Ticker.new(name)
|
21
|
+
@uuid = uuid || ENV['DYNO'] || SecureRandom.hex(12)
|
22
|
+
end
|
23
|
+
|
24
|
+
#region Command/Response
|
25
|
+
# ----------------
|
26
|
+
# This workflow is used by a "Requestor" to make a "call"
|
27
|
+
# or "publish" request to the "Dispatcher". This would for example be in
|
28
|
+
# your rails app where a service or controller needs to make a WAMP call
|
29
|
+
#
|
30
|
+
# The flow is as follows
|
31
|
+
#
|
32
|
+
# - Requestor performs a "push" operation with the following parameters
|
33
|
+
# - queue_name - The "command queue"
|
34
|
+
# - command - The command ("call" or "publish")
|
35
|
+
# - params - The parameters for the command (args/kwargs/etc.)
|
36
|
+
# - handle - A unique "response queue" name that the Dispatcher will
|
37
|
+
# provide the resposne on
|
38
|
+
# - Requestor then blocks (with timeout) awaiting the response
|
39
|
+
# - Dispatcher performs a "pop" operation and executes the command
|
40
|
+
# - Dispatcher "pushes" the response to the "handle" queue
|
41
|
+
# - Requestor "pops" the response and deletes the temporary "handle" queue
|
42
|
+
|
43
|
+
# Returns the commands queue key for the worker
|
44
|
+
#
|
45
|
+
# @return [String] - The key for the commands list
|
46
|
+
def command_req_queue
|
47
|
+
"wamp:#{self.name}:command"
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns a new handle
|
51
|
+
#
|
52
|
+
# @return [String] - The key for the new handle
|
53
|
+
def unique_command_resp_queue
|
54
|
+
"wamp:#{self.name}:response:#{SecureRandom.hex(12)}"
|
55
|
+
end
|
56
|
+
|
57
|
+
#endregion
|
58
|
+
|
59
|
+
#region Dispatcher/Backgrounder
|
60
|
+
# ----------------
|
61
|
+
# This workflow is used by a "Dispatcher" to execute a "topic" or "procedure"
|
62
|
+
# on a background thread. This is used by a "BackgroundHandler" to push a
|
63
|
+
# handler to Sidekiq and get the response from the background job. This frees
|
64
|
+
# up the Event Machine to process other requests
|
65
|
+
#
|
66
|
+
# The flow is as follows
|
67
|
+
#
|
68
|
+
# - Dispatcher pushes the task to the background sidekiq worker providing
|
69
|
+
# the "handle" it will respond on
|
70
|
+
# - Backgrounder performs the operation
|
71
|
+
# - Backgrounder performs a "push" with response back to the Dispatcher
|
72
|
+
# - Dispatcher performs a "pop" and sends the response (if it is a call)
|
73
|
+
|
74
|
+
# Returns the response queue name for the backgrounder
|
75
|
+
#
|
76
|
+
# @return [String] - The key for the worker
|
77
|
+
def background_res_queue
|
78
|
+
"wamp:#{self.name}:background:#{self.uuid}"
|
79
|
+
end
|
80
|
+
|
81
|
+
#endregion
|
82
|
+
|
83
|
+
#region Requestor/Dispatcher Ticker
|
84
|
+
# ----------------
|
85
|
+
# This workflow is used to sense when a worker is no longer running
|
86
|
+
#
|
87
|
+
# The flow is as follows
|
88
|
+
#
|
89
|
+
# - Dispatcher periodically increments the ticker
|
90
|
+
# - Requestor does the following when performing a pop
|
91
|
+
# - stores the value of the ticker
|
92
|
+
# - blocks waiting for a "pop"
|
93
|
+
# - if the pop comes back "nil", it means we timed out
|
94
|
+
# - if the value of the ticker is that same as before, then th worker is not running
|
95
|
+
|
96
|
+
#endregion
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|