wamp-worker 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +5 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +204 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/bin/wamp-worker +46 -0
  13. data/lib/wamp/worker.rb +132 -0
  14. data/lib/wamp/worker/config.rb +184 -0
  15. data/lib/wamp/worker/handler.rb +196 -0
  16. data/lib/wamp/worker/proxy/backgrounder.rb +38 -0
  17. data/lib/wamp/worker/proxy/base.rb +101 -0
  18. data/lib/wamp/worker/proxy/dispatcher.rb +115 -0
  19. data/lib/wamp/worker/proxy/requestor.rb +91 -0
  20. data/lib/wamp/worker/queue.rb +135 -0
  21. data/lib/wamp/worker/rails.rb +28 -0
  22. data/lib/wamp/worker/runner.rb +240 -0
  23. data/lib/wamp/worker/ticker.rb +30 -0
  24. data/lib/wamp/worker/version.rb +5 -0
  25. data/spec/spec_helper.rb +29 -0
  26. data/spec/support/client_stub.rb +47 -0
  27. data/spec/support/handler_stub.rb +105 -0
  28. data/spec/support/redis_stub.rb +89 -0
  29. data/spec/support/session_stub.rb +101 -0
  30. data/spec/wamp/worker/config_spec.rb +90 -0
  31. data/spec/wamp/worker/handler_spec.rb +162 -0
  32. data/spec/wamp/worker/proxy_spec.rb +153 -0
  33. data/spec/wamp/worker/queue_spec.rb +49 -0
  34. data/spec/wamp/worker/runner_spec.rb +108 -0
  35. data/spec/wamp/worker_spec.rb +8 -0
  36. data/test/app_test.rb +124 -0
  37. data/test/hello.py +50 -0
  38. data/test/sidekiq.yml +5 -0
  39. data/test/wamp_test/.generators +8 -0
  40. data/test/wamp_test/.ruby-version +1 -0
  41. data/test/wamp_test/Gemfile +65 -0
  42. data/test/wamp_test/Gemfile.lock +246 -0
  43. data/test/wamp_test/README.md +24 -0
  44. data/test/wamp_test/Rakefile +6 -0
  45. data/test/wamp_test/app/assets/config/manifest.js +3 -0
  46. data/test/wamp_test/app/assets/images/.keep +0 -0
  47. data/test/wamp_test/app/assets/javascripts/application.js +16 -0
  48. data/test/wamp_test/app/assets/javascripts/cable.js +13 -0
  49. data/test/wamp_test/app/assets/javascripts/channels/.keep +0 -0
  50. data/test/wamp_test/app/assets/stylesheets/application.css +15 -0
  51. data/test/wamp_test/app/channels/application_cable/channel.rb +4 -0
  52. data/test/wamp_test/app/channels/application_cable/connection.rb +4 -0
  53. data/test/wamp_test/app/controllers/add_controller.rb +11 -0
  54. data/test/wamp_test/app/controllers/application_controller.rb +3 -0
  55. data/test/wamp_test/app/controllers/concerns/.keep +0 -0
  56. data/test/wamp_test/app/controllers/ping_controller.rb +7 -0
  57. data/test/wamp_test/app/handlers/add_handler.rb +9 -0
  58. data/test/wamp_test/app/handlers/back_add_handler.rb +26 -0
  59. data/test/wamp_test/app/handlers/back_ping_handler.rb +10 -0
  60. data/test/wamp_test/app/handlers/ping_handler.rb +10 -0
  61. data/test/wamp_test/app/helpers/application_helper.rb +2 -0
  62. data/test/wamp_test/app/jobs/application_job.rb +2 -0
  63. data/test/wamp_test/app/mailers/application_mailer.rb +4 -0
  64. data/test/wamp_test/app/models/application_record.rb +3 -0
  65. data/test/wamp_test/app/models/concerns/.keep +0 -0
  66. data/test/wamp_test/app/views/layouts/application.html.erb +15 -0
  67. data/test/wamp_test/app/views/layouts/mailer.html.erb +13 -0
  68. data/test/wamp_test/app/views/layouts/mailer.text.erb +1 -0
  69. data/test/wamp_test/bin/bundle +3 -0
  70. data/test/wamp_test/bin/rails +9 -0
  71. data/test/wamp_test/bin/rake +9 -0
  72. data/test/wamp_test/bin/setup +36 -0
  73. data/test/wamp_test/bin/spring +17 -0
  74. data/test/wamp_test/bin/update +31 -0
  75. data/test/wamp_test/bin/yarn +11 -0
  76. data/test/wamp_test/config.ru +5 -0
  77. data/test/wamp_test/config/application.rb +19 -0
  78. data/test/wamp_test/config/boot.rb +4 -0
  79. data/test/wamp_test/config/cable.yml +10 -0
  80. data/test/wamp_test/config/credentials.yml.enc +1 -0
  81. data/test/wamp_test/config/database.yml +25 -0
  82. data/test/wamp_test/config/environment.rb +5 -0
  83. data/test/wamp_test/config/environments/development.rb +61 -0
  84. data/test/wamp_test/config/environments/production.rb +94 -0
  85. data/test/wamp_test/config/environments/test.rb +46 -0
  86. data/test/wamp_test/config/initializers/application_controller_renderer.rb +8 -0
  87. data/test/wamp_test/config/initializers/assets.rb +14 -0
  88. data/test/wamp_test/config/initializers/backtrace_silencers.rb +7 -0
  89. data/test/wamp_test/config/initializers/content_security_policy.rb +25 -0
  90. data/test/wamp_test/config/initializers/cookies_serializer.rb +5 -0
  91. data/test/wamp_test/config/initializers/filter_parameter_logging.rb +4 -0
  92. data/test/wamp_test/config/initializers/inflections.rb +16 -0
  93. data/test/wamp_test/config/initializers/mime_types.rb +4 -0
  94. data/test/wamp_test/config/initializers/wamp-worker.rb +8 -0
  95. data/test/wamp_test/config/initializers/wrap_parameters.rb +14 -0
  96. data/test/wamp_test/config/locales/en.yml +33 -0
  97. data/test/wamp_test/config/master.key +1 -0
  98. data/test/wamp_test/config/puma.rb +34 -0
  99. data/test/wamp_test/config/routes.rb +4 -0
  100. data/test/wamp_test/config/sidekiq.yml +6 -0
  101. data/test/wamp_test/config/spring.rb +6 -0
  102. data/test/wamp_test/config/storage.yml +34 -0
  103. data/test/wamp_test/db/development.sqlite3 +0 -0
  104. data/test/wamp_test/db/seeds.rb +7 -0
  105. data/test/wamp_test/lib/assets/.keep +0 -0
  106. data/test/wamp_test/lib/tasks/.keep +0 -0
  107. data/test/wamp_test/package.json +5 -0
  108. data/test/wamp_test/public/404.html +67 -0
  109. data/test/wamp_test/public/422.html +67 -0
  110. data/test/wamp_test/public/500.html +66 -0
  111. data/test/wamp_test/public/apple-touch-icon-precomposed.png +0 -0
  112. data/test/wamp_test/public/apple-touch-icon.png +0 -0
  113. data/test/wamp_test/public/favicon.ico +0 -0
  114. data/test/wamp_test/public/robots.txt +1 -0
  115. data/test/wamp_test/storage/.keep +0 -0
  116. data/test/wamp_test/test/application_system_test_case.rb +5 -0
  117. data/test/wamp_test/test/controllers/.keep +0 -0
  118. data/test/wamp_test/test/fixtures/.keep +0 -0
  119. data/test/wamp_test/test/fixtures/files/.keep +0 -0
  120. data/test/wamp_test/test/helpers/.keep +0 -0
  121. data/test/wamp_test/test/integration/.keep +0 -0
  122. data/test/wamp_test/test/mailers/.keep +0 -0
  123. data/test/wamp_test/test/models/.keep +0 -0
  124. data/test/wamp_test/test/system/.keep +0 -0
  125. data/test/wamp_test/test/test_helper.rb +10 -0
  126. data/test/wamp_test/vendor/.keep +0 -0
  127. data/test/web/index.html +101 -0
  128. data/wamp-worker.gemspec +32 -0
  129. metadata +395 -0
@@ -0,0 +1,115 @@
1
+ require_relative "base"
2
+
3
+ module Wamp
4
+ module Worker
5
+ module Proxy
6
+
7
+ class Dispatcher < Base
8
+ attr_accessor :session
9
+
10
+ # We want to timeout every few seconds so higher level code can
11
+ # look for a shutdown
12
+ TIMEOUT = 2
13
+
14
+ # Constructor
15
+ #
16
+ def initialize(name, session=nil, uuid: nil)
17
+ super name, uuid: uuid
18
+ self.session = session
19
+ end
20
+
21
+ # Increments the ticker
22
+ #
23
+ def increment_ticker
24
+ self.ticker.increment
25
+ end
26
+
27
+ # Check the queues
28
+ #
29
+ def check_queues
30
+ check_queue [self.command_req_queue, self.background_res_queue]
31
+ end
32
+
33
+ # Executes the request
34
+ #
35
+ # @param request [Descriptor] - The request
36
+ def process(descriptor)
37
+ return unless descriptor != nil
38
+
39
+ raise(RuntimeError, "must have a session to process a descriptor") unless self.session != nil
40
+
41
+ # Create the callback
42
+ callback = -> result, error, details {
43
+ # Need to remove the session from the details response
44
+ details&.delete(:session)
45
+
46
+ # Create the params
47
+ params = { result: result, error: error, details: details }
48
+
49
+ # Push the response back
50
+ self.queue.push descriptor.handle, descriptor.command, params
51
+ }
52
+
53
+ # Call the session
54
+ if descriptor.command == :call
55
+
56
+ # invoke the call method
57
+ procedure = descriptor.params[:procedure]
58
+ args = descriptor.params[:args]
59
+ kwargs = descriptor.params[:kwargs]
60
+ options = descriptor.params[:options]
61
+
62
+ self.session.call(procedure, args, kwargs, options, &callback)
63
+
64
+ elsif descriptor.command == :publish
65
+
66
+ # invoke the publish method
67
+ topic = descriptor.params[:topic]
68
+ args = descriptor.params[:args]
69
+ kwargs = descriptor.params[:kwargs]
70
+ options = descriptor.params[:options]
71
+
72
+ self.session.publish(topic, args, kwargs, options, &callback)
73
+
74
+ elsif descriptor.command == :yield
75
+
76
+ # invoke the yield method
77
+ request = descriptor.params[:request]
78
+ options = descriptor.params[:options]
79
+ check_defer = descriptor.params[:check_defer]
80
+ result_hash = descriptor.params[:result] || {}
81
+
82
+ # Get the response from the descriptor params
83
+ result = Wamp::Client::Response.from_hash(result_hash)
84
+
85
+ self.session.yield(request, result, options, check_defer)
86
+
87
+ else
88
+
89
+ # Return error if the command is not supported
90
+ error = Wamp::Client::Response::CallError.new(
91
+ Wamp::Client::Response::DEFAULT_ERROR,
92
+ ["unsupported proxy command '#{descriptor.command}'"])
93
+ callback.call(nil, error.to_hash, {})
94
+
95
+ end
96
+
97
+ end
98
+
99
+ private
100
+
101
+ # This methods blocks waiting for a value to appear in the queue
102
+ #
103
+ # @param queue_name [String] - the name of the queue
104
+ def check_queue(queue_name)
105
+
106
+ # Wait for a value to appear in the queue. We have a timeout so
107
+ # the thread can check if the worker has been killed
108
+ self.queue.pop(queue_name, wait: true, timeout: TIMEOUT)
109
+ end
110
+
111
+ end
112
+ end
113
+ end
114
+ end
115
+
@@ -0,0 +1,91 @@
1
+ require_relative "base"
2
+
3
+ module Wamp
4
+ module Worker
5
+ module Proxy
6
+
7
+ class Requestor < Base
8
+
9
+ # Performs the session "call" method
10
+ #
11
+ # @param procedure [String] - The procedure to call
12
+ # @param args [Array] - Array of arguments
13
+ # @param kwargs [Hash] - Hash of key/word arguments
14
+ # @param options [Hash] - Options for the call
15
+ def call(procedure, args=nil, kwargs=nil, options={}, &callback)
16
+
17
+ # Create the params
18
+ params = { procedure: procedure, args: args, kwargs: kwargs, options: options }
19
+
20
+ # Execute the command
21
+ request_response :call, params, true, &callback
22
+ end
23
+
24
+ # Performs the session "publish" method
25
+ #
26
+ # @param topic [String] - The topic to publish
27
+ # @param args [Array] - Array of arguments
28
+ # @param kwargs [Hash] - Hash of key/word arguments
29
+ # @param options [Hash] - Options for the subscribe
30
+ def publish(topic, args=nil, kwargs=nil, options={}, &callback)
31
+
32
+ # Create the params
33
+ params = { topic: topic , args: args, kwargs: kwargs, options: options }
34
+
35
+ # Execute the command
36
+ request_response :publish, params, options[:acknowledge], &callback
37
+ end
38
+
39
+ private
40
+
41
+ # Method to push the request and wait for the response
42
+ #
43
+ # @param command [Symbol] - The command
44
+ # @param params [Hash] - The parameters
45
+ # @param wait [Bool] - if true, will wait for the response
46
+ def request_response(command, params, wait=true)
47
+
48
+ # Create a response handle
49
+ handle = self.unique_command_resp_queue
50
+
51
+ # Push the request
52
+ self.queue.push self.command_req_queue, command, params, handle
53
+
54
+ # If wait, check the queue and respond
55
+ if wait
56
+
57
+ # Store the start ticker
58
+ start_tick = self.ticker.get
59
+
60
+ # Wait for the response
61
+ descriptor = self.queue.pop(handle, wait: true, delete: true)
62
+
63
+ # check for nil descriptor
64
+ if descriptor == nil
65
+
66
+ # If the ticker never incremented, throw a "worker not responding" error
67
+ current_tick = self.ticker.get
68
+ if start_tick == current_tick
69
+ raise(RuntimeError, "worker '#{self.name}' is not responding")
70
+ else
71
+ raise(RuntimeError, "request to #{handle} timed out")
72
+ end
73
+
74
+ else
75
+
76
+ # If a block was given, respond
77
+ if block_given?
78
+ response = [descriptor.params[:result], descriptor.params[:error], descriptor.params[:details]]
79
+ yield(*response)
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+ end
86
+
87
+
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,135 @@
1
+ require "json"
2
+
3
+ module Wamp
4
+ module Worker
5
+
6
+ class Queue
7
+ attr_reader :redis, :default_timeout
8
+
9
+ # This class represents the payload that will be stored in Redis
10
+ class Descriptor
11
+ attr_reader :command, :handle, :params
12
+
13
+ # Constructor
14
+ #
15
+ # @param command [Symbol] - The command for the descriptor
16
+ # @param handle [String] - The handle representing the descriptor
17
+ # @param params [Hash] - The params for the command
18
+ def initialize(command, handle, params)
19
+ @command = command.to_sym
20
+ @handle = handle
21
+ @params = params || {}
22
+ end
23
+
24
+ # Create a Descriptor object from the json payload
25
+ #
26
+ # @param json_string [String] - The string from the Redis store
27
+ # @return [Descriptor] - The instantiated descriptor
28
+ def self.from_json(json_string)
29
+ return unless json_string
30
+ parsed = JSON.parse(json_string, :symbolize_names => true)
31
+ self.new(parsed[:command], parsed[:handle], parsed[:params])
32
+ end
33
+
34
+ # Creates the json payload from the object
35
+ #
36
+ # @return [String] - The string that will go into the Redis store
37
+ def to_json
38
+ { command: self.command, handle: self.handle, params: self.params }.to_json
39
+ end
40
+ end
41
+
42
+ # Constructor
43
+ #
44
+ def initialize(name)
45
+ @redis = Wamp::Worker.config.redis(name)
46
+ @default_timeout = Wamp::Worker.config.timeout(name)
47
+ end
48
+
49
+ # Pushes a command onto the queue
50
+ #
51
+ # @param queue_name [String] - The name of the queue
52
+ # @param command [Symbol] - The command
53
+ # @param params [Hash] - The params for the request
54
+ # @param handle [String] - The response handle
55
+ def push(queue_name, command, params, handle=nil)
56
+
57
+ # Create the descriptor
58
+ descriptor = Descriptor.new(command, handle, params)
59
+
60
+ # Log the info
61
+ log(:push, queue_name, descriptor)
62
+
63
+ # Queue the command
64
+ self.redis.lpush(queue_name, descriptor.to_json)
65
+ end
66
+
67
+ # Pops a command off of the queue
68
+ #
69
+ # @param queue_name [String, Array] - The name of the queue (or multiple queues if brpop)
70
+ # @param wait [Bool] - True if we want to block waiting for the response
71
+ # @param delete [Bool] - True if we want the queue deleted (only applicable if wait)
72
+ # @param timeout [Int] - Number of seconds to wait before timing out
73
+ def pop(queue_name, wait: false, delete: false, timeout: nil)
74
+
75
+ # Retrieve the response from the queue
76
+ if wait
77
+ # Use the default timeout if non is specified
78
+ timeout ||= self.default_timeout
79
+
80
+ # Make the pop call
81
+ response = self.redis.brpop(queue_name, timeout: timeout)
82
+
83
+ # Returns [queue, value]
84
+ if response != nil
85
+ queue_name = response[0]
86
+ response = response[1]
87
+ end
88
+ else
89
+ # Else just call the method
90
+ response = self.redis.rpop(queue_name)
91
+ end
92
+
93
+ # If delete was set, delete the queue
94
+ if delete
95
+ self.redis.del(queue_name)
96
+ end
97
+
98
+ # Parse the response
99
+ descriptor = response != nil ? Descriptor.from_json(response) : nil
100
+
101
+ # Log the info
102
+ log(:pop, queue_name, descriptor)
103
+
104
+ # Return the queue_name and the descriptor
105
+ descriptor
106
+ end
107
+
108
+ private
109
+
110
+ # Returns the logger
111
+ #
112
+ def logger
113
+ Wamp::Worker.logger
114
+ end
115
+
116
+ # Logs the info
117
+ #
118
+ def log(type, queue_name, descriptor)
119
+ return unless logger.level == Logger::DEBUG
120
+
121
+ if descriptor
122
+ logger.debug("#{self.class.name} #{type.upcase} : #{queue_name}")
123
+ logger.debug(" command: #{descriptor.command}")
124
+ logger.debug(" params: #{descriptor.params}")
125
+ logger.debug(" handle: #{descriptor.handle}")
126
+ else
127
+ logger.debug("#{self.class.name} #{type.upcase} : #{queue_name} : EMPTY")
128
+ end
129
+ end
130
+
131
+
132
+ end
133
+ end
134
+ end
135
+
@@ -0,0 +1,28 @@
1
+ module Wamp
2
+ module Worker
3
+ module Rails
4
+
5
+ # This method will load Rails
6
+ #
7
+ # @param environment [String] - The Rails environment
8
+ # @param require [String] - The path to the Rails working directory or a file with requires
9
+ def self.load_app(environment, require)
10
+ ENV['RACK_ENV'] = ENV['RAILS_ENV'] = environment
11
+
12
+ raise ArgumentError, "'#{require}' does not exist" unless File.exist?(require)
13
+
14
+ if File.directory?(require)
15
+ require 'rails'
16
+ if ::Rails::VERSION::MAJOR < 5
17
+ raise "only Rails version 5 and higher supported"
18
+ else
19
+ require File.expand_path("#{require}/config/environment.rb")
20
+ end
21
+ else
22
+ require(require) || raise(ArgumentError, "no require file found at '#{require}'")
23
+ end
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,240 @@
1
+ require "thread"
2
+ require "wamp/client/connection"
3
+
4
+ module Wamp
5
+ module Worker
6
+ module Runner
7
+
8
+ # This is a base class for all of the runners
9
+ class Base
10
+ attr_reader :name, :dispatcher
11
+
12
+ # Constructor
13
+ #
14
+ # @param name [Symbol] - the name of the worker
15
+ def initialize(name, uuid: nil)
16
+ # Initialize the dispatcher
17
+ @name = name || :default
18
+ @dispatcher = Proxy::Dispatcher.new(self.name, uuid: uuid)
19
+ @active = false
20
+ end
21
+
22
+ # Returns the logger
23
+ #
24
+ def logger
25
+ Wamp::Worker.logger
26
+ end
27
+
28
+ # Returns if the runner is active
29
+ #
30
+ def active?
31
+ @active
32
+ end
33
+
34
+ # Starts the runner
35
+ #
36
+ def start
37
+ return if self.active?
38
+ @active = true
39
+ self._start
40
+ end
41
+
42
+ # Stops the runner
43
+ #
44
+ def stop
45
+ return unless self.active?
46
+ self._stop
47
+ @active = false
48
+ end
49
+
50
+ #region Override Methods
51
+ def _start
52
+ end
53
+
54
+ def _stop
55
+ end
56
+ #endregion
57
+
58
+ end
59
+
60
+ # This class monitors the queue and returns the descriptor
61
+ class Background < Base
62
+ attr_reader :callback, :thread
63
+
64
+ # Constructor
65
+ #
66
+ # @param name [Symbol] - the name of the worker
67
+ def initialize(name, uuid: nil, &callback)
68
+ super name, uuid: uuid
69
+
70
+ @callback = callback
71
+
72
+ # Log the event
73
+ logger.debug("#{self.class.name} '#{self.name}' created")
74
+ end
75
+
76
+ # Starts the background runner
77
+ #
78
+ def _start
79
+ # Start the background thread
80
+ Thread.new do
81
+
82
+ # The background thread will infinitely call the callback while the
83
+ # runner is active
84
+ while self.active?
85
+ begin
86
+ self.callback.call(self)
87
+ rescue => e
88
+ logger.error("#{self.class.name} #{e.class.name} - #{e.message}")
89
+ end
90
+ end
91
+
92
+ end
93
+ end
94
+ end
95
+
96
+ # This class is the main runner
97
+ class Main < Base
98
+ attr_reader :challenge, :client, :descriptor_queue, :queue_monitor
99
+
100
+ # Constructor
101
+ #
102
+ def initialize(name=nil, **options)
103
+ super name
104
+
105
+ # Combine the options
106
+ options = Wamp::Worker.config.connection(self.name).merge options
107
+
108
+ # Setup different options
109
+ @challenge = options[:challenge]
110
+ @client = options[:client] || Wamp::Client::Connection.new(options)
111
+ @active = false
112
+
113
+ # Log the event
114
+ logger.info("#{self.class.name} '#{self.name}' created with options")
115
+ logger.info(" uri: #{options[:uri]}")
116
+ logger.info(" realm: #{options[:realm]}")
117
+
118
+ # Create a queue for passing messages to the main runner
119
+ @descriptor_queue = ::Queue.new
120
+
121
+ # Note: since the queue monitor is attached to the same worker,
122
+ # we need to lock the UUIDs together. This will make sure they
123
+ # delegate background tasks correctly
124
+ uuid = self.dispatcher.uuid
125
+
126
+ # Create a command queue monitor
127
+ @queue_monitor = Background.new(self.name, uuid: uuid) do |runner|
128
+ descriptor = runner.dispatcher.check_queues
129
+ self.descriptor_queue.push(descriptor) if descriptor
130
+ end
131
+
132
+ # Add the tick loop handler
133
+ self.client.transport_class.add_tick_loop { self.tick_handler }
134
+
135
+ # Initialize the last tick
136
+ @last_tick = Time.now.to_i
137
+
138
+ # Catch SIGINT
139
+ Signal.trap('INT') { self.stop }
140
+ Signal.trap('TERM') { self.stop }
141
+ end
142
+
143
+ # Starts the run loop
144
+ #
145
+ def _start
146
+
147
+ # On join, we need to subscribe and register the different handlers
148
+ self.client.on :join do |session, details|
149
+ self.join_handler session, details
150
+ end
151
+
152
+ # On leave, we will print a message
153
+ self.client.on :leave do |reason, details|
154
+ self.leave_handler(reason, details)
155
+ end
156
+
157
+ # On challenge, we will run the users challenge code
158
+ self.client.on :challenge do |authmethod, details|
159
+ self.challenge_handler(authmethod, details)
160
+ end
161
+
162
+ # Start the monitors
163
+ self.queue_monitor.start
164
+
165
+ # Log info
166
+ logger.info("#{self.class.name} '#{self.name}' started")
167
+
168
+ # Start the connection
169
+ self.client.open
170
+ end
171
+
172
+ # Stops the run loop
173
+ #
174
+ def _stop
175
+
176
+ # Stop the other threads
177
+ self.queue_monitor.stop
178
+
179
+ # Stop the event machine
180
+ self.client.close
181
+ end
182
+
183
+ def join_handler(session, details)
184
+ logger.info("#{self.class.name} runner '#{self.name}' joined session with realm '#{details[:realm]}'")
185
+
186
+ # Set the session
187
+ self.dispatcher.session = session
188
+
189
+ # Register for the procedures
190
+ Wamp::Worker.register_procedures(self.name, self.dispatcher, session)
191
+
192
+ # Subscribe to the topics
193
+ Wamp::Worker.subscribe_topics(self.name, self.dispatcher, session)
194
+ end
195
+
196
+ def leave_handler(reason, details)
197
+ logger.info("#{self.class.name} runner '#{self.name}' left session: #{reason}")
198
+
199
+ # Clear the session
200
+ self.dispatcher.session = nil
201
+ end
202
+
203
+ def challenge_handler(authmethod, extra)
204
+ logger.info("#{self.class.name} runner '#{self.name}' challenge")
205
+
206
+ if self.challenge
207
+ self.challenge.call(authmethod, extra)
208
+ else
209
+ self.stop
210
+ raise(ArgumentError, "client asked for '#{authmethod}' challenge, but no ':challenge' option was provided")
211
+ end
212
+ end
213
+
214
+ # This method periodically checks if any work has come in from the queues
215
+ #
216
+ def tick_handler
217
+
218
+ # This code will implement the ticker every second. This tells the
219
+ # requestors that the worker is alive
220
+ current_time = Time.now.to_i
221
+ if current_time > @last_tick
222
+ self.dispatcher.increment_ticker
223
+ @last_tick = current_time
224
+ end
225
+
226
+ # Loop until the queue is empty
227
+ until self.descriptor_queue.empty? do
228
+
229
+ # Pop the value and process it
230
+ descriptor = self.descriptor_queue.pop
231
+ self.dispatcher.process(descriptor)
232
+
233
+ end
234
+ end
235
+
236
+ end
237
+
238
+ end
239
+ end
240
+ end