pomelo-citrus 0.0.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 +7 -0
- data/README.md +20 -0
- data/Rakefile +0 -0
- data/citrus.gemspec +35 -0
- data/lib/citrus.rb +18 -0
- data/lib/citrus/application.rb +237 -0
- data/lib/citrus/citrus.rb +27 -0
- data/lib/citrus/common/remote/backend/msg_remote.rb +57 -0
- data/lib/citrus/common/remote/frontend/channel_remote.rb +73 -0
- data/lib/citrus/common/remote/frontend/session_remote.rb +108 -0
- data/lib/citrus/common/service/backend_session_service.rb +265 -0
- data/lib/citrus/common/service/channel_service.rb +485 -0
- data/lib/citrus/common/service/connection_service.rb +71 -0
- data/lib/citrus/common/service/filter_service.rb +92 -0
- data/lib/citrus/common/service/handler_service.rb +63 -0
- data/lib/citrus/common/service/session_service.rb +446 -0
- data/lib/citrus/components/backend_session.rb +32 -0
- data/lib/citrus/components/channel.rb +33 -0
- data/lib/citrus/components/component.rb +19 -0
- data/lib/citrus/components/connection.rb +48 -0
- data/lib/citrus/components/connector.rb +265 -0
- data/lib/citrus/components/master.rb +40 -0
- data/lib/citrus/components/monitor.rb +48 -0
- data/lib/citrus/components/proxy.rb +195 -0
- data/lib/citrus/components/push_scheduler.rb +74 -0
- data/lib/citrus/components/remote.rb +71 -0
- data/lib/citrus/components/server.rb +61 -0
- data/lib/citrus/components/session.rb +41 -0
- data/lib/citrus/connectors/commands/handshake.rb +22 -0
- data/lib/citrus/connectors/commands/heartbeat.rb +22 -0
- data/lib/citrus/connectors/commands/kick.rb +22 -0
- data/lib/citrus/connectors/common/coder.rb +21 -0
- data/lib/citrus/connectors/common/handler.rb +21 -0
- data/lib/citrus/connectors/ws_connector.rb +110 -0
- data/lib/citrus/connectors/ws_socket.rb +75 -0
- data/lib/citrus/filters/handler/handler_filter.rb +19 -0
- data/lib/citrus/filters/handler/too_busy.rb +16 -0
- data/lib/citrus/filters/rpc/rpc_filter.rb +19 -0
- data/lib/citrus/filters/rpc/too_busy.rb +16 -0
- data/lib/citrus/master/master.rb +60 -0
- data/lib/citrus/master/starter.rb +73 -0
- data/lib/citrus/master/watchdog.rb +83 -0
- data/lib/citrus/modules/console.rb +45 -0
- data/lib/citrus/modules/console_module.rb +35 -0
- data/lib/citrus/modules/master_watcher.rb +88 -0
- data/lib/citrus/modules/monitor_watcher.rb +86 -0
- data/lib/citrus/monitor/monitor.rb +61 -0
- data/lib/citrus/push_schedulers/buffer.rb +16 -0
- data/lib/citrus/push_schedulers/direct.rb +76 -0
- data/lib/citrus/server/server.rb +327 -0
- data/lib/citrus/util/app_util.rb +203 -0
- data/lib/citrus/util/constants.rb +19 -0
- data/lib/citrus/util/countdown_latch.rb +42 -0
- data/lib/citrus/util/events.rb +14 -0
- data/lib/citrus/util/module_util.rb +68 -0
- data/lib/citrus/util/path_util.rb +50 -0
- data/lib/citrus/util/utils.rb +49 -0
- data/lib/citrus/version.rb +7 -0
- metadata +241 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 25 July 2014
|
4
|
+
|
5
|
+
module Citrus
|
6
|
+
# Connectors
|
7
|
+
#
|
8
|
+
#
|
9
|
+
module Connectors
|
10
|
+
# Commands
|
11
|
+
#
|
12
|
+
#
|
13
|
+
module Commands
|
14
|
+
# HeartBeat
|
15
|
+
#
|
16
|
+
#
|
17
|
+
class HeartBeat
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 25 July 2014
|
4
|
+
|
5
|
+
module Citrus
|
6
|
+
# Connectors
|
7
|
+
#
|
8
|
+
#
|
9
|
+
module Connectors
|
10
|
+
# Commands
|
11
|
+
#
|
12
|
+
#
|
13
|
+
module Commands
|
14
|
+
# Kick
|
15
|
+
#
|
16
|
+
#
|
17
|
+
class Kick
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 25 July 2014
|
4
|
+
|
5
|
+
module Citrus
|
6
|
+
# Connectors
|
7
|
+
#
|
8
|
+
#
|
9
|
+
module Connectors
|
10
|
+
# Common
|
11
|
+
#
|
12
|
+
#
|
13
|
+
module Common
|
14
|
+
# Coder
|
15
|
+
#
|
16
|
+
#
|
17
|
+
module Coder
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 25 July 2014
|
4
|
+
|
5
|
+
module Citrus
|
6
|
+
# Connectors
|
7
|
+
#
|
8
|
+
#
|
9
|
+
module Connectors
|
10
|
+
# Common
|
11
|
+
#
|
12
|
+
#
|
13
|
+
module Common
|
14
|
+
# Handler
|
15
|
+
#
|
16
|
+
#
|
17
|
+
module Handler
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 25 July 2014
|
4
|
+
|
5
|
+
require 'json'
|
6
|
+
require 'websocket-eventmachine-server'
|
7
|
+
require 'citrus/connectors/ws_socket'
|
8
|
+
|
9
|
+
module Citrus
|
10
|
+
# Connectors
|
11
|
+
#
|
12
|
+
#
|
13
|
+
module Connectors
|
14
|
+
# WsConnector
|
15
|
+
#
|
16
|
+
#
|
17
|
+
class WsConnector
|
18
|
+
include Utils::EventEmitter
|
19
|
+
|
20
|
+
# Create a new websocket connector
|
21
|
+
#
|
22
|
+
# @param [Integer] port
|
23
|
+
# @param [String] host
|
24
|
+
# @param [Hash] args
|
25
|
+
def initialize port, host, args={}
|
26
|
+
@port = port
|
27
|
+
@host = host
|
28
|
+
@args = args
|
29
|
+
|
30
|
+
@heartbeats = args[:heartbeats] || true
|
31
|
+
@heartbeat_timeout = args[:heartbeat_timeout] || 0.06
|
32
|
+
@heartbeat_interval = args[:heartbeat_interval] || 0.025
|
33
|
+
|
34
|
+
@cur_id = 0
|
35
|
+
end
|
36
|
+
|
37
|
+
# Start the connector to listen to the specified port
|
38
|
+
def start &block
|
39
|
+
begin
|
40
|
+
@server = WebSocket::EventMachine::Server.start(:host => @host, :port => @port) { |ws|
|
41
|
+
ws.onopen {
|
42
|
+
ws_socket = WsSocket.new @cur_id, ws
|
43
|
+
@cur_id += 1
|
44
|
+
emit :connection, ws_socket
|
45
|
+
ws_socket.on(:closing) { |reason|
|
46
|
+
ws_socket.send({ 'route' => 'on_kick', 'reason' => reason })
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
rescue => err
|
51
|
+
end
|
52
|
+
EM.next_tick { block_given? and yield }
|
53
|
+
end
|
54
|
+
|
55
|
+
# Stop the connector
|
56
|
+
#
|
57
|
+
# @param [Boolean] force
|
58
|
+
def stop force=false, &block
|
59
|
+
@server.close
|
60
|
+
EM.next_tick { block_given? and yield }
|
61
|
+
end
|
62
|
+
|
63
|
+
# Encode message
|
64
|
+
#
|
65
|
+
# @param [Integer, NilClass] req_id
|
66
|
+
# @param [String] route
|
67
|
+
# @param [Object] msg
|
68
|
+
def encode req_id, route, msg
|
69
|
+
if req_id
|
70
|
+
compose_response req_id, route, msg
|
71
|
+
else
|
72
|
+
componse_push route, msg
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Decode message
|
77
|
+
#
|
78
|
+
# @param [String] msg
|
79
|
+
def decode msg
|
80
|
+
begin
|
81
|
+
JSON.parse msg
|
82
|
+
rescue => err
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
# Compose response message
|
89
|
+
#
|
90
|
+
# @param [Integer] msg_id
|
91
|
+
# @param [String] route
|
92
|
+
# @param [Hash] msg_body
|
93
|
+
#
|
94
|
+
# @private
|
95
|
+
def compose_response msg_id, route, msg_body
|
96
|
+
{ 'id' => msg_id, 'body' => msg_body }
|
97
|
+
end
|
98
|
+
|
99
|
+
# Compose push message
|
100
|
+
#
|
101
|
+
# @param [String] route
|
102
|
+
# @param [Hash] msg_body
|
103
|
+
#
|
104
|
+
# @private
|
105
|
+
def compose_push route, msg_body
|
106
|
+
{ 'route' => route, 'body' => msg_body }
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 25 July 2014
|
4
|
+
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
module Citrus
|
8
|
+
# Connectors
|
9
|
+
#
|
10
|
+
#
|
11
|
+
module Connectors
|
12
|
+
# WsSocket
|
13
|
+
#
|
14
|
+
#
|
15
|
+
class WsSocket
|
16
|
+
include Utils::EventEmitter
|
17
|
+
|
18
|
+
attr_reader :id, :remote_address
|
19
|
+
|
20
|
+
# Create a new ws socket
|
21
|
+
#
|
22
|
+
# @param [Integer] id
|
23
|
+
# @param [Object] ws
|
24
|
+
def initialize id, ws
|
25
|
+
@id = id
|
26
|
+
@ws = ws
|
27
|
+
|
28
|
+
port, ip = Socket.unpack_sockaddr_in @ws.get_peername
|
29
|
+
@remote_address = {
|
30
|
+
:port => port,
|
31
|
+
:ip => ip
|
32
|
+
}
|
33
|
+
|
34
|
+
@ws.onclose { emit :disconnect }
|
35
|
+
@ws.onerror { |err| emit :error }
|
36
|
+
@ws.onmessage { |msg, type| emit :message, msg }
|
37
|
+
|
38
|
+
@state = :state_inited
|
39
|
+
end
|
40
|
+
|
41
|
+
# Send message to the client
|
42
|
+
#
|
43
|
+
# @param [Hash] msg
|
44
|
+
def send msg
|
45
|
+
return unless @state == :state_inited
|
46
|
+
@ws.send msg.to_json
|
47
|
+
end
|
48
|
+
|
49
|
+
# Disconnect the client
|
50
|
+
def disconnect
|
51
|
+
return if @state == :state_closed
|
52
|
+
@state = :state_closed
|
53
|
+
@ws.close
|
54
|
+
end
|
55
|
+
|
56
|
+
# Batch version for send
|
57
|
+
#
|
58
|
+
# @param [Array] msgs
|
59
|
+
def send_batch msgs
|
60
|
+
@ws.send encode_batch(msgs)
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
# Encode batch messages
|
66
|
+
#
|
67
|
+
# @param [Array] msgs
|
68
|
+
#
|
69
|
+
# @private
|
70
|
+
def encode_batch msgs
|
71
|
+
msgs.to_json
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 21 July 2014
|
4
|
+
|
5
|
+
module Citrus
|
6
|
+
# HandlerFilter
|
7
|
+
#
|
8
|
+
#
|
9
|
+
class HandlerFilter
|
10
|
+
attr_accessor :name
|
11
|
+
|
12
|
+
#
|
13
|
+
#
|
14
|
+
#
|
15
|
+
def initialize
|
16
|
+
@name = ''
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 17 July 2014
|
4
|
+
|
5
|
+
require 'citrus/filters/handler/handler_filter'
|
6
|
+
|
7
|
+
module Citrus
|
8
|
+
# TooBusy
|
9
|
+
#
|
10
|
+
#
|
11
|
+
class TooBusy < HandlerFilter
|
12
|
+
def initialize
|
13
|
+
@name = 'too_busy'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 21 July 2014
|
4
|
+
|
5
|
+
module Citrus
|
6
|
+
# RpcFilter
|
7
|
+
#
|
8
|
+
#
|
9
|
+
class RpcFilter
|
10
|
+
attr_accessor :name
|
11
|
+
|
12
|
+
#
|
13
|
+
#
|
14
|
+
#
|
15
|
+
def initialize
|
16
|
+
@name = ''
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 17 July 2014
|
4
|
+
|
5
|
+
require 'citrus/filters/rpc/rpc_filter'
|
6
|
+
|
7
|
+
module Citrus
|
8
|
+
# TooBusy
|
9
|
+
#
|
10
|
+
#
|
11
|
+
class TooBusy < RpcFilter
|
12
|
+
def initialize
|
13
|
+
@name = 'too_busy'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 18 July 2014
|
4
|
+
|
5
|
+
require 'citrus/master/starter'
|
6
|
+
require 'citrus/util/module_util'
|
7
|
+
|
8
|
+
module Citrus
|
9
|
+
# Master
|
10
|
+
#
|
11
|
+
#
|
12
|
+
module Master
|
13
|
+
# Master
|
14
|
+
#
|
15
|
+
#
|
16
|
+
class Master
|
17
|
+
include Starter
|
18
|
+
include Utils::ModuleUtil
|
19
|
+
|
20
|
+
# Create a new master
|
21
|
+
#
|
22
|
+
# @param [Object] app
|
23
|
+
# @param [Hash] args
|
24
|
+
def initialize app, args={}
|
25
|
+
@app = app
|
26
|
+
@master = true
|
27
|
+
@master_info = app.master
|
28
|
+
@modules = []
|
29
|
+
@close_watcher = args[:close_watcher]
|
30
|
+
@console_service = CitrusAdmin::ConsoleService.create_master_console(
|
31
|
+
args.merge({
|
32
|
+
:env => app.env,
|
33
|
+
:port => @master_info[:port]
|
34
|
+
})
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Start master
|
39
|
+
def start &block
|
40
|
+
register_default_modules
|
41
|
+
load_modules
|
42
|
+
@console_service.start { |err|
|
43
|
+
exit if err
|
44
|
+
start_modules { |err|
|
45
|
+
if err
|
46
|
+
block_given? and yield err
|
47
|
+
return
|
48
|
+
end
|
49
|
+
run_servers
|
50
|
+
block_given? and yield
|
51
|
+
}
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
# Stop master
|
56
|
+
def stop &block
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 19 July 2014
|
4
|
+
|
5
|
+
module Citrus
|
6
|
+
# Master
|
7
|
+
#
|
8
|
+
#
|
9
|
+
module Master
|
10
|
+
# Starter
|
11
|
+
#
|
12
|
+
#
|
13
|
+
module Starter
|
14
|
+
include Utils
|
15
|
+
|
16
|
+
# Run servers
|
17
|
+
def run_servers
|
18
|
+
condition = @app.start_id || @app.type
|
19
|
+
case condition
|
20
|
+
when :master
|
21
|
+
when :all
|
22
|
+
@app.servers_map.each { |server_id, server|
|
23
|
+
run_server server
|
24
|
+
}
|
25
|
+
else
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Run server
|
30
|
+
#
|
31
|
+
# @param [Hash] server
|
32
|
+
def run_server server, &block
|
33
|
+
if local? server[:host]
|
34
|
+
options = []
|
35
|
+
options << sprintf('%s', $0)
|
36
|
+
options << sprintf('env=%s', @app.env)
|
37
|
+
server.each { |key, value|
|
38
|
+
options << sprintf('%s=%s', key, value)
|
39
|
+
}
|
40
|
+
local_run 'ruby', nil, options
|
41
|
+
else
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
#
|
47
|
+
#
|
48
|
+
def ssh_run
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
#
|
53
|
+
#
|
54
|
+
def local_run cmd, host, options
|
55
|
+
spawn_process cmd, host, options
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
#
|
60
|
+
#
|
61
|
+
def spawn_process cmd, host, options
|
62
|
+
child = fork {
|
63
|
+
exec cmd + options.inject('') { |res, str| res += ' ' + str }
|
64
|
+
}
|
65
|
+
EM.watch_process child, Module.new {
|
66
|
+
define_method(:process_exited) {
|
67
|
+
Process.wait child
|
68
|
+
}
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|