pomelo-citrus 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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,195 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 20 July 2014
|
4
|
+
|
5
|
+
require 'digest/crc32'
|
6
|
+
require 'citrus/components/component'
|
7
|
+
require 'citrus/util/path_util'
|
8
|
+
|
9
|
+
module Citrus
|
10
|
+
# Components
|
11
|
+
#
|
12
|
+
#
|
13
|
+
module Components
|
14
|
+
# Proxy
|
15
|
+
#
|
16
|
+
#
|
17
|
+
class Proxy < Component
|
18
|
+
@name = 'proxy'
|
19
|
+
|
20
|
+
include Utils::PathUtil
|
21
|
+
|
22
|
+
# Initialize the component
|
23
|
+
#
|
24
|
+
# @param [Object] app
|
25
|
+
# @param [Hash] args
|
26
|
+
def initialize app, args={}
|
27
|
+
args[:buffer_msg] = args[:buffer_msg] || false
|
28
|
+
args[:interval] = args[:interval] || 0.03
|
29
|
+
|
30
|
+
args[:router] = gen_router
|
31
|
+
args[:context] = app
|
32
|
+
args[:route_context] = app
|
33
|
+
|
34
|
+
@args = args
|
35
|
+
@client = CitrusRpc::RpcClient::Client.new @args
|
36
|
+
|
37
|
+
@app = app
|
38
|
+
@app.on(:add_servers) { |servers| add_servers servers }
|
39
|
+
@app.on(:remove_servers) { |ids| remove_servers ids }
|
40
|
+
@app.on(:replace_servers) { |servers| replace_servers servers }
|
41
|
+
end
|
42
|
+
|
43
|
+
# Start the component
|
44
|
+
def start &block
|
45
|
+
unless @app.rpc_befores.empty?
|
46
|
+
@client.before @app.rpc_befores
|
47
|
+
end
|
48
|
+
|
49
|
+
unless @app.rpc_afters.empty?
|
50
|
+
@client.after @app.rpc_afters
|
51
|
+
end
|
52
|
+
|
53
|
+
if @app.rpc_error_handler
|
54
|
+
@client.set_error_handler @app.rpc_error_handler
|
55
|
+
end
|
56
|
+
|
57
|
+
EM.next_tick { block_given? and yield }
|
58
|
+
end
|
59
|
+
|
60
|
+
# Component lifecycle callback
|
61
|
+
def after_start &block
|
62
|
+
@app.rpc = @client.proxies.user
|
63
|
+
@app.sysrpc = @client.proxies.sys
|
64
|
+
|
65
|
+
@app.define_singleton_method :rpc_invoke, proc{ |*args, &block|
|
66
|
+
@client.rpc_invoke *args, &block
|
67
|
+
}
|
68
|
+
|
69
|
+
@client.start &block
|
70
|
+
end
|
71
|
+
|
72
|
+
# Add remote servers
|
73
|
+
#
|
74
|
+
# @param [Array] servers
|
75
|
+
def add_servers servers
|
76
|
+
return unless servers
|
77
|
+
return if servers.empty
|
78
|
+
|
79
|
+
gen_proxies servers
|
80
|
+
|
81
|
+
@client.add_servers servers
|
82
|
+
end
|
83
|
+
|
84
|
+
# Remove remote servers
|
85
|
+
#
|
86
|
+
# @param [Array] ids
|
87
|
+
def remove_servers ids
|
88
|
+
@client.remove_servers ids
|
89
|
+
end
|
90
|
+
|
91
|
+
# Replace remote servers
|
92
|
+
#
|
93
|
+
# @param [Array] servers
|
94
|
+
def replace_servers servers
|
95
|
+
return unless servers
|
96
|
+
return if servers.empty
|
97
|
+
|
98
|
+
@client.proxies = {}
|
99
|
+
gen_proxies servers
|
100
|
+
|
101
|
+
@client.replace_servers servers
|
102
|
+
end
|
103
|
+
|
104
|
+
# Proxy for rpc client's rpc_invoke
|
105
|
+
#
|
106
|
+
# @param [String] server_id
|
107
|
+
# @param [Hash] msg
|
108
|
+
def rpc_invoke server_id, msg, &block
|
109
|
+
@client.rpc_invoke server_id, msg, &block
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
# Generate proxies for the server infos
|
115
|
+
#
|
116
|
+
# @param [Array] sinfos
|
117
|
+
#
|
118
|
+
# @private
|
119
|
+
def gen_proxies sinfos
|
120
|
+
sinfos.each { |sinfo|
|
121
|
+
@client.add_proxies get_proxy_records(sinfo) unless has_proxy? sinfo
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
# Check whether a proxy has been generated
|
126
|
+
#
|
127
|
+
# @param [Hash] sinfo
|
128
|
+
#
|
129
|
+
# @private
|
130
|
+
def has_proxy? sinfo
|
131
|
+
@client.proxies.sys && @client.proxies.sys.respond_to? sinfo[:server_type]
|
132
|
+
end
|
133
|
+
|
134
|
+
# Get proxy path for rpc client
|
135
|
+
#
|
136
|
+
# @param [Hash] sinfo
|
137
|
+
#
|
138
|
+
# @private
|
139
|
+
def get_proxy_records sinfo
|
140
|
+
records = []
|
141
|
+
|
142
|
+
role = @app.frontend? sinfo ? :frontend : :backend
|
143
|
+
server_type = sinfo[:server_type]
|
144
|
+
|
145
|
+
record = get_sys_remote_path role
|
146
|
+
records << remote_path_record('sys', server_type, record) if record
|
147
|
+
|
148
|
+
record = get_user_remote_path @app.base, server_type
|
149
|
+
records << remote_path_record('user', server_type, record) if record
|
150
|
+
|
151
|
+
records
|
152
|
+
end
|
153
|
+
|
154
|
+
# Generate router
|
155
|
+
#
|
156
|
+
# @private
|
157
|
+
def gen_router
|
158
|
+
Proc.new { |session, msg, &block|
|
159
|
+
routers = @app.routers
|
160
|
+
unless routers
|
161
|
+
default_router session, msg, &block
|
162
|
+
return
|
163
|
+
end
|
164
|
+
|
165
|
+
type = msg['server_type']
|
166
|
+
router = routers[type] || routers['default']
|
167
|
+
|
168
|
+
if router
|
169
|
+
router.call session, msg, &block
|
170
|
+
else
|
171
|
+
default_router session, msg, &block
|
172
|
+
end
|
173
|
+
}
|
174
|
+
end
|
175
|
+
|
176
|
+
# Default router
|
177
|
+
#
|
178
|
+
# @param [Object] session
|
179
|
+
# @param [Hash] msg
|
180
|
+
#
|
181
|
+
# @private
|
182
|
+
def default_router session, msg, &block
|
183
|
+
list = @app.get_servers_by_type msg['server_type']
|
184
|
+
unless list && !list.empty?
|
185
|
+
block_given? and yield Exception.new 'can not find server info for type: ' + msg['server_type']
|
186
|
+
return
|
187
|
+
end
|
188
|
+
|
189
|
+
uid = session ? (session.uid || '') : ''
|
190
|
+
idx = (Digest::CRC32.hexdigest uid).to_i % list.length
|
191
|
+
block_given? and yield nil, list[idx][:server_id]
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 17 July 2014
|
4
|
+
|
5
|
+
require 'citrus/components/component'
|
6
|
+
require 'citrus/push_schedulers/direct'
|
7
|
+
|
8
|
+
module Citrus
|
9
|
+
# Components
|
10
|
+
#
|
11
|
+
#
|
12
|
+
module Components
|
13
|
+
# PushScheduler
|
14
|
+
#
|
15
|
+
#
|
16
|
+
class PushScheduler < Component
|
17
|
+
@name = 'push_scheduler'
|
18
|
+
|
19
|
+
# Initialize the component
|
20
|
+
#
|
21
|
+
# @param [Object] app
|
22
|
+
# @param [Hash] args
|
23
|
+
def initialize app, args={}
|
24
|
+
@app = app
|
25
|
+
@scheduler = get_scheduler app, args
|
26
|
+
end
|
27
|
+
|
28
|
+
# Component lifecycle callback
|
29
|
+
def after_start &block
|
30
|
+
if @scheduler.respond_to? :start
|
31
|
+
@scheduler.start &block
|
32
|
+
else
|
33
|
+
EM.next_tick { block.call } if block_given?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Component lifecycle callback
|
38
|
+
def stop &block
|
39
|
+
if @scheduler.respond_to? :stop
|
40
|
+
@scheduler.stop &block
|
41
|
+
else
|
42
|
+
EM.next_tick { block.call } if block_given?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Schedule how the message to send
|
47
|
+
#
|
48
|
+
# @param [Integer] req_id
|
49
|
+
# @param [String] route
|
50
|
+
# @param [Hash] msg
|
51
|
+
# @param [Array] recvs
|
52
|
+
# @param [Hash] args
|
53
|
+
def schedule req_id, route, msg, recvs, args, &block
|
54
|
+
if @scheculer.respond_to? :schedule
|
55
|
+
@scheduler.schedule req_id, route, msg, recvs, args, &block
|
56
|
+
else
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
# Get scheduler
|
63
|
+
#
|
64
|
+
# @param [Object] app
|
65
|
+
# @param [Hash] args
|
66
|
+
#
|
67
|
+
# @private
|
68
|
+
def get_scheduler app, args={}
|
69
|
+
scheduler = args[:scheduler] || Citrus::PushSchedulers::Direct
|
70
|
+
scheduler.new app, args
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 17 July 2014
|
4
|
+
|
5
|
+
require 'citrus/components/component'
|
6
|
+
require 'citrus/util/path_util'
|
7
|
+
|
8
|
+
module Citrus
|
9
|
+
# Components
|
10
|
+
#
|
11
|
+
#
|
12
|
+
module Components
|
13
|
+
# Remote
|
14
|
+
#
|
15
|
+
#
|
16
|
+
class Remote < Component
|
17
|
+
@name = 'remote'
|
18
|
+
|
19
|
+
include Utils::PathUtil
|
20
|
+
|
21
|
+
# Initialize the component
|
22
|
+
#
|
23
|
+
# @param [Object] app
|
24
|
+
# @param [Hash] args
|
25
|
+
def initialize app, args={}
|
26
|
+
args[:buffer_msg] = args[:buffer_msg] || false
|
27
|
+
args[:interval] = args[:interval] || 0.03
|
28
|
+
@app = app
|
29
|
+
@args = args
|
30
|
+
end
|
31
|
+
|
32
|
+
# Start the component
|
33
|
+
def start &block
|
34
|
+
@args[:port] = @app.cur_server[:port]
|
35
|
+
@args[:paths] = get_remote_paths
|
36
|
+
@args[:context] = @app
|
37
|
+
|
38
|
+
@remote = CitrusRpc::RpcServer::Server.new @args
|
39
|
+
@remote.start
|
40
|
+
|
41
|
+
EM.next_tick { block_given? and yield }
|
42
|
+
end
|
43
|
+
|
44
|
+
# Stop the component
|
45
|
+
#
|
46
|
+
# @param [Boolean] force
|
47
|
+
def stop force=false, &block
|
48
|
+
@remote.stop force
|
49
|
+
EM.next_tick { block_given? and yield }
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
# Get remote paths
|
55
|
+
def get_remote_paths
|
56
|
+
paths = []
|
57
|
+
|
58
|
+
role = @app.frontend? sinfo ? :frontend : :backend
|
59
|
+
server_type = sinfo[:server_type]
|
60
|
+
|
61
|
+
sys_path = get_sys_remote_path role
|
62
|
+
paths << remote_path_record('sys', server_type, sys_path) if sys_path
|
63
|
+
|
64
|
+
user_path = get_user_remote_path @app.base, server_type
|
65
|
+
paths << remote_path_record('user', server_type, user_path) if user_path
|
66
|
+
|
67
|
+
paths
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 17 July 2014
|
4
|
+
|
5
|
+
require 'citrus/components/component'
|
6
|
+
require 'citrus/server/server'
|
7
|
+
|
8
|
+
module Citrus
|
9
|
+
# Components
|
10
|
+
#
|
11
|
+
#
|
12
|
+
module Components
|
13
|
+
# Server
|
14
|
+
#
|
15
|
+
#
|
16
|
+
class Server < Component
|
17
|
+
@name = 'server'
|
18
|
+
|
19
|
+
# Initialize the component
|
20
|
+
#
|
21
|
+
# @param [Object] app
|
22
|
+
def initialize app
|
23
|
+
@server = Citrus::Server::Server.new app
|
24
|
+
end
|
25
|
+
|
26
|
+
# Start the component
|
27
|
+
def start &block
|
28
|
+
@server.start
|
29
|
+
EM.next_tick { block_given? and yield }
|
30
|
+
end
|
31
|
+
|
32
|
+
# Component lifecycle callback
|
33
|
+
def after_start &block
|
34
|
+
@server.after_start
|
35
|
+
EM.next_tick { block_given? and yield }
|
36
|
+
end
|
37
|
+
|
38
|
+
# Stop the component
|
39
|
+
def stop force=false, &block
|
40
|
+
@server.stop
|
41
|
+
EM.next_tick { block_given? and yield }
|
42
|
+
end
|
43
|
+
|
44
|
+
# Proxy server handle
|
45
|
+
#
|
46
|
+
# @param [Hash] msg
|
47
|
+
# @param [Object] session
|
48
|
+
def handle msg, session, &block
|
49
|
+
@server.handle msg, session, &block
|
50
|
+
end
|
51
|
+
|
52
|
+
# Proxy server global handle
|
53
|
+
#
|
54
|
+
# @param [Hash] msg
|
55
|
+
# @param [Object] session
|
56
|
+
def global_handle msg, session, &block
|
57
|
+
@server.global_handle msg, session, &block
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 17 July 2014
|
4
|
+
|
5
|
+
require 'citrus/components/component'
|
6
|
+
require 'citrus/common/service/session_service'
|
7
|
+
|
8
|
+
module Citrus
|
9
|
+
# Components
|
10
|
+
#
|
11
|
+
#
|
12
|
+
module Components
|
13
|
+
# Session
|
14
|
+
#
|
15
|
+
#
|
16
|
+
class Session < Component
|
17
|
+
@name = 'session'
|
18
|
+
|
19
|
+
attr_reader :service
|
20
|
+
|
21
|
+
# Initialize the component
|
22
|
+
#
|
23
|
+
# @param [Object] app
|
24
|
+
# @param [Hash] args
|
25
|
+
def initialize app, args={}
|
26
|
+
@app = app
|
27
|
+
@service = Common::Service::SessionService.new args
|
28
|
+
|
29
|
+
this = self
|
30
|
+
@app.define_singleton_method :session_service, proc{ this }
|
31
|
+
end
|
32
|
+
|
33
|
+
# Proxy for connection service
|
34
|
+
#
|
35
|
+
# @param [String] name
|
36
|
+
def method_missing name, *args, &block
|
37
|
+
@service.send name, *args, &block
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
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
|
+
# HandShake
|
15
|
+
#
|
16
|
+
#
|
17
|
+
class HandShake
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|