plezi 0.9.2 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/README.md +44 -31
  4. data/bin/plezi +3 -3
  5. data/lib/plezi.rb +21 -43
  6. data/lib/plezi/common/defer.rb +21 -0
  7. data/lib/plezi/common/dsl.rb +115 -91
  8. data/lib/plezi/common/redis.rb +44 -0
  9. data/lib/plezi/common/settings.rb +58 -0
  10. data/lib/plezi/handlers/controller_core.rb +132 -0
  11. data/lib/plezi/handlers/controller_magic.rb +85 -259
  12. data/lib/plezi/handlers/http_router.rb +139 -60
  13. data/lib/plezi/handlers/route.rb +9 -178
  14. data/lib/plezi/handlers/stubs.rb +2 -2
  15. data/lib/plezi/helpers/http_sender.rb +72 -0
  16. data/lib/plezi/helpers/magic_helpers.rb +12 -0
  17. data/lib/plezi/{server → helpers}/mime_types.rb +0 -0
  18. data/lib/plezi/version.rb +1 -1
  19. data/plezi.gemspec +3 -11
  20. data/resources/Gemfile +20 -21
  21. data/resources/controller.rb +2 -2
  22. data/resources/oauth_config.rb +1 -1
  23. data/resources/redis_config.rb +2 -0
  24. data/test/plezi_tests.rb +39 -46
  25. metadata +24 -33
  26. data/lib/plezi/common/logging.rb +0 -60
  27. data/lib/plezi/eventmachine/connection.rb +0 -190
  28. data/lib/plezi/eventmachine/em.rb +0 -98
  29. data/lib/plezi/eventmachine/io.rb +0 -272
  30. data/lib/plezi/eventmachine/protocol.rb +0 -54
  31. data/lib/plezi/eventmachine/queue.rb +0 -51
  32. data/lib/plezi/eventmachine/ssl_connection.rb +0 -144
  33. data/lib/plezi/eventmachine/timers.rb +0 -117
  34. data/lib/plezi/eventmachine/workers.rb +0 -33
  35. data/lib/plezi/handlers/http_echo.rb +0 -27
  36. data/lib/plezi/handlers/http_host.rb +0 -214
  37. data/lib/plezi/handlers/magic_helpers.rb +0 -32
  38. data/lib/plezi/server/http.rb +0 -129
  39. data/lib/plezi/server/http_protocol.rb +0 -319
  40. data/lib/plezi/server/http_request.rb +0 -146
  41. data/lib/plezi/server/http_response.rb +0 -319
  42. data/lib/plezi/server/websocket.rb +0 -251
  43. data/lib/plezi/server/websocket_client.rb +0 -178
  44. data/lib/plezi/server/ws_response.rb +0 -161
@@ -1,60 +0,0 @@
1
-
2
- module Plezi
3
-
4
- #######################
5
- ## Logging
6
- module_function
7
-
8
- # the logger object
9
- @logger = ::Logger.new(STDOUT)
10
-
11
- # gets the active logger
12
- def logger
13
- @logger
14
- end
15
- # gets the active STDOUT copy, if exists
16
- def logger_copy
17
- @copy_to_stdout
18
- end
19
-
20
- # create and set the logger object. accepts:
21
- # log_file:: a log file name to be used for logging
22
- # copy_to_stdout:: if false, log will only log to file. defaults to true.
23
- def create_logger log_file = STDOUT, copy_to_stdout = false
24
- @copy_to_stdout = ( copy_to_stdout ? (::Logger.new(STDOUT)) : false )
25
- @logger = ::Logger.new(log_file)
26
- end
27
- alias :set_logger :create_logger
28
-
29
- # writes a raw line to the log\
30
- def log_raw line
31
- @logger << line
32
- @copy_to_stdout << line if @copy_to_stdout
33
- end
34
-
35
- # logs info
36
- def log data
37
- @logger.info data
38
- @copy_to_stdout.info data if @copy_to_stdout
39
- end
40
- # logs info
41
- def info data
42
- @logger.info data
43
- @copy_to_stdout.info data if @copy_to_stdout
44
- end
45
- # logs warning
46
- def warn data
47
- @logger.warn data
48
- @copy_to_stdout.warn data if @copy_to_stdout
49
- end
50
- # logs errors
51
- def error data
52
- @logger.error data
53
- @copy_to_stdout.error data if @copy_to_stdout
54
- end
55
- # logs a fatal error
56
- def fatal data
57
- @logger.fatal data
58
- @copy_to_stdout.fatal data if @copy_to_stdout
59
- end
60
- end
@@ -1,190 +0,0 @@
1
- # encoding: UTF-8
2
-
3
-
4
-
5
- module Plezi
6
-
7
- module EventMachine
8
-
9
- class Connection
10
- attr_reader :socket, :params, :active_time, :out_que, :locker
11
- attr_accessor :protocol, :handler, :timeout
12
-
13
- # initializes the connection and it's settings.
14
- def initialize socket, params
15
- @socket, @params, @handler = socket, params, params[:handler]
16
- # socket.setsockopt Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, "\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" #== [10 sec 0 usec].pack '1_2'
17
- @out_que, @locker = [], Mutex.new
18
- @protocol = params[:protocol].is_a?(Class) ? (params[:protocol].new self, params) : params[:protocol]
19
- @protocol.on_connect if @protocol.is_a?(Protocol)
20
- touch
21
- @timeout ||= 5
22
- end
23
-
24
- # used by the EM when the connection should handle data.
25
- def call
26
- # don't let competing threads do the same job.
27
- return false if @locker.locked?
28
- begin
29
- @locker.synchronize do
30
- return disconnect if disconnected?
31
- protocol.on_message
32
- end
33
-
34
- rescue Exception => e
35
- PL.error e
36
- return disconnect
37
- end
38
- end
39
-
40
- def clear?
41
- return false unless timedout? || disconnected?
42
- close
43
- true
44
- end
45
-
46
- # checks if a connection timed out
47
- def timedout?
48
- Time.now - @active_time > @timeout.to_i
49
- end
50
-
51
- # resets the timer for the connection timeout
52
- def touch
53
- @active_time = Time.now
54
- end
55
-
56
- # returns an IO-like object used for reading/writing (unlike the original IO object, this can be an SSL layer or any other wrapper object).
57
- def io
58
- @socket
59
- end
60
-
61
- # the proc used to remove the connection from the IO stack.
62
- REMOVE_CONNECTION_PROC = Proc.new {|old_io| EventMachine.remove_io old_io }
63
- # sends data immidiately - forcing the data to be sent, flushing any pending messages in the que
64
- def send data = nil
65
- return false unless @out_que.any? || data
66
- begin
67
- @locker.synchronize do
68
- unless @out_que.empty?
69
- @out_que.each { |d| _send d }
70
- @out_que.clear
71
- end
72
- (_send data rescue disconnect) if data
73
- end
74
- rescue => e
75
- EventMachine.queue( [@socket], REMOVE_CONNECTION_PROC)
76
- end
77
- true
78
- end
79
-
80
- # the non-blocking proc used for send_nonblock
81
- SEND_COMPLETE_PROC = Proc.new {|c| c.send }
82
-
83
- # sends data without waiting - data might be sent in a different order then intended.
84
- def send_nonblock data
85
- touch
86
- @locker.synchronize {@out_que << data}
87
- EventMachine.queue [self], SEND_COMPLETE_PROC
88
- end
89
-
90
- # adds data to the out buffer - but doesn't send the data until a send event is called.
91
- def << data
92
- touch
93
- @locker.synchronize {@out_que << data}
94
- end
95
-
96
- # makes sure any data in the que is send and calls `flush` on the socket, to make sure the buffer is sent.
97
- def flush
98
- send
99
- io.flush rescue true
100
- end
101
-
102
- # called once the connection is closed.
103
- #
104
- def on_disconnect
105
- @locker.synchronize do
106
- EventMachine.queue [], protocol.method(:on_disconnect) if protocol && !protocol.is_a?(Class)
107
- @protocol = false
108
- end
109
- end
110
-
111
- # the non-blocking proc used for send_nonblock
112
- FLUSH_AND_CLOSE_PROC = Proc.new {|c| c.flush; EventMachine.remove_io c.socket}
113
-
114
- # Closes the connection. This is always asynchronous and will return immidiately.
115
- def close
116
- EventMachine.queue [self], FLUSH_AND_CLOSE_PROC
117
- end
118
- alias :disconnect :close
119
-
120
- # status markers
121
-
122
- # returns true if the service is disconnected
123
- def disconnected?
124
- (@socket.closed? || socket.stat.mode != 0140666) rescue true # if mode is read only, it's the same as closed.
125
- end
126
-
127
- # returns true if the socket has content to be read.
128
- def has_incoming_data?
129
- (@socket.stat.size > 0) rescue false
130
- end
131
-
132
-
133
- # identification markers
134
-
135
- #returns the service type - set to normal
136
- def service_type
137
- 'normal'
138
- end
139
- #returns true if the service is encrypted using the OpenSSL library.
140
- def ssl?
141
- false
142
- end
143
-
144
- #################
145
- # overide the followind methods for any child class.
146
-
147
- # this is a public method and it should be used by child classes to implement each
148
- # read(_nonblock) action. accepts one argument ::size for an optional buffer size to be read.
149
- def read size = 1048576
150
- begin
151
- data = @socket.recv_nonblock( size )
152
- return nil if data.to_s.empty?
153
- touch
154
- data
155
- rescue Exception => e
156
-
157
- end
158
- end
159
- # # this is a public method and it should be used by child classes to implement each
160
- # # read(_nonblock) action. accepts one argument ::size for an optional buffer size to be read.
161
- # def read_line
162
- # data = @line_data ||= ''
163
- # begin
164
- # data << @socket.recv_nonblock( 1 ).to_s until data[-1] == "\n"
165
- # @line_data = ''
166
- # return data
167
- # rescue => e
168
- # return false
169
- # ensure
170
- # touch
171
- # end
172
- # end
173
-
174
- protected
175
-
176
- # this is a protected method, it should be used by child classes to implement each
177
- # send action.
178
- def _send data
179
- @active_time += 7200
180
- len = data.bytesize
181
- i = act = @socket.send data, 0
182
- while len > act && i!=0
183
- act += (i = @socket.send data.byteslice(act..-1) , 0)
184
- end
185
- touch
186
- end
187
-
188
- end
189
- end
190
- end
@@ -1,98 +0,0 @@
1
- module Plezi
2
-
3
- # This module holds the events, timers and IO logic and workflow (asynchronous workflow).
4
- #
5
- # Timed events are approximated and their exact time of execution is dependant on the workload and continues uptime of the process (timed events AREN'T persistant)
6
- module EventMachine
7
-
8
- module_function
9
-
10
- # sets the amount of worker threads cycling the event machine and starts (or re-starts) the event machine.
11
- def start count=12
12
- @workers ||= []
13
- @workers_lock ||= Mutex.new
14
- stop unless @workers.count <= count
15
- (count - @workers.count).times {@workers << Worker.new}
16
- end
17
-
18
- # runs through all existing events and one idle cycle
19
- def run wait = 0.1
20
- begin
21
- fire_timers
22
- do_job while do_job
23
- # replace with io
24
- review_io || sleep(wait)
25
- rescue => e
26
- Plezi.error e
27
- end
28
- end
29
-
30
- def stop_and_wait
31
- @workers.each {|w| w.stop }
32
- @workers.each {|w| w.join }
33
- @workers_lock.synchronize { @workers.clear }
34
- end
35
-
36
- def stop
37
- @workers.each {|w| w.stop }
38
- @workers_lock.synchronize { @workers.clear;}
39
- end
40
-
41
- def running?
42
- @workers && @workers.any?
43
- end
44
- def count_living_workers
45
- (@workers_lock.synchronize { @workers.select {|w| w.alive? } } ).count
46
- end
47
- def workers_status
48
- @workers_lock.synchronize { @workers.map {|w| w.status } }
49
- end
50
-
51
- SHUTDOWN_CALLBACKS = []
52
- # runs the shutdown queue
53
- def shutdown
54
- old_timeout = io_timeout
55
- io_timeout = 0.001
56
- stop_and_wait rescue false
57
- run
58
- io_timeout = old_timeout
59
- do_job while do_job
60
- stop_connections
61
- do_job while do_job
62
- QUEUE_LOCKER.synchronize do
63
- SHUTDOWN_CALLBACKS.each { |s_job| s_job[0].call(*s_job[1]) }
64
- SHUTDOWN_CALLBACKS.clear
65
- end
66
- true
67
- end
68
- # Adds a callback to be called once the services were shut down. see: callback for more info.
69
- def on_shutdown object=nil, method=nil, *args, &block
70
- if block && !object && !method
71
- QUEUE_LOCKER.synchronize {SHUTDOWN_CALLBACKS << [block, args]}
72
- elsif block
73
- QUEUE_LOCKER.synchronize {SHUTDOWN_CALLBACKS << [(Proc.new {|*a| block.call(object.method(method).call(*a))} ), args]}
74
- elsif object && method
75
- QUEUE_LOCKER.synchronize {SHUTDOWN_CALLBACKS << [object.method(method), args]}
76
- end
77
- end
78
-
79
- end
80
-
81
- module_function
82
-
83
- # Plezi event cycle settings: gets how many worker threads Plezi will initially run.
84
- def max_threads
85
- @max_threads ||= 16
86
- end
87
- # Plezi event cycle settings: sets how many worker threads Plezi will initially run.
88
- def max_threads= value
89
- raise "Plezi will hang and do nothing if there isn't at least one (1) working thread. Cannot set Plezi.max_threads = #{value}" if value.to_i <= 0
90
- @max_threads = value.to_i
91
- start @max_threads if EventMachine.running?
92
- end
93
-
94
- # Adds a callback to be called once the services were shut down. see: callback for more info.
95
- def on_shutdown object=nil, method=nil, *args, &block
96
- EventMachine.on_shutdown object, method, *args, &block
97
- end
98
- end
@@ -1,272 +0,0 @@
1
- module Plezi
2
- module EventMachine
3
-
4
- # a basic IO listening socket wrapper.
5
- class BasicIO
6
-
7
- # attribute readers
8
- attr_reader :io, :params, :protocol
9
- # initialize the listener with the actual socket and the properties.
10
- def initialize io, params
11
- @io, @params, @protocol = io, params, false
12
- end
13
- # returns true if the socket is closed and the object can be cleared.
14
- def clear?
15
- @io.closed?
16
- end
17
- # accepts a new connection, adding it to the IO stack, so that it will be reviewed.
18
- def call
19
- begin
20
- socket = io.accept_nonblock
21
- handler = (@params[:ssl] ? SSLConnection : Connection).new socket, @params
22
- EventMachine.add_io socket, handler
23
- rescue Errno::EWOULDBLOCK => e
24
-
25
- rescue OpenSSL::SSL::SSLError => e
26
- Plezi.info "Due to an SSL issue, the connection was refused (maybe untrusted certificate)?"
27
-
28
- rescue => e
29
- Plezi.error e
30
- end
31
- end
32
- def on_disconnect
33
- true
34
- end
35
- def close
36
- false
37
- end
38
- alias :disconnect :close
39
- end
40
- module_function
41
-
42
- # the IO stack.
43
- EM_IO = {}
44
- # the IO Mutex
45
- IO_LOCKER = Mutex.new
46
-
47
- # Adds an io object to the Plezi event machine.
48
- #
49
- # accepts:
50
- # io:: an actual IO object (i.e. socket) that can be passed on to IO.select.
51
- # job:: an object that answers to #call. job#call will be called whenever the IO object is flagged by IO.select.
52
- #
53
- def add_io io, job
54
- IO_LOCKER.synchronize { EM_IO[io] = job }
55
- end
56
-
57
- # the proc for async IO removal, in case of IO exceptions raised by unexpectedly closed sockets.
58
- IO_CLEAR_ASYNC_PROC = Proc.new {|c| c.on_disconnect rescue false }
59
- # removes an IO from the event machine.
60
- def remove_io io
61
- IO_LOCKER.synchronize { queue [(EM_IO.delete io)], IO_CLEAR_ASYNC_PROC; (io.close unless io.closed? rescue true); }
62
- end
63
-
64
- # deletes any connections that are closed or timed out.
65
- def clear_connections
66
- IO_LOCKER.synchronize { EM_IO.delete_if { |io, c| c.clear? } }
67
- end
68
-
69
- # forces the event machine to forget all the existing connections (they will not be reviewed any longer).
70
- def forget_connections
71
- IO_LOCKER.synchronize { EM_IO.clear }
72
- end
73
-
74
- # stops all the connections without stopping the lisntener IO's.
75
- def stop_connections
76
- IO_LOCKER.synchronize { EM_IO.each { |io, c| c.close } }
77
- end
78
-
79
- # set the default idle waiting time.
80
- @io_timeout = 0.1
81
-
82
- # Plezi event cycle settings: how long to wait for IO activity before forcing another cycle.
83
- #
84
- # No timing methods will be called during this interval.
85
- #
86
- # Gets the current idle setting. The default setting is 0.1 seconds.
87
- def io_timeout
88
- @io_timeout
89
- end
90
- # Plezi event cycle settings: how long to wait for IO activity before forcing another cycle.
91
- #
92
- # No timing methods will be called during this interval (#run_after / #run_every).
93
- #
94
- # It's rare, but it's one of the reasons for the timeout: some connections might wait for the timeout befor being established.
95
- #
96
- # set the current idle setting
97
- def io_timeout= value
98
- @io_timeout = value
99
- end
100
-
101
- # hangs for IO data or io_timeout
102
- def review_io
103
- return false if IO_LOCKER.locked?
104
- IO_LOCKER.synchronize do
105
- return false unless queue_empty? && EM_IO.any?
106
- io_array = EM_IO.keys
107
- begin
108
- io_r = ::IO.select(io_array, nil, io_array, @io_timeout)
109
- return false unless io_r
110
- io_r[0].each {|io| queue [], EM_IO[io] }
111
- io_r[2].each { |io| EM_IO.delete io }
112
- rescue Errno::EWOULDBLOCK => e
113
-
114
- rescue => e
115
- EM_IO.keys.each {|io| EventMachine.queue [EM_IO.delete(io)], IO_CLEAR_ASYNC_PROC if io.closed?}
116
- raise e
117
- end
118
- true
119
- end
120
- end
121
-
122
- end
123
-
124
- module DSL
125
- module_function
126
-
127
- # public API to add a service to the framework.
128
- # accepts a Hash object with any of the following options (Hash keys):
129
- # port:: port number. defaults to 3000 or the port specified when the script was called.
130
- # host:: the host name. defaults to any host not explicitly defined (a catch-all).
131
- # alias:: a String or an Array of Strings which represent alternative host names (i.e. `alias: ["admin.google.com", "admin.gmail.com"]`).
132
- # root:: the public root folder. if this is defined, static files will be served from the location.
133
- # assets:: the assets root folder. defaults to nil (no assets support). if the path is defined, assets will be served from `/assets/...` (or the public_asset path defined) before any static files. assets will not be served if the file in the /public/assets folder if up to date (a rendering attempt will be made for systems that allow file writing).
134
- # assets_public:: the assets public uri location (uri format, NOT a file path). defaults to `/assets`. assets will be saved (or rendered) to the assets public folder and served as static files.
135
- # assets_callback:: a method that accepts one parameters: `request` and renders any custom assets. the method should return `false` unless it has created a response object (`response = Plezi::HTTPResponse.new(request)`) and sent a response to the client using `response.finish`.
136
- # save_assets:: saves the rendered assets to the filesystem, under the public folder. defaults to false.
137
- # templates:: the templates root folder. defaults to nil (no template support). templates can be rendered by a Controller class, using the `render` method.
138
- # ssl:: if true, an SSL service will be attempted. if no certificate is defined, an attempt will be made to create a self signed certificate.
139
- # ssl_key:: the public key for the SSL service.
140
- # ssl_cert:: the certificate for the SSL service.
141
- #
142
- # some further options, which are unstable and might be removed in future versions, are:
143
- # protocol:: the protocol objects (usually a class, but any object answering `#call` will do).
144
- # handler:: an optional handling object, to be called upon by the protocol (i.e. #on_message, #on_connect, etc'). this option is used to allow easy protocol switching, such as from HTTP to Websockets.
145
- #
146
- # Duringn normal Plezi behavior, the optional `handler` object will be returned if `listen` is called more than once for the same port.
147
- #
148
- # assets:
149
- #
150
- # assets support will render `.sass`, `.scss` and `.coffee` and save them as local files (`.css`, `.css`, and `.js` respectively)
151
- # before sending them as static files.
152
- #
153
- # templates:
154
- #
155
- # ERB, Slim and Haml are natively supported.
156
- #
157
- def listen parameters = {}
158
- # update default values
159
- parameters = {assets_public: '/assets'}.update(parameters)
160
-
161
- # set port if undefined
162
- if !parameters[:port] && defined? ARGV
163
- if ARGV.find_index('-p')
164
- port_index = ARGV.find_index('-p') + 1
165
- parameters[:port] ||= ARGV[port_index].to_i
166
- ARGV[port_index] = (parameters[:port] + 1).to_s
167
- else
168
- ARGV << '-p'
169
- ARGV << '3001'
170
- parameters[:port] ||= 3000
171
- end
172
- end
173
-
174
- #keeps information of past ports.
175
- @listeners ||= {}
176
- @listeners_locker = Mutex.new
177
-
178
- # check if the port is used twice.
179
- if @listeners[parameters[:port]]
180
- puts "WARNING: port aleady in use! returning existing service and attemptin to add host (maybe multiple hosts? use `host` instead)." unless parameters[:host]
181
- @active_router = @listeners[parameters[:port]].params[:handler] || @listeners[parameters[:port]].params[:protocol]
182
- @active_router.add_host parameters[:host], parameters if @active_router.is_a?(HTTPRouter)
183
- return @active_router
184
- end
185
-
186
- # make sure the protocol exists.
187
- unless parameters[:protocol]
188
- parameters[:protocol] = HTTPProtocol
189
- parameters[:handler] ||= HTTPRouter.new
190
- end
191
-
192
- # create the EventMachine IO object.
193
- io = defined?(PLEZI_ON_RACK) ? parameters : EventMachine::BasicIO.new( TCPServer.new(parameters[:port]), parameters)
194
- EventMachine.add_io io.io, io unless defined? PLEZI_ON_RACK
195
- @listeners_locker.synchronize { @listeners[parameters[:port]] = io }
196
- # set the active router to the handler or the protocol.
197
- @active_router = (parameters[:handler] || parameters[:protocol])
198
- @active_router.add_host(parameters[:host], parameters) if @active_router.is_a?(HTTPRouter)
199
-
200
- Plezi.run_async { Plezi.info "Started listening on port #{parameters[:port]}." } unless defined?(PLEZI_ON_RACK)
201
-
202
- # return the current handler or the protocol..
203
- @active_router
204
- end
205
-
206
- # Plezi Engine, DO NOT CALL. creates the thread pool and starts cycling through the events.
207
- def start_services
208
- if @listeners && @listeners.any?
209
- # prepare threads
210
- exit_flag = false
211
- threads = []
212
- Plezi.run_every(5, &EventMachine.method(:clear_connections))
213
- Plezi.run_every(3_600) {GC.start; Plezi.info "Refreshing worker threads."; EventMachine.stop; EventMachine.start Plezi.max_threads}
214
- # run_every( 1 , Proc.new() { Plezi.info "#{IO_CONNECTION_DIC.length} active connections ( #{ IO_CONNECTION_DIC.select{|k,v| v.protocol.is_a?(WSProtocol)} .length } websockets)." })
215
- # run_every 10 , -> {Plezi.info "Cache report: #{CACHE_STORE.length} objects cached." }
216
- # puts "** Deprecation Warning:\n- The current code for default error pages will be changed in version 0.9.0.\n- Default error pages will follow a different naming and location conventions.\n- The updated design will be part of the updated `plezi` helper script.\nPlease review your code before upgrading to the 0.9.0 version.\n"
217
- puts "Services running Plezi version #{Plezi::VERSION}. Press ^C to stop"
218
- EventMachine.start Plezi.max_threads
219
-
220
- # set signal tarps
221
- trap('INT'){ exit_flag = true; raise "close Plezi" }
222
- trap('TERM'){ exit_flag = true; raise "close Plezi" }
223
- # sleep until trap raises exception (cycling might cause the main thread to ignor signals and lose attention)
224
- sleep rescue true
225
- # avoid refreshing the working threads and stop all timed events.
226
- EventMachine.clear_timers
227
- # start shutdown.
228
- exit_flag = true
229
- # set new tarps
230
- trap('INT'){ puts 'Forced exit.'; Kernel.exit } #rescue true}
231
- trap('TERM'){ puts 'Forced exit.'; Kernel.exit } #rescue true }
232
- puts 'Started shutdown process. Press ^C to force quit.'
233
- # shut down listening sockets
234
- stop_services
235
- # cycle down threads
236
- Plezi.info "Finishing up and running shutdown tasks."
237
- end
238
- EventMachine.shutdown
239
- Plezi.info "Plezi shutdown as requested."
240
- puts "Since we're resting, why not practice Tai Chi?"
241
- # return exit code?
242
- 0
243
- end
244
- # Closes and removes listening IO's registered by Plezi using #listen
245
- def stop_services
246
- Plezi.info 'Stopping services'
247
- @listeners_locker.synchronize { @listeners.each {|port, io| EventMachine.remove_io(io.io); Plezi.info "Stoped listening on port #{port}" } ; @listeners.clear } if @listeners
248
- true
249
- end
250
- end
251
-
252
- module_function
253
-
254
- # Plezi event cycle settings: how long to wait for IO activity before forcing another cycle.
255
- #
256
- # No timing methods will be called during this interval.
257
- #
258
- # Gets the current idle setting. The default setting is 0.1 seconds.
259
- def idle_sleep
260
- EventMachine.io_timeout
261
- end
262
- # Plezi event cycle settings: how long to wait for IO activity before forcing another cycle.
263
- #
264
- # No timing methods will be called during this interval (#run_after / #run_every).
265
- #
266
- # It's rare, but it's one of the reasons for the timeout: some connections might wait for the timeout befor being established.
267
- #
268
- # set the current idle setting
269
- def idle_sleep= value
270
- EventMachine.io_timeout = value
271
- end
272
- end