Class: Roby::Interface::REST::Server
- Defined in:
- lib/roby/interface/rest/server.rb
Overview
A thin-based server class that provides the REST API in-process
Defined Under Namespace
Classes: InvalidServer, Timeout
Instance Attribute Summary collapse
-
#app ⇒ Object
readonly
The application that is being exposed by this server.
-
#host ⇒ String
readonly
The host the server is bound to.
-
#port(timeout: 0) ⇒ Object
readonly
The server port.
Class Method Summary collapse
-
.attach_api_to_interface(api, interface) ⇒ Object
private
Helper method that transforms a Grape API class so that it gets an #interface accessor that provides the interface object the API is meant to work on.
-
.server_alive?(host, port) ⇒ Boolean
Tests whether the server is actually alive.
Instance Method Summary collapse
-
#create_thin_thread(server, sync) ⇒ Object
private
Create the underlying thread that starts the thin server.
-
#initialize(app, host: '0.0.0.0', port: Roby::Interface::DEFAULT_REST_PORT, api: REST::API) ⇒ Server
constructor
Create a new server.
-
#join(timeout: nil) ⇒ Object
Waits for the server to stop.
-
#running? ⇒ Boolean
Whether the server is running.
- #server_alive? ⇒ Boolean
-
#start(wait_timeout: 5) ⇒ Object
Starts the server.
-
#stop(join_timeout: 10) ⇒ Object
Asks the server to stop.
-
#wait_start(timeout: 10) ⇒ Object
Wait for the server to be properly booted.
Constructor Details
#initialize(app, host: '0.0.0.0', port: Roby::Interface::DEFAULT_REST_PORT, api: REST::API) ⇒ Server
Create a new server
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/roby/interface/rest/server.rb', line 32 def initialize(app, host: '0.0.0.0', port: Roby::Interface::DEFAULT_REST_PORT, api: REST::API) @app = app @host = host @interface = Interface.new(app) @wait_start = Concurrent::IVar.new api = self.class.attach_api_to_interface(api, @interface) rack_app = Rack::Builder.new do yield(self) if block_given? map '/api' do run api end end @server = Thin::Server.new(host, port, rack_app, signals: false) @server.silent = true if @server.backend.respond_to?(:port) @original_port = port if port != 0 @port = port end else @original_port = @port = nil end end |
Instance Attribute Details
#app ⇒ Object (readonly)
The application that is being exposed by this server
7 8 9 |
# File 'lib/roby/interface/rest/server.rb', line 7 def app @app end |
#host ⇒ String (readonly)
The host the server is bound to
12 13 14 |
# File 'lib/roby/interface/rest/server.rb', line 12 def host @host end |
#port(timeout: 0) ⇒ Object (readonly)
The server port
If the port given to #initialize was zero, the method will return the actual port only if the server is fully started. Set timeout to a value greater than zero or nil to synchronize on it.
21 22 23 |
# File 'lib/roby/interface/rest/server.rb', line 21 def port @port end |
Class Method Details
.attach_api_to_interface(api, interface) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Helper method that transforms a Grape API class so that it gets an #interface accessor that provides the interface object the API is meant to work on
64 65 66 67 68 69 70 71 72 73 |
# File 'lib/roby/interface/rest/server.rb', line 64 def self.attach_api_to_interface(api, interface) storage = Hash.new Class.new do define_method(:call) do |env| env['roby.interface'] = interface env['roby.storage'] = storage api.call(env) end end.new end |
.server_alive?(host, port) ⇒ Boolean
Tests whether the server is actually alive
It accesses the ‘ping’ endpoint and verifies its result
195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/roby/interface/rest/server.rb', line 195 def self.server_alive?(host, port) test_value = rand(10) returned_value = RestClient. get("http://#{host}:#{port}/api/ping", params: { value: test_value }) if test_value != Integer(returned_value) raise InvalidServer, "unexpected server answer to 'ping', expected #{test_value} but got #{returned_value}" end true rescue Errno::ECONNREFUSED => e false rescue RestClient::Exception => e raise InvalidServer, "unexpected server answer to 'ping': #{e}" end |
Instance Method Details
#create_thin_thread(server, sync) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Create the underlying thread that starts the thin server
97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/roby/interface/rest/server.rb', line 97 def create_thin_thread(server, sync) Thread.new do server.backend.start do if server.backend.respond_to?(:port) sync.set(server.backend.port) else sync.set(nil) end end end end |
#join(timeout: nil) ⇒ Object
Waits for the server to stop
166 167 168 169 170 171 172 173 174 |
# File 'lib/roby/interface/rest/server.rb', line 166 def join(timeout: nil) if timeout if !@server_thread.join(timeout) raise Timeout, "timed out while waiting for the server to stop" end else @server_thread.join end end |
#running? ⇒ Boolean
Whether the server is running
90 91 92 |
# File 'lib/roby/interface/rest/server.rb', line 90 def running? @server_thead && @server_thread.alive? end |
#server_alive? ⇒ Boolean
181 182 183 184 185 186 187 |
# File 'lib/roby/interface/rest/server.rb', line 181 def server_alive? if !@wait_start.complete? return false else self.class.server_alive?('localhost', port) end end |
#start(wait_timeout: 5) ⇒ Object
Starts the server
82 83 84 85 86 87 |
# File 'lib/roby/interface/rest/server.rb', line 82 def start(wait_timeout: 5) @server_thread = create_thin_thread(@server, @wait_start) if wait_timeout != 0 wait_start(timeout: wait_timeout) end end |
#stop(join_timeout: 10) ⇒ Object
Asks the server to stop
153 154 155 156 157 158 |
# File 'lib/roby/interface/rest/server.rb', line 153 def stop(join_timeout: 10) EventMachine.next_tick { @server.stop! } if join_timeout != 0 join(timeout: join_timeout) end end |
#wait_start(timeout: 10) ⇒ Object
Wait for the server to be properly booted
140 141 142 143 144 145 |
# File 'lib/roby/interface/rest/server.rb', line 140 def wait_start(timeout: 10) @wait_start.wait(timeout) if !@wait_start.complete? raise Timeout, "timed out while waiting for the server to start" end end |