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.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +20 -0
  3. data/Rakefile +0 -0
  4. data/citrus.gemspec +35 -0
  5. data/lib/citrus.rb +18 -0
  6. data/lib/citrus/application.rb +237 -0
  7. data/lib/citrus/citrus.rb +27 -0
  8. data/lib/citrus/common/remote/backend/msg_remote.rb +57 -0
  9. data/lib/citrus/common/remote/frontend/channel_remote.rb +73 -0
  10. data/lib/citrus/common/remote/frontend/session_remote.rb +108 -0
  11. data/lib/citrus/common/service/backend_session_service.rb +265 -0
  12. data/lib/citrus/common/service/channel_service.rb +485 -0
  13. data/lib/citrus/common/service/connection_service.rb +71 -0
  14. data/lib/citrus/common/service/filter_service.rb +92 -0
  15. data/lib/citrus/common/service/handler_service.rb +63 -0
  16. data/lib/citrus/common/service/session_service.rb +446 -0
  17. data/lib/citrus/components/backend_session.rb +32 -0
  18. data/lib/citrus/components/channel.rb +33 -0
  19. data/lib/citrus/components/component.rb +19 -0
  20. data/lib/citrus/components/connection.rb +48 -0
  21. data/lib/citrus/components/connector.rb +265 -0
  22. data/lib/citrus/components/master.rb +40 -0
  23. data/lib/citrus/components/monitor.rb +48 -0
  24. data/lib/citrus/components/proxy.rb +195 -0
  25. data/lib/citrus/components/push_scheduler.rb +74 -0
  26. data/lib/citrus/components/remote.rb +71 -0
  27. data/lib/citrus/components/server.rb +61 -0
  28. data/lib/citrus/components/session.rb +41 -0
  29. data/lib/citrus/connectors/commands/handshake.rb +22 -0
  30. data/lib/citrus/connectors/commands/heartbeat.rb +22 -0
  31. data/lib/citrus/connectors/commands/kick.rb +22 -0
  32. data/lib/citrus/connectors/common/coder.rb +21 -0
  33. data/lib/citrus/connectors/common/handler.rb +21 -0
  34. data/lib/citrus/connectors/ws_connector.rb +110 -0
  35. data/lib/citrus/connectors/ws_socket.rb +75 -0
  36. data/lib/citrus/filters/handler/handler_filter.rb +19 -0
  37. data/lib/citrus/filters/handler/too_busy.rb +16 -0
  38. data/lib/citrus/filters/rpc/rpc_filter.rb +19 -0
  39. data/lib/citrus/filters/rpc/too_busy.rb +16 -0
  40. data/lib/citrus/master/master.rb +60 -0
  41. data/lib/citrus/master/starter.rb +73 -0
  42. data/lib/citrus/master/watchdog.rb +83 -0
  43. data/lib/citrus/modules/console.rb +45 -0
  44. data/lib/citrus/modules/console_module.rb +35 -0
  45. data/lib/citrus/modules/master_watcher.rb +88 -0
  46. data/lib/citrus/modules/monitor_watcher.rb +86 -0
  47. data/lib/citrus/monitor/monitor.rb +61 -0
  48. data/lib/citrus/push_schedulers/buffer.rb +16 -0
  49. data/lib/citrus/push_schedulers/direct.rb +76 -0
  50. data/lib/citrus/server/server.rb +327 -0
  51. data/lib/citrus/util/app_util.rb +203 -0
  52. data/lib/citrus/util/constants.rb +19 -0
  53. data/lib/citrus/util/countdown_latch.rb +42 -0
  54. data/lib/citrus/util/events.rb +14 -0
  55. data/lib/citrus/util/module_util.rb +68 -0
  56. data/lib/citrus/util/path_util.rb +50 -0
  57. data/lib/citrus/util/utils.rb +49 -0
  58. data/lib/citrus/version.rb +7 -0
  59. 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