pomelo-citrus-rpc 0.0.2
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-rpc.gemspec +32 -0
- data/example/client.rb +43 -0
- data/example/remote/test/service.rb +9 -0
- data/example/server.rb +20 -0
- data/lib/citrus-rpc.rb +16 -0
- data/lib/citrus-rpc/rpc-client/client.rb +328 -0
- data/lib/citrus-rpc/rpc-client/mailboxes/ws_mailbox.rb +164 -0
- data/lib/citrus-rpc/rpc-client/mailstation.rb +363 -0
- data/lib/citrus-rpc/rpc-client/proxy.rb +37 -0
- data/lib/citrus-rpc/rpc-client/router.rb +63 -0
- data/lib/citrus-rpc/rpc-server/acceptors/ws_acceptor.rb +143 -0
- data/lib/citrus-rpc/rpc-server/dispatcher.rb +36 -0
- data/lib/citrus-rpc/rpc-server/gateway.rb +58 -0
- data/lib/citrus-rpc/rpc-server/server.rb +92 -0
- data/lib/citrus-rpc/util/constants.rb +20 -0
- data/lib/citrus-rpc/util/utils.rb +42 -0
- data/lib/citrus-rpc/version.rb +7 -0
- data/spec/mock-remote/area/add_one_remote.rb +13 -0
- data/spec/mock-remote/area/add_three_remote.rb +9 -0
- data/spec/mock-remote/area/who_am_i_remote.rb +9 -0
- data/spec/mock-remote/connector/who_am_i_remote.rb +9 -0
- data/spec/rpc-client/client_spec.rb +166 -0
- data/spec/rpc-client/mailstaion_spec.rb +235 -0
- data/spec/rpc-client/proxy_spec.rb +8 -0
- data/spec/rpc-client/router_spec.rb +8 -0
- data/spec/rpc-client/ws_mailbox_spec.rb +144 -0
- data/spec/rpc-server/client/mock-tcp-client.rb +6 -0
- data/spec/rpc-server/client/mock-ws-client.rb +48 -0
- data/spec/rpc-server/dispatcher_spec.rb +88 -0
- data/spec/rpc-server/gateway_spec.rb +206 -0
- data/spec/rpc-server/server_spec.rb +79 -0
- data/spec/rpc-server/ws_acceptor_spec.rb +138 -0
- data/spec/spec_helper.rb +25 -0
- metadata +179 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 5 July 2014
|
4
|
+
|
5
|
+
module CitrusRpc
|
6
|
+
# Utils
|
7
|
+
#
|
8
|
+
#
|
9
|
+
module Utils
|
10
|
+
# EventEmitter
|
11
|
+
#
|
12
|
+
#
|
13
|
+
module EventEmitter
|
14
|
+
# Register event
|
15
|
+
#
|
16
|
+
# @param [String] event
|
17
|
+
def on event, &block
|
18
|
+
@on_blocks ||= {}
|
19
|
+
@on_blocks[event] = block
|
20
|
+
end
|
21
|
+
|
22
|
+
# Register event once
|
23
|
+
#
|
24
|
+
# @param [String] event
|
25
|
+
def once event, &block
|
26
|
+
@once_blocks ||= {}
|
27
|
+
@once_blocks[event] = block
|
28
|
+
end
|
29
|
+
|
30
|
+
# Emit event
|
31
|
+
def emit *args
|
32
|
+
event = args.shift
|
33
|
+
if @once_blocks && block = @once_blocks[event]
|
34
|
+
@once_blocks.delete event
|
35
|
+
elsif !@on_blocks || !block = @on_blocks[event]
|
36
|
+
return
|
37
|
+
end
|
38
|
+
block.call *args
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 5 July 2014
|
4
|
+
|
5
|
+
class AddOneRemote < Citrus::AppRemote
|
6
|
+
def do value, &block
|
7
|
+
block.call nil, value + 1
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_two value, &block
|
11
|
+
block.call nil, value + 2
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 5 July 2014
|
4
|
+
|
5
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
6
|
+
|
7
|
+
describe Client do
|
8
|
+
|
9
|
+
dirname = File.expand_path File.dirname(__FILE__)
|
10
|
+
records = [
|
11
|
+
{ :namespace => 'user', :server_type => 'area', :path => dirname + '/../mock-remote/area' },
|
12
|
+
{ :namespace => 'sys', :server_type => 'connector', :path => dirname + '/../mock-remote/connector' }
|
13
|
+
]
|
14
|
+
|
15
|
+
server_list = [
|
16
|
+
{ :id => 'area-server-1', :server_type => 'area', :host => '127.0.0.1', :port => 3333 },
|
17
|
+
{ :id => 'connector-server-1', :server_type => 'connector', :host => '127.0.0.1', :port => 4444 },
|
18
|
+
{ :id => 'connector-server-2', :server_type => 'connector', :host => '127.0.0.1', :port => 5555 }
|
19
|
+
]
|
20
|
+
|
21
|
+
describe '#create' do
|
22
|
+
it 'should be ok when created with empty options' do
|
23
|
+
client = Client.new
|
24
|
+
expect(client).to be_an_instance_of Client
|
25
|
+
|
26
|
+
EM.run {
|
27
|
+
client.start { |err|
|
28
|
+
expect(err).to be_nil
|
29
|
+
client.stop true
|
30
|
+
}
|
31
|
+
|
32
|
+
EM.add_timer(0.1) { EM.stop_event_loop }
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should add proxies by add_proxies method' do
|
37
|
+
client = Client.new
|
38
|
+
expect(client).to be_an_instance_of Client
|
39
|
+
|
40
|
+
client.add_proxies records
|
41
|
+
records.each { |record|
|
42
|
+
namespace = record[:namespace]
|
43
|
+
server_type = record[:server_type]
|
44
|
+
expect(client.proxies).to respond_to namespace
|
45
|
+
expect(client.proxies[namespace]).to respond_to server_type
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should replace the default router when created by passing router argument' do
|
50
|
+
route_count = 0
|
51
|
+
callback_count = 0
|
52
|
+
|
53
|
+
server = server_list[1]
|
54
|
+
server_id = server[:id]
|
55
|
+
|
56
|
+
router = Proc.new do |route_param, msg, route_context, &block|
|
57
|
+
route_count = route_count + 1
|
58
|
+
block.call nil, server_id
|
59
|
+
end
|
60
|
+
|
61
|
+
EM.run {
|
62
|
+
server_list.each { |server|
|
63
|
+
Server.new( :records => records, :port => server[:port],
|
64
|
+
:context => { :server_id => server[:id] }).start
|
65
|
+
}
|
66
|
+
|
67
|
+
client = Client.new :router => router
|
68
|
+
client.add_proxies records
|
69
|
+
client.add_server server
|
70
|
+
|
71
|
+
client.start { |err|
|
72
|
+
expect(err).to be_nil
|
73
|
+
|
74
|
+
client.proxies.sys.connector.whoAmIRemote.do(nil) { |err, sid|
|
75
|
+
callback_count = callback_count + 1
|
76
|
+
expect(sid).to eq server_id
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
EM.add_timer(0.1) {
|
81
|
+
expect(route_count).to eq 1
|
82
|
+
expect(callback_count).to eq 1
|
83
|
+
EM.stop_event_loop
|
84
|
+
}
|
85
|
+
}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '#status' do
|
90
|
+
it 'should return an error if started twice' do
|
91
|
+
client = Client.new
|
92
|
+
EM.run {
|
93
|
+
client.start { |err|
|
94
|
+
expect(err).to be_nil
|
95
|
+
client.start { |err|
|
96
|
+
expect(err).to be
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
EM.add_timer(0.1) { EM.stop_event_loop }
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should ignore the later operation if stopped twice' do
|
105
|
+
client = Client.new
|
106
|
+
EM.run {
|
107
|
+
client.start { |err|
|
108
|
+
expect(err).to be_nil
|
109
|
+
client.stop
|
110
|
+
client.stop
|
111
|
+
}
|
112
|
+
|
113
|
+
EM.add_timer(0.1) { EM.stop_event_loop }
|
114
|
+
}
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should return an error when doing rpc invoke with the client not started' do
|
118
|
+
client = Client.new
|
119
|
+
EM.run {
|
120
|
+
client.rpc_invoke(server_list[0][:id], '') { |err|
|
121
|
+
expect(err).to be
|
122
|
+
}
|
123
|
+
|
124
|
+
EM.add_timer(0.1) { EM.stop_event_loop }
|
125
|
+
}
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should return an error when doing rpc invoke after the client stopped' do
|
129
|
+
server_id = server_list[0][:id]
|
130
|
+
|
131
|
+
client = Client.new
|
132
|
+
client.add_server server_list[0]
|
133
|
+
|
134
|
+
EM.run {
|
135
|
+
server_list.each { |server|
|
136
|
+
Server.new( :records => records, :port => server[:port],
|
137
|
+
:context => { :server_id => server[:id] }).start
|
138
|
+
}
|
139
|
+
|
140
|
+
msg = {
|
141
|
+
'namespace' => 'user',
|
142
|
+
'server_type' => 'area',
|
143
|
+
'service' => 'whoAmIAreaRemote',
|
144
|
+
'method' => 'do',
|
145
|
+
'args' => []
|
146
|
+
};
|
147
|
+
|
148
|
+
client.start { |err|
|
149
|
+
expect(err).to be_nil
|
150
|
+
|
151
|
+
client.rpc_invoke(server_id, msg) { |err|
|
152
|
+
expect(err).to be_nil
|
153
|
+
client.stop true
|
154
|
+
EM.add_timer(0.1) {
|
155
|
+
client.rpc_invoke(server_id, msg) { |err|
|
156
|
+
expect(err).to be
|
157
|
+
}
|
158
|
+
}
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
162
|
+
EM.add_timer(0.2) { EM.stop_event_loop }
|
163
|
+
}
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,235 @@
|
|
1
|
+
# Author:: MinixLi (gmail: MinixLi1986)
|
2
|
+
# Homepage:: http://citrus.inspawn.com
|
3
|
+
# Date:: 5 July 2014
|
4
|
+
|
5
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
6
|
+
|
7
|
+
describe MailStation do
|
8
|
+
|
9
|
+
dirname = File.expand_path File.dirname(__FILE__)
|
10
|
+
records = [
|
11
|
+
{ :namespace => 'user', :server_type => 'area', :path => dirname + '/../mock-remote/area' },
|
12
|
+
{ :namespace => 'sys', :server_type => 'connector', :path => dirname + '/../mock-remote/connector' }
|
13
|
+
]
|
14
|
+
|
15
|
+
server_list = [
|
16
|
+
{ :id => 'area-server-1', :server_type => 'area', :host => '127.0.0.1', :port => 3333 },
|
17
|
+
{ :id => 'connector-server-1', :server_type => 'connector', :host => '127.0.0.1', :port => 4444 },
|
18
|
+
{ :id => 'connector-server-2', :server_type => 'connector', :host => '127.0.0.1', :port => 5555 }
|
19
|
+
]
|
20
|
+
|
21
|
+
msg = {
|
22
|
+
'namespace' => 'user',
|
23
|
+
'server_type' => 'area',
|
24
|
+
'service' => 'whoAmIAreaRemote',
|
25
|
+
'method' => 'do',
|
26
|
+
'args' => []
|
27
|
+
}
|
28
|
+
|
29
|
+
describe '#create' do
|
30
|
+
it 'should be ok when created with empty options' do
|
31
|
+
EM.run {
|
32
|
+
station = MailStation.new
|
33
|
+
expect(station).to be
|
34
|
+
|
35
|
+
station.start { |err|
|
36
|
+
expect(err).to be_nil
|
37
|
+
EM.stop_event_loop
|
38
|
+
}
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should change the default mailbox class by passing mailbox class argument' do
|
43
|
+
MockMailBox = Class.new
|
44
|
+
|
45
|
+
station = MailStation.new :mailbox_class => MockMailBox
|
46
|
+
expect(station).to be
|
47
|
+
expect(station.mailbox_class).to eql MockMailBox
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#add server' do
|
52
|
+
it 'should add server info into the mail station' do
|
53
|
+
station = MailStation.new
|
54
|
+
expect(station).to be
|
55
|
+
|
56
|
+
server_list.each { |server|
|
57
|
+
station.add_server server
|
58
|
+
}
|
59
|
+
|
60
|
+
servers = station.servers
|
61
|
+
server_list.each { |item|
|
62
|
+
server = servers[item[:id]]
|
63
|
+
expect(server).to be
|
64
|
+
expect(server).to eql item
|
65
|
+
}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe '#dispatch' do
|
70
|
+
it 'should send the request to the right remote server and get the response from callback' do
|
71
|
+
callback_count = 0
|
72
|
+
count = 0
|
73
|
+
|
74
|
+
station = MailStation.new
|
75
|
+
expect(station).to be
|
76
|
+
|
77
|
+
server_list.each { |server|
|
78
|
+
station.add_server server
|
79
|
+
}
|
80
|
+
|
81
|
+
EM.run do
|
82
|
+
server_list.each { |server|
|
83
|
+
Server.new(
|
84
|
+
:records => records,
|
85
|
+
:port => server[:port],
|
86
|
+
:context => { :server_id => server[:id] }
|
87
|
+
).start
|
88
|
+
}
|
89
|
+
|
90
|
+
func = Proc.new { |server_id|
|
91
|
+
Proc.new { |err, remote_id|
|
92
|
+
expect(remote_id).to be
|
93
|
+
expect(remote_id).to eql server_id
|
94
|
+
callback_count = callback_count + 1
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
station.start { |err|
|
99
|
+
server_list.each { |server|
|
100
|
+
count = count + 1
|
101
|
+
station.dispatch server[:id], msg, nil, func.call(server[:id])
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
EM.add_timer(0.1) {
|
106
|
+
expect(callback_count).to eql count
|
107
|
+
EM.stop_event_loop
|
108
|
+
}
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should update the mailbox map by add server after start' do
|
113
|
+
callback_count = 0
|
114
|
+
count = 0
|
115
|
+
|
116
|
+
station = MailStation.new
|
117
|
+
expect(station).to be
|
118
|
+
|
119
|
+
server_list.each { |server|
|
120
|
+
station.add_server server
|
121
|
+
}
|
122
|
+
|
123
|
+
EM.run {
|
124
|
+
server_list.each { |server|
|
125
|
+
Server.new(
|
126
|
+
:records => records,
|
127
|
+
:port => server[:port],
|
128
|
+
:context => { :server_id => server[:id] }
|
129
|
+
).start
|
130
|
+
}
|
131
|
+
|
132
|
+
server = server_list[0]
|
133
|
+
|
134
|
+
block = Proc.new { |err, remote_id|
|
135
|
+
expect(remote_id).to be
|
136
|
+
expect(remote_id).to eql server[:id]
|
137
|
+
callback_count = callback_count + 1
|
138
|
+
}
|
139
|
+
|
140
|
+
station.start { |err|
|
141
|
+
station.add_server server
|
142
|
+
station.dispatch server[:id], msg, nil, block
|
143
|
+
}
|
144
|
+
|
145
|
+
EM.add_timer(0.1) {
|
146
|
+
expect(callback_count).to eql 1
|
147
|
+
EM.stop_event_loop
|
148
|
+
}
|
149
|
+
}
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe '#close' do
|
154
|
+
it 'should emit a close event for each mailbox close' do
|
155
|
+
close_event_count = 0
|
156
|
+
|
157
|
+
server_ids = []
|
158
|
+
mailbox_ids = []
|
159
|
+
|
160
|
+
station = MailStation.new
|
161
|
+
expect(station).to be
|
162
|
+
|
163
|
+
EM.run {
|
164
|
+
server_list.each { |server|
|
165
|
+
Server.new(
|
166
|
+
:records => records,
|
167
|
+
:port => server[:port],
|
168
|
+
:context => { :server_id => server[:id] }
|
169
|
+
).start
|
170
|
+
|
171
|
+
station.add_server server
|
172
|
+
|
173
|
+
server_ids << server[:id]
|
174
|
+
}
|
175
|
+
|
176
|
+
server_ids.sort
|
177
|
+
|
178
|
+
func = Proc.new { |server_id|
|
179
|
+
Proc.new { |err, remote_id|
|
180
|
+
expect(remote_id).to be
|
181
|
+
expect(remote_id).to eql server_id
|
182
|
+
}
|
183
|
+
}
|
184
|
+
|
185
|
+
station.start { |err|
|
186
|
+
server_list.each { |server|
|
187
|
+
station.dispatch server[:id], msg, nil, func.call(server[:id])
|
188
|
+
}
|
189
|
+
station.on(:close) { |mailbox_id|
|
190
|
+
mailbox_ids << mailbox_id
|
191
|
+
close_event_count = close_event_count + 1
|
192
|
+
}
|
193
|
+
}
|
194
|
+
|
195
|
+
EM.add_timer(0.1) {
|
196
|
+
station.stop true
|
197
|
+
EM.add_timer(0.1) {
|
198
|
+
expect(close_event_count).to eql server_ids.length
|
199
|
+
mailbox_ids.sort
|
200
|
+
expect(mailbox_ids).to eql server_ids
|
201
|
+
EM.stop_event_loop
|
202
|
+
}
|
203
|
+
}
|
204
|
+
}
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'should return an error when trying to dispatch message with a closed station' do
|
208
|
+
error_count = 0
|
209
|
+
|
210
|
+
station = MailStation.new
|
211
|
+
expect(station).to be
|
212
|
+
|
213
|
+
server_list.each { |server|
|
214
|
+
station.add_server server
|
215
|
+
}
|
216
|
+
|
217
|
+
EM.run do
|
218
|
+
station.start { |err|
|
219
|
+
station.stop
|
220
|
+
server_list.each { |server|
|
221
|
+
station.dispatch server[:id], msg, nil, proc{ |err, remote_id|
|
222
|
+
expect(err).to be
|
223
|
+
error_count = error_count + 1
|
224
|
+
}
|
225
|
+
}
|
226
|
+
}
|
227
|
+
|
228
|
+
EM.add_timer(0.1) {
|
229
|
+
expect(error_count).to eql server_list.length
|
230
|
+
EM.stop_event_loop
|
231
|
+
}
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|