Class: CelluloidPubsub::WebServer
- Inherits:
-
Reel::Server::HTTP
- Object
- Reel::Server::HTTP
- CelluloidPubsub::WebServer
- Includes:
- BaseActor
- Defined in:
- lib/celluloid_pubsub/web_server.rb
Overview
webserver to which socket connects should connect to . the server will dispatch each request into a new Reactor which will handle the action based on the message
Constant Summary collapse
- HOST =
The hostname on which the webserver runs on by default
'0.0.0.0'
- PATH =
The request path that the webserver accepts by default
'/ws'
- CLASSIC_ADAPTER =
The name of the default adapter
'classic'
Instance Attribute Summary collapse
Attributes included from BaseActor
Class Method Summary collapse
-
.find_unused_port ⇒ Integer
the method get from the socket connection that is already opened the port used.
-
.open_socket_on_unused_port ⇒ TCPServer
the method will return the socket conection opened on the unused port.
-
.socket_families ⇒ Hash
the method will return the socket families avaiable.
-
.socket_infos ⇒ Array
the method will return the socket information available as an array.
Instance Method Summary collapse
-
#adapter ⇒ Boolean
the method will return true if redis can be used otherwise false.
-
#backlog ⇒ Integer
the method will return the number of connections allowed to the server.
-
#debug_enabled? ⇒ Boolean
the method will return true if debug is enabled otherwise false.
-
#dispatch_websocket_request(request) ⇒ void
method will instantiate a new reactor object, will link the reactor to the current actor and will dispatch the request to the reactor.
-
#handle_dispatched_message(reactor, data) ⇒ void
If the message can be parsed into a Hash it will respond to the reactor’s websocket connection with the same message in JSON format otherwise will try send the message how it is and escaped into JSON format.
-
#hostname ⇒ String
the method will return the hostname on which the server is running on.
-
#initialize(options = {}) ⇒ void
constructor
receives a list of options that are used to configure the webserver.
-
#log_file_path ⇒ String
the method will return the file path of the log file where debug messages will be printed.
-
#on_connection(connection) ⇒ void
callback that will execute when receiving new conections If the connections is a websocket will call method #route_websocket and if the connection is HTTP will call method #route_request For websocket connections , the connection is detached from the server and dispatched to another actor.
-
#path ⇒ String
the method will return the URL path on which will acceept connections.
-
#port ⇒ String
the method will return the port on which will accept connections.
-
#reactor_class ⇒ Class
returns the reactor class that will handle the connection depending if redis is enabled or not.
-
#route_request(connection, request) ⇒ void
HTTP connections are not accepted so this method will show 404 message “Not Found”.
-
#route_websocket(reactor, socket) ⇒ void
If the socket url matches with the one accepted by the server, it will dispatch the socket connection to a new reactor Reactor#work The new actor is linked to the webserver.
-
#run ⇒ Object
this method is overriden from the Reel::Server::HTTP in order to set the spy to the celluloid logger before the connection is accepted.
-
#shutdown ⇒ void
the method will terminate the current actor.
-
#spy ⇒ Boolean
the method will return true if connection to the server should be spied upon.
Methods included from BaseActor
celluloid_logger_class, celluloid_version, config, included, setup_actor_supervision, version_less_than_seventeen?
Methods included from Helper
action_subscribe?, fetch_gem_version, filtered_error?, find_loaded_gem, find_loaded_gem_property, get_parsed_version, log_debug, parse_options, setup_celluloid_exception_handler, setup_celluloid_logger, setup_log_file, #succesfull_subscription?, verify_gem_version
Constructor Details
#initialize(options = {}) ⇒ void
receives a list of options that are used to configure the webserver
:nocov:
45 46 47 48 49 50 51 52 53 |
# File 'lib/celluloid_pubsub/web_server.rb', line 45 def initialize( = {}) Celluloid.boot unless Celluloid.running? @server_options = () @subscribers = {} @mutex = Mutex.new setup_celluloid_logger debug "CelluloidPubsub::WebServer example starting on #{hostname}:#{port}" super(hostname, port, { spy: spy, backlog: backlog }, &method(:on_connection)) end |
Instance Attribute Details
#mutex ⇒ Mutex, Object
20 21 22 |
# File 'lib/celluloid_pubsub/web_server.rb', line 20 def mutex @mutex end |
#server_options ⇒ Hash, Object
20 21 22 |
# File 'lib/celluloid_pubsub/web_server.rb', line 20 def @server_options end |
#subscribers ⇒ Hash, Object
20 21 22 |
# File 'lib/celluloid_pubsub/web_server.rb', line 20 def subscribers @subscribers end |
Class Method Details
.find_unused_port ⇒ Integer
the method get from the socket connection that is already opened the port used.
94 95 96 97 98 99 100 101 |
# File 'lib/celluloid_pubsub/web_server.rb', line 94 def self.find_unused_port @@unused_port ||= begin socket = open_socket_on_unused_port port = socket.addr[1] socket.close port end end |
.open_socket_on_unused_port ⇒ TCPServer
the method will return the socket conection opened on the unused port
61 62 63 64 65 |
# File 'lib/celluloid_pubsub/web_server.rb', line 61 def self.open_socket_on_unused_port return ::TCPServer.open('0.0.0.0', 0) if socket_families.key?('AF_INET') return ::TCPServer.open('::', 0) if socket_families.key?('AF_INET6') ::TCPServer.open(0) end |
.socket_families ⇒ Hash
the method will return the socket families avaiable
rubocop:disable ClassVars
84 85 86 |
# File 'lib/celluloid_pubsub/web_server.rb', line 84 def self.socket_families @@socket_families ||= Hash[*socket_infos.map { |af, *_| af }.uniq.zip([]).flatten] end |
.socket_infos ⇒ Array
the method will return the socket information available as an array
73 74 75 |
# File 'lib/celluloid_pubsub/web_server.rb', line 73 def self.socket_infos ::Socket::getaddrinfo('localhost', nil, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE) end |
Instance Method Details
#adapter ⇒ Boolean
the method will return true if redis can be used otherwise false
119 120 121 122 |
# File 'lib/celluloid_pubsub/web_server.rb', line 119 def adapter @adapter ||= @server_options.fetch('adapter', CelluloidPubsub::WebServer::CLASSIC_ADAPTER) @adapter.present? ? @adapter : CelluloidPubsub::WebServer::CLASSIC_ADAPTER end |
#backlog ⇒ Integer
the method will return the number of connections allowed to the server
202 203 204 |
# File 'lib/celluloid_pubsub/web_server.rb', line 202 def backlog @backlog = @server_options.fetch('backlog', 1024) end |
#debug_enabled? ⇒ Boolean
the method will return true if debug is enabled otherwise false
130 131 132 133 |
# File 'lib/celluloid_pubsub/web_server.rb', line 130 def debug_enabled? @debug_enabled = @server_options.fetch('enable_debug', true) @debug_enabled == true end |
#dispatch_websocket_request(request) ⇒ void
This method returns an undefined value.
method will instantiate a new reactor object, will link the reactor to the current actor and will dispatch the request to the reactor
258 259 260 261 262 |
# File 'lib/celluloid_pubsub/web_server.rb', line 258 def dispatch_websocket_request(request) reactor = reactor_class.new Actor.current.link reactor route_websocket(reactor, request.websocket) end |
#handle_dispatched_message(reactor, data) ⇒ void
This method returns an undefined value.
If the message can be parsed into a Hash it will respond to the reactor’s websocket connection with the same message in JSON format otherwise will try send the message how it is and escaped into JSON format
306 307 308 309 310 311 |
# File 'lib/celluloid_pubsub/web_server.rb', line 306 def (reactor, data) log_debug "#{self.class} trying to dispatch message #{data.inspect}" = reactor.parse_json_data(data) final_data = .present? && .is_a?(Hash) ? .to_json : data.to_json reactor.websocket << final_data end |
#hostname ⇒ String
the method will return the hostname on which the server is running on
162 163 164 |
# File 'lib/celluloid_pubsub/web_server.rb', line 162 def hostname @hostname = @server_options.fetch('hostname', CelluloidPubsub::WebServer::HOST) end |
#log_file_path ⇒ String
the method will return the file path of the log file where debug messages will be printed
152 153 154 |
# File 'lib/celluloid_pubsub/web_server.rb', line 152 def log_file_path @log_file_path = @server_options.fetch('log_file_path', nil) end |
#on_connection(connection) ⇒ void
This method returns an undefined value.
callback that will execute when receiving new conections If the connections is a websocket will call method #route_websocket and if the connection is HTTP will call method #route_request For websocket connections , the connection is detached from the server and dispatched to another actor
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/celluloid_pubsub/web_server.rb', line 219 def on_connection(connection) while request = connection.request if request.websocket? log_debug "#{self.class} Received a WebSocket connection" # We're going to hand off this connection to another actor (Writer/Reader) # However, initially Reel::Connections are "attached" to the # Reel::Server::HTTP actor, meaning that the server manages the connection # lifecycle (e.g. error handling) for us. # # If we want to hand this connection off to another actor, we first # need to detach it from the Reel::Server (in this case, Reel::Server::HTTP) connection.detach dispatch_websocket_request(request) return else route_request connection, request end end end |
#path ⇒ String
the method will return the URL path on which will acceept connections
182 183 184 |
# File 'lib/celluloid_pubsub/web_server.rb', line 182 def path @path = @server_options.fetch('path', CelluloidPubsub::WebServer::PATH) end |
#port ⇒ String
the method will return the port on which will accept connections
172 173 174 |
# File 'lib/celluloid_pubsub/web_server.rb', line 172 def port @port ||= @server_options.fetch('port', nil) || self.class.find_unused_port end |
#reactor_class ⇒ Class
returns the reactor class that will handle the connection depending if redis is enabled or not
246 247 248 |
# File 'lib/celluloid_pubsub/web_server.rb', line 246 def reactor_class adapter == CelluloidPubsub::WebServer::CLASSIC_ADAPTER ? CelluloidPubsub::Reactor : "CelluloidPubsub::#{adapter.camelize}Reactor".constantize end |
#route_request(connection, request) ⇒ void
This method returns an undefined value.
HTTP connections are not accepted so this method will show 404 message “Not Found”
272 273 274 275 |
# File 'lib/celluloid_pubsub/web_server.rb', line 272 def route_request(connection, request) log_debug "404 Not Found: #{request.path}" connection.respond :not_found, 'Not found' end |
#route_websocket(reactor, socket) ⇒ void
This method returns an undefined value.
If the socket url matches with the one accepted by the server, it will dispatch the socket connection to a new reactor Reactor#work The new actor is linked to the webserver
287 288 289 290 291 292 293 294 295 |
# File 'lib/celluloid_pubsub/web_server.rb', line 287 def route_websocket(reactor, socket) url = socket.url if url == path || url == '/?' reactor.async.work(socket, Actor.current) else log_debug "Received invalid WebSocket request for: #{url}" socket.close end end |
#run ⇒ Object
this method is overriden from the Reel::Server::HTTP in order to set the spy to the celluloid logger before the connection is accepted.
108 109 110 111 |
# File 'lib/celluloid_pubsub/web_server.rb', line 108 def run @spy = Celluloid.logger if spy loop { async.handle_connection @server.accept } end |
#shutdown ⇒ void
This method returns an undefined value.
the method will terminate the current actor
141 142 143 144 |
# File 'lib/celluloid_pubsub/web_server.rb', line 141 def shutdown debug "#{self.class} tries to 'shudown'" terminate end |
#spy ⇒ Boolean
the method will return true if connection to the server should be spied upon
192 193 194 |
# File 'lib/celluloid_pubsub/web_server.rb', line 192 def spy @spy = @server_options.fetch('spy', false) end |