plezi 0.7.7 → 0.8.1
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 +4 -4
- data/CHANGELOG.md +26 -0
- data/README.md +3 -3
- data/lib/plezi.rb +35 -36
- data/lib/plezi/common/cache.rb +94 -0
- data/lib/plezi/{base → common}/dsl.rb +87 -68
- data/lib/plezi/{base → common}/logging.rb +15 -15
- data/lib/plezi/eventmachine/connection.rb +192 -0
- data/lib/plezi/eventmachine/em.rb +95 -0
- data/lib/plezi/eventmachine/io.rb +265 -0
- data/lib/plezi/eventmachine/protocol.rb +54 -0
- data/lib/plezi/eventmachine/queue.rb +51 -0
- data/lib/plezi/eventmachine/ssl_connection.rb +138 -0
- data/lib/plezi/eventmachine/timers.rb +117 -0
- data/lib/plezi/eventmachine/workers.rb +35 -0
- data/lib/plezi/handlers/http_host.rb +4 -4
- data/lib/plezi/handlers/magic_helpers.rb +1 -21
- data/lib/plezi/handlers/route.rb +3 -3
- data/lib/plezi/server/{helpers/http.rb → http.rb} +1 -57
- data/lib/plezi/server/{protocols/http_protocol.rb → http_protocol.rb} +18 -35
- data/lib/plezi/server/{protocols/http_request.rb → http_request.rb} +1 -1
- data/lib/plezi/server/{protocols/http_response.rb → http_response.rb} +45 -22
- data/lib/plezi/server/{helpers/mime_types.rb → mime_types.rb} +0 -0
- data/lib/plezi/server/{protocols/websocket.rb → websocket.rb} +34 -37
- data/lib/plezi/server/{protocols/ws_response.rb → ws_response.rb} +37 -19
- data/lib/plezi/version.rb +1 -1
- data/plezi.gemspec +3 -3
- data/resources/config.ru +9 -11
- metadata +27 -30
- data/lib/plezi/base/cache.rb +0 -89
- data/lib/plezi/base/connections.rb +0 -33
- data/lib/plezi/base/engine.rb +0 -77
- data/lib/plezi/base/events.rb +0 -93
- data/lib/plezi/base/io_reactor.rb +0 -62
- data/lib/plezi/base/rack_app.rb +0 -89
- data/lib/plezi/base/services.rb +0 -57
- data/lib/plezi/base/timers.rb +0 -71
- data/lib/plezi/server/README.md +0 -33
- data/lib/plezi/server/services/basic_service.rb +0 -224
- data/lib/plezi/server/services/no_service.rb +0 -196
- data/lib/plezi/server/services/ssl_service.rb +0 -193
@@ -21,22 +21,53 @@ module Plezi
|
|
21
21
|
@request, @service = request,request.service
|
22
22
|
end
|
23
23
|
|
24
|
-
#
|
24
|
+
# sends data through the websocket connection in a non-blocking way.
|
25
|
+
#
|
26
|
+
# Plezi will try a best guess at the type of the data (binary vs. clear text).
|
27
|
+
#
|
28
|
+
# This should be the preferred way.
|
25
29
|
def << str
|
26
30
|
service.send_nonblock self.class.frame_data(str.dup)
|
27
31
|
self
|
28
32
|
end
|
29
33
|
|
30
|
-
# sends
|
34
|
+
# sends data through the websocket connection in a blocking way.
|
35
|
+
#
|
36
|
+
# Plezi will try a best guess at the type of the data (binary vs. clear text).
|
31
37
|
#
|
32
|
-
# the response will remain open for more data to be sent through (using `response << data` and `response.send`).
|
33
38
|
def send str
|
34
|
-
service.
|
39
|
+
service.send self.class.frame_data(str.dup)
|
40
|
+
self
|
41
|
+
end
|
42
|
+
# sends binary data through the websocket connection in a blocking way.
|
43
|
+
#
|
44
|
+
def binsend str
|
45
|
+
service.send self.class.frame_data(str.dup, 2)
|
46
|
+
self
|
47
|
+
end
|
48
|
+
# sends clear text data through the websocket connection in a blocking way.
|
49
|
+
#
|
50
|
+
def txtsend str
|
51
|
+
service.send self.class.frame_data(str.dup, 1)
|
52
|
+
self
|
35
53
|
end
|
36
54
|
|
55
|
+
|
37
56
|
# makes sure any data held in the buffer is actually sent.
|
38
57
|
def flush
|
39
58
|
service.flush
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
# pings the connection
|
63
|
+
def ping
|
64
|
+
service.send_nonblock self.class.frame_data('', 9)
|
65
|
+
self
|
66
|
+
end
|
67
|
+
# pings the connection
|
68
|
+
def pong
|
69
|
+
service.send_nonblock self.class.frame_data('', 10)
|
70
|
+
self
|
40
71
|
end
|
41
72
|
|
42
73
|
# sends any pending data and closes the connection.
|
@@ -49,10 +80,10 @@ module Plezi
|
|
49
80
|
def self.frame_data data, op_code = nil, fin = true
|
50
81
|
# set up variables
|
51
82
|
frame = ''.force_encoding('binary')
|
52
|
-
op_code ||= data.encoding.name == 'UTF-8' ? 1 : 2
|
83
|
+
op_code ||= (data.encoding.name == 'UTF-8' ? 1 : 2)
|
53
84
|
data.force_encoding('binary')
|
54
85
|
|
55
|
-
# fragment big data chuncks into smaller frames
|
86
|
+
# fragment big data chuncks into smaller frames - op-code reset for 0 for all future frames.
|
56
87
|
[frame << frame_data(data.slice!(0..1048576), op_code, false), op_code = 0] while data.length > 1048576
|
57
88
|
|
58
89
|
# apply extenetions to the frame
|
@@ -77,16 +108,3 @@ module Plezi
|
|
77
108
|
end
|
78
109
|
end
|
79
110
|
end
|
80
|
-
|
81
|
-
|
82
|
-
######
|
83
|
-
## example requests
|
84
|
-
|
85
|
-
# GET / HTTP/1.1
|
86
|
-
# Host: localhost:2000
|
87
|
-
# Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
|
88
|
-
# Cookie: user_token=2INa32_vDgx8Aa1qe43oILELpSdIe9xwmT8GTWjkS-w
|
89
|
-
# User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/600.1.25 (KHTML, like Gecko) Version/8.0 Safari/600.1.25
|
90
|
-
# Accept-Language: en-us
|
91
|
-
# Accept-Encoding: gzip, deflate
|
92
|
-
# Connection: keep-alive
|
data/lib/plezi/version.rb
CHANGED
data/plezi.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Plezi::VERSION
|
9
9
|
spec.authors = ["Boaz Segev"]
|
10
10
|
spec.email = ['boaz@2be.co.il']
|
11
|
-
spec.summary = %q{
|
12
|
-
spec.description = %q{Plezi is
|
11
|
+
spec.summary = %q{Plezi is the native Ruby Framework for real time web-apps, with Websockets, RESTful routing and HTTP streaming support.}
|
12
|
+
spec.description = %q{Plezi is the native Ruby Framework for real time web-apps, with Websockets, RESTful routing and HTTP streaming support.}
|
13
13
|
spec.homepage = "http://boazsegev.github.io/plezi/"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
@@ -22,6 +22,6 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_development_dependency "rake", "~> 10.0"
|
23
23
|
|
24
24
|
# spec.post_install_message = "This update might break existing code - please review ChangeLog.md before upgrading any apps."
|
25
|
-
spec.post_install_message = "Thank you for installing Plezi, the Ruby Framework for real time web-apps."
|
25
|
+
spec.post_install_message = "Thank you for installing Plezi, the native Ruby Framework for real time web-apps."
|
26
26
|
|
27
27
|
end
|
data/resources/config.ru
CHANGED
@@ -22,18 +22,16 @@
|
|
22
22
|
# 2. you have better control over Middleware then you could have with Plezi.
|
23
23
|
# ("wait", you might say, "there is no Middleware in Plezi!"... "Ahhh", I will answer, "so much to discover...")
|
24
24
|
|
25
|
-
|
26
|
-
working_dir = ::File.expand_path(Dir.pwd)
|
27
|
-
app_path = ::File.expand_path(File.join(".."), __FILE__)
|
28
|
-
app_file_name = app_path.split(/[\\\/]/).last + ".rb"
|
29
|
-
|
30
|
-
# # make sure plezi doesn't set up sockets nor starts the event cycle.
|
31
25
|
PLEZI_ON_RACK = true
|
32
26
|
|
33
|
-
#load
|
34
|
-
|
35
|
-
|
27
|
+
# load all framework and gems
|
28
|
+
load ::File.expand_path(File.join("..", "environment.rb"), __FILE__)
|
29
|
+
|
30
|
+
# set up the routes
|
31
|
+
load ::File.expand_path(File.join("..", "routes.rb"), __FILE__)
|
36
32
|
|
37
|
-
|
33
|
+
# start the plezi EM, to make sure that the plezi async code doesn't break.
|
34
|
+
Plezi::EventMachine.start Plezi.max_threads
|
38
35
|
|
39
|
-
run
|
36
|
+
# run the Rack app
|
37
|
+
run Plezi::DSL
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: plezi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Boaz Segev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,8 +38,8 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
|
-
description: Plezi is
|
42
|
-
|
41
|
+
description: Plezi is the native Ruby Framework for real time web-apps, with Websockets,
|
42
|
+
RESTful routing and HTTP streaming support.
|
43
43
|
email:
|
44
44
|
- boaz@2be.co.il
|
45
45
|
executables:
|
@@ -56,16 +56,17 @@ files:
|
|
56
56
|
- TODO.md
|
57
57
|
- bin/plezi
|
58
58
|
- lib/plezi.rb
|
59
|
-
- lib/plezi/
|
60
|
-
- lib/plezi/
|
61
|
-
- lib/plezi/
|
62
|
-
- lib/plezi/
|
63
|
-
- lib/plezi/
|
64
|
-
- lib/plezi/
|
65
|
-
- lib/plezi/
|
66
|
-
- lib/plezi/
|
67
|
-
- lib/plezi/
|
68
|
-
- lib/plezi/
|
59
|
+
- lib/plezi/common/cache.rb
|
60
|
+
- lib/plezi/common/dsl.rb
|
61
|
+
- lib/plezi/common/logging.rb
|
62
|
+
- lib/plezi/eventmachine/connection.rb
|
63
|
+
- lib/plezi/eventmachine/em.rb
|
64
|
+
- lib/plezi/eventmachine/io.rb
|
65
|
+
- lib/plezi/eventmachine/protocol.rb
|
66
|
+
- lib/plezi/eventmachine/queue.rb
|
67
|
+
- lib/plezi/eventmachine/ssl_connection.rb
|
68
|
+
- lib/plezi/eventmachine/timers.rb
|
69
|
+
- lib/plezi/eventmachine/workers.rb
|
69
70
|
- lib/plezi/handlers/controller_magic.rb
|
70
71
|
- lib/plezi/handlers/http_echo.rb
|
71
72
|
- lib/plezi/handlers/http_host.rb
|
@@ -73,17 +74,13 @@ files:
|
|
73
74
|
- lib/plezi/handlers/magic_helpers.rb
|
74
75
|
- lib/plezi/handlers/route.rb
|
75
76
|
- lib/plezi/handlers/stubs.rb
|
76
|
-
- lib/plezi/server/
|
77
|
-
- lib/plezi/server/
|
78
|
-
- lib/plezi/server/
|
79
|
-
- lib/plezi/server/
|
80
|
-
- lib/plezi/server/
|
81
|
-
- lib/plezi/server/
|
82
|
-
- lib/plezi/server/
|
83
|
-
- lib/plezi/server/protocols/ws_response.rb
|
84
|
-
- lib/plezi/server/services/basic_service.rb
|
85
|
-
- lib/plezi/server/services/no_service.rb
|
86
|
-
- lib/plezi/server/services/ssl_service.rb
|
77
|
+
- lib/plezi/server/http.rb
|
78
|
+
- lib/plezi/server/http_protocol.rb
|
79
|
+
- lib/plezi/server/http_request.rb
|
80
|
+
- lib/plezi/server/http_response.rb
|
81
|
+
- lib/plezi/server/mime_types.rb
|
82
|
+
- lib/plezi/server/websocket.rb
|
83
|
+
- lib/plezi/server/ws_response.rb
|
87
84
|
- lib/plezi/version.rb
|
88
85
|
- plezi.gemspec
|
89
86
|
- resources/404.erb
|
@@ -116,8 +113,8 @@ homepage: http://boazsegev.github.io/plezi/
|
|
116
113
|
licenses:
|
117
114
|
- MIT
|
118
115
|
metadata: {}
|
119
|
-
post_install_message: Thank you for installing Plezi, the Ruby Framework for
|
120
|
-
time web-apps.
|
116
|
+
post_install_message: Thank you for installing Plezi, the native Ruby Framework for
|
117
|
+
real time web-apps.
|
121
118
|
rdoc_options: []
|
122
119
|
require_paths:
|
123
120
|
- lib
|
@@ -133,9 +130,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
133
130
|
version: '0'
|
134
131
|
requirements: []
|
135
132
|
rubyforge_project:
|
136
|
-
rubygems_version: 2.4.
|
133
|
+
rubygems_version: 2.4.7
|
137
134
|
signing_key:
|
138
135
|
specification_version: 4
|
139
|
-
summary:
|
140
|
-
streaming support.
|
136
|
+
summary: Plezi is the native Ruby Framework for real time web-apps, with Websockets,
|
137
|
+
RESTful routing and HTTP streaming support.
|
141
138
|
test_files: []
|
data/lib/plezi/base/cache.rb
DELETED
@@ -1,89 +0,0 @@
|
|
1
|
-
|
2
|
-
module Plezi
|
3
|
-
|
4
|
-
# File and Object Caching for Plezi
|
5
|
-
module_function
|
6
|
-
# contains the cached data, in the format: CACHE_STORE["filename"] = CacheObject
|
7
|
-
CACHE_STORE = {}
|
8
|
-
LOCK = Mutex.new
|
9
|
-
CACHABLE = %w{cache object slim haml css map js html scss sass coffee txt xml json yaml rb}
|
10
|
-
|
11
|
-
@cache_to_disk = true
|
12
|
-
|
13
|
-
# this class holds cached objects (data and modification times)
|
14
|
-
class CacheObject
|
15
|
-
# Cached attributes
|
16
|
-
attr_accessor :data, :mtime
|
17
|
-
|
18
|
-
# initialize a Cached object
|
19
|
-
def initialize d = nil, t = Time.now
|
20
|
-
@data, @mtime = d, t
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
# load the file from the cache (if exists) or the file system (if it doesn't)
|
25
|
-
def load_file filename
|
26
|
-
cached?(filename) ? get_cached(filename) : reload_file(filename)
|
27
|
-
end
|
28
|
-
# review a file's modification time
|
29
|
-
def file_mtime filename
|
30
|
-
return CACHE_STORE[filename].mtime if cached?(filename)
|
31
|
-
File.mtime(filename)
|
32
|
-
end
|
33
|
-
|
34
|
-
# force a file onto the cache (only if it is cachable - otherwise will load the file but will not cache it).
|
35
|
-
def reload_file filename
|
36
|
-
if CACHABLE.include? filename.match(/\.([^\.]+)$/)[1]
|
37
|
-
return cache_data filename, IO.read(filename), File.mtime(filename)
|
38
|
-
else
|
39
|
-
return IO.read(filename)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
# places data into the cache, and attempts to save the data to a file name.
|
43
|
-
def save_file filename, data, save_to_disk = false
|
44
|
-
cache_data filename, data if CACHABLE.include? filename.match(/\.([^\.]+)$/)[1]
|
45
|
-
begin
|
46
|
-
IO.write filename, data if save_to_disk
|
47
|
-
rescue Exception => e
|
48
|
-
Plezi.warn("File couldn't be written (#{filename}) - file system error?")
|
49
|
-
end
|
50
|
-
data
|
51
|
-
end
|
52
|
-
|
53
|
-
# places data into the cache, under an identifier ( file name ).
|
54
|
-
def cache_data filename, data, mtime = Time.now
|
55
|
-
LOCK.synchronize { CACHE_STORE[filename] = CacheObject.new( data, mtime ) }
|
56
|
-
data
|
57
|
-
end
|
58
|
-
|
59
|
-
# Get data from the cache. will throw an exception if there is no data in the cache.
|
60
|
-
def get_cached filename
|
61
|
-
CACHE_STORE[filename].data # if CACHE_STORE[filename]
|
62
|
-
end
|
63
|
-
|
64
|
-
# Remove data from the cache, if it exists.
|
65
|
-
def clear_cached filename
|
66
|
-
LOCK.synchronize { CACHE_STORE.delete filename } # if CACHE_STORE[filename]
|
67
|
-
end
|
68
|
-
|
69
|
-
# clears all cached data.
|
70
|
-
def clear_cache! filename
|
71
|
-
LOCK.synchronize { CACHE_STORE.clear } # if CACHE_STORE[filename]
|
72
|
-
end
|
73
|
-
|
74
|
-
# returns true if the filename is cached.
|
75
|
-
def cached? filename
|
76
|
-
!CACHE_STORE[filename].nil?
|
77
|
-
end
|
78
|
-
|
79
|
-
# returns true if the file exists on disk or in the cache.
|
80
|
-
def file_exists? filename
|
81
|
-
(CACHE_STORE[filename] || File.exists?(filename)) ? true : false
|
82
|
-
end
|
83
|
-
|
84
|
-
# returns true if the file has been update since data was last cached.
|
85
|
-
def cache_needs_update? filename
|
86
|
-
return true if CACHE_STORE[filename].nil? || CACHE_STORE[filename].mtime < File.mtime(filename)
|
87
|
-
false
|
88
|
-
end
|
89
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
|
2
|
-
module Plezi
|
3
|
-
|
4
|
-
module_function
|
5
|
-
|
6
|
-
# DANGER ZONE - Plezi Engine. the connections store
|
7
|
-
IO_CONNECTION_DIC = {}
|
8
|
-
# DANGER ZONE - Plezi Engine. the connections mutex
|
9
|
-
C_LOCKER = Mutex.new
|
10
|
-
|
11
|
-
# Plezi Engine, DO NOT CALL. disconnectes all active connections
|
12
|
-
def stop_connections
|
13
|
-
log 'Stopping connections'
|
14
|
-
C_LOCKER.synchronize {IO_CONNECTION_DIC.values.each {|c| c.timeout = -1; callback c, :on_disconnect unless c.disconnected?} ; IO_CONNECTION_DIC.clear}
|
15
|
-
end
|
16
|
-
|
17
|
-
# Plezi Engine, DO NOT CALL. adds a new connection to the connection stack
|
18
|
-
def add_connection io, params
|
19
|
-
connection = params[:service_type].new(io, params)
|
20
|
-
C_LOCKER.synchronize {IO_CONNECTION_DIC[connection.socket] = connection} if connection
|
21
|
-
callback(connection, :on_message)
|
22
|
-
end
|
23
|
-
# Plezi Engine, DO NOT CALL. removes a connection from the connection stack
|
24
|
-
def remove_connection connection
|
25
|
-
C_LOCKER.synchronize { IO_CONNECTION_DIC.delete connection.socket }
|
26
|
-
end
|
27
|
-
|
28
|
-
# clears closed connections from the stack
|
29
|
-
def clear_connections
|
30
|
-
C_LOCKER.synchronize { IO_CONNECTION_DIC.values.each {|c| callback c, :on_disconnect if c.disconnected? || c.timedout? } }
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|
data/lib/plezi/base/engine.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
|
2
|
-
module Plezi
|
3
|
-
|
4
|
-
module_function
|
5
|
-
|
6
|
-
# Plezi event cycle settings: gets how many worker threads Plezi will run.
|
7
|
-
def max_threads
|
8
|
-
@max_threads ||= 16
|
9
|
-
end
|
10
|
-
# Plezi event cycle settings: sets how many worker threads Plezi will run.
|
11
|
-
def max_threads= value
|
12
|
-
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
|
13
|
-
@max_threads = value.to_i
|
14
|
-
end
|
15
|
-
|
16
|
-
# Plezi Engine, DO NOT CALL. creates the thread pool and starts cycling through the events.
|
17
|
-
def start_services
|
18
|
-
# prepare threads
|
19
|
-
exit_flag = false
|
20
|
-
threads = []
|
21
|
-
run_every(5 , Plezi.method(:clear_connections)) #{info "Cleared inactive Connections"}
|
22
|
-
run_every 3600 , GC.method(:start)
|
23
|
-
# 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)." })
|
24
|
-
# run_every 10 , -> {Plezi.info "Cache report: #{CACHE_STORE.length} objects cached." }
|
25
|
-
(max_threads).times { Thread.new { thread_cycle until exit_flag } }
|
26
|
-
|
27
|
-
# Thread.new { check_connections until SERVICES.empty? }
|
28
|
-
#...
|
29
|
-
# set signal tarps
|
30
|
-
trap('INT'){ exit_flag = true; raise "close Plezi" }
|
31
|
-
trap('TERM'){ exit_flag = true; raise "close Plezi" }
|
32
|
-
puts "Services running Plezi version #{Plezi::VERSION}. Press ^C to stop"
|
33
|
-
puts %q{**deprecation notice**:
|
34
|
-
|
35
|
-
v.0.8.0 will consist of many changes that will also influence the API. The 0.8.0 version will mark the begining of some major rewrites, so that the code will be even easier to maintain.
|
36
|
-
|
37
|
-
If your code depends on Timers and other advanced API, please review your code before updating to the 0.8.0 version.
|
38
|
-
|
39
|
-
}
|
40
|
-
# sleep until trap raises exception (cycling might cause the main thread to ignor signals and lose attention)
|
41
|
-
(sleep unless SERVICES.empty?) rescue true
|
42
|
-
# start shutdown.
|
43
|
-
exit_flag = true
|
44
|
-
# set new tarps
|
45
|
-
trap('INT'){ puts 'Forced exit.'; Kernel.exit }#rescue true}
|
46
|
-
trap('TERM'){ puts 'Forced exit.'; Kernel.exit }#rescue true }
|
47
|
-
puts 'Started shutdown process. Press ^C to force quit.'
|
48
|
-
# shut down listening sockets
|
49
|
-
stop_services
|
50
|
-
# disconnect active connections
|
51
|
-
stop_connections
|
52
|
-
# cycle down threads
|
53
|
-
info "Waiting for workers to cycle down"
|
54
|
-
threads.each {|t| t.join if t.alive?}
|
55
|
-
|
56
|
-
# rundown any active events
|
57
|
-
thread_cycle
|
58
|
-
|
59
|
-
# call shutdown callbacks
|
60
|
-
SHUTDOWN_CALLBACKS.each {|s| s[0].call(*s[1]) }
|
61
|
-
SHUTDOWN_CALLBACKS.clear
|
62
|
-
|
63
|
-
# return exit code?
|
64
|
-
0
|
65
|
-
end
|
66
|
-
|
67
|
-
# Plezi Engine, DO NOT CALL. runs one thread cycle
|
68
|
-
def self.thread_cycle flag = 0
|
69
|
-
io_reactor rescue false # stop_connections
|
70
|
-
true while fire_event
|
71
|
-
fire_timers
|
72
|
-
|
73
|
-
# rescue Exception => e
|
74
|
-
# error e
|
75
|
-
# # raise if e.is_a?(SignalException) || e.is_a?(SystemExit)
|
76
|
-
end
|
77
|
-
end
|
data/lib/plezi/base/events.rb
DELETED
@@ -1,93 +0,0 @@
|
|
1
|
-
|
2
|
-
module Plezi
|
3
|
-
|
4
|
-
module_function
|
5
|
-
|
6
|
-
#######################
|
7
|
-
## Events (Callbacks) / Multi-tasking Platform
|
8
|
-
|
9
|
-
# DANGER ZONE - Plezi Engine. an Array containing all the shutdown callbacks that need to be called.
|
10
|
-
SHUTDOWN_CALLBACKS = []
|
11
|
-
# DANGER ZONE - Plezi Engine. an Array containing all the current events.
|
12
|
-
EVENTS = []
|
13
|
-
# DANGER ZONE - Plezi Engine. the Mutex locker for the event machine.
|
14
|
-
LOCKER = Mutex.new
|
15
|
-
|
16
|
-
# returns true if there are any unhandled events
|
17
|
-
def events?
|
18
|
-
LOCKER.synchronize {!EVENTS.empty?}
|
19
|
-
end
|
20
|
-
|
21
|
-
# Public API. pushes an event to the event's stack
|
22
|
-
#
|
23
|
-
# accepts:
|
24
|
-
# handler:: an object that answers to `call`, usually a Proc or a method.
|
25
|
-
# *arg:: any arguments that will be passed to the handler's `call` method.
|
26
|
-
#
|
27
|
-
# if a block is passed along, it will be used as a callback: the block will be called with the values returned by the handler's `call` method.
|
28
|
-
def push_event handler, *args, &block
|
29
|
-
if block
|
30
|
-
LOCKER.synchronize {EVENTS << [(Proc.new {|a| Plezi.push_event block, handler.call(*a)} ), args]}
|
31
|
-
else
|
32
|
-
LOCKER.synchronize {EVENTS << [handler, args]}
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# Public API. Runs the block asynchronously by pushin it as an event to the event's stack
|
37
|
-
#
|
38
|
-
# accepts a block to be executed asynchronously.
|
39
|
-
#
|
40
|
-
def run_async *args, &block
|
41
|
-
LOCKER.synchronize {EVENTS << [ block, args ]} if block
|
42
|
-
block
|
43
|
-
end
|
44
|
-
|
45
|
-
# Public API. creates an asynchronous call to a method, with an optional callback:
|
46
|
-
# demo use:
|
47
|
-
# `callback( Kernel, :sleep, 1 ) { puts "this is a demo" }`
|
48
|
-
# callback sets an asynchronous method call with a callback.
|
49
|
-
#
|
50
|
-
# parameters:
|
51
|
-
# object:: the object holding the method to be called (use `Kernel` for global methods).
|
52
|
-
# method:: the method's name (Symbol). this is the method that will be called.
|
53
|
-
# *arguments:: any additional arguments that should be sent to the method (the main method, not the callback).
|
54
|
-
#
|
55
|
-
# this method also accepts an optional block (the callback) that will be called once the main method has completed.
|
56
|
-
# the block will recieve the method's returned value.
|
57
|
-
#
|
58
|
-
# i.e.
|
59
|
-
# puts 'while we wait for my work to complete, can you tell me your name?'
|
60
|
-
# Plezi.callback(STDIO, :gets) do |name|
|
61
|
-
# puts "thank you, #{name}. I'm working on your request as we speak."
|
62
|
-
# end
|
63
|
-
# # do more work without waiting for the chat to start nor complete.
|
64
|
-
def callback object, method, *args, &block
|
65
|
-
push_event object.method(method), *args, &block
|
66
|
-
end
|
67
|
-
|
68
|
-
# Public API. 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
|
-
LOCKER.synchronize {SHUTDOWN_CALLBACKS << [block, args]}
|
72
|
-
elsif block
|
73
|
-
LOCKER.synchronize {SHUTDOWN_CALLBACKS << [(Proc.new {|*a| block.call(object.method(method).call(*a))} ), args]}
|
74
|
-
elsif object && method
|
75
|
-
LOCKER.synchronize {SHUTDOWN_CALLBACKS << [object.method(method), args]}
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
# Plezi Engine, DO NOT CALL. pulls an event from the event's stack and processes it.
|
80
|
-
def fire_event
|
81
|
-
event = LOCKER.synchronize {EVENTS.shift}
|
82
|
-
return false unless event
|
83
|
-
begin
|
84
|
-
event[0].call(*event[1])
|
85
|
-
rescue OpenSSL::SSL::SSLError => e
|
86
|
-
warn "SSL Bump - SSL Certificate refused?"
|
87
|
-
rescue Exception => e
|
88
|
-
raise if e.is_a?(SignalException) || e.is_a?(SystemExit)
|
89
|
-
error e
|
90
|
-
end
|
91
|
-
true
|
92
|
-
end
|
93
|
-
end
|