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,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
|