smartfox_jruby 0.2.1-java → 0.2.2-java
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.
- data/Doubleshot +15 -9
- data/lib/smartfox_jruby/common.rb +25 -22
- data/lib/smartfox_jruby/sfs_adapter.rb +137 -135
- data/lib/smartfox_jruby/sfs_runner.rb +91 -88
- data/lib/smartfox_jruby/sfs_worker.rb +199 -197
- data/lib/smartfox_jruby.rb +5 -4
- metadata +2 -5
data/Doubleshot
CHANGED
@@ -1,21 +1,27 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require 'pathname'
|
3
|
-
require
|
3
|
+
require File.join(File.dirname(File.expand_path(__FILE__)),"lib", "smartfox_jruby")
|
4
|
+
|
4
5
|
Doubleshot.new do |config|
|
5
6
|
|
6
7
|
config.project = "smartfox_jruby"
|
7
8
|
config.version = SmartfoxJruby::VERSION
|
8
9
|
|
9
|
-
config.
|
10
|
-
config.gem 'json'
|
11
|
-
config.gem 'rspec', '~> 2.10.0'
|
12
|
-
|
13
|
-
config.mvn_repository 'http://repo1.maven.org/maven2'
|
14
|
-
config.mvn_repository 'http://artifactory-innovations.i-free.ru/artifactory/ext-release-local'
|
15
|
-
|
10
|
+
config.mvn_repository 'http://maven.smecsia.me/'
|
16
11
|
config.jar 'com.smartfox2x.client:sfs2x-client-core:jar:1.0.4'
|
17
12
|
config.jar 'com.smartfox2x.client:sfs2x-api-java:jar:1.0.4'
|
18
13
|
config.jar 'org.slf4j:slf4j-log4j12:jar:1.5.10'
|
14
|
+
config.jar 'io.netty:netty:jar:3.5.3.Final'
|
15
|
+
config.jar 'commons-beanutils:commons-beanutils:jar:1.7.0'
|
16
|
+
config.jar 'net.sf.ezmorph:ezmorph:jar:1.0.6'
|
17
|
+
config.jar 'net.sf.json-lib:json-lib:jar:jdk5:2.2.3'
|
18
|
+
config.jar 'commons-lang:commons-lang:jar:2.5'
|
19
|
+
config.jar 'commons-collections:commons-collections:jar:3.2.1'
|
20
|
+
config.jar 'commons-logging:commons-logging:jar:1.1.1'
|
21
|
+
|
22
|
+
config.gem 'activesupport', '~> 3.2.8'
|
23
|
+
config.gem 'json'
|
24
|
+
config.gem 'rspec', '~> 2.10.0'
|
19
25
|
|
20
26
|
config.gemspec do |spec|
|
21
27
|
spec.summary = "Smartfox client for jruby"
|
@@ -29,4 +35,4 @@ Doubleshot.new do |config|
|
|
29
35
|
spec.license = "Apache 2.0"
|
30
36
|
end
|
31
37
|
|
32
|
-
end
|
38
|
+
end
|
@@ -20,35 +20,38 @@ module ISFSObject
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
module SmartfoxJruby
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
23
|
+
module SmartfoxJruby
|
24
|
+
module SFSUtil
|
25
|
+
class << self
|
26
|
+
def boxing(v, type)
|
27
|
+
case type
|
28
|
+
when :long
|
29
|
+
java.lang.Long.valueOf(v)
|
30
|
+
when :float
|
31
|
+
java.lang.Float.valueOf(v)
|
32
|
+
when :double
|
33
|
+
java.lang.Double.valueOf(v)
|
34
|
+
when :int
|
35
|
+
java.lang.Integer.valueOf(v)
|
36
|
+
when :boolean
|
37
|
+
java.lang.Boolean.valueOf(v)
|
38
|
+
else
|
39
|
+
v
|
40
|
+
end
|
39
41
|
end
|
40
|
-
end
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
def to_java_list(value, type)
|
44
|
+
list = java.util.ArrayList.new
|
45
|
+
value.to_java(type).each do |v|
|
46
|
+
list.add(boxing(v, type))
|
47
|
+
end
|
48
|
+
list
|
46
49
|
end
|
47
|
-
list
|
48
50
|
end
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
54
|
+
|
52
55
|
def SFSObject.from_hash(hash, opts = {})
|
53
56
|
res = SFSObject.new
|
54
57
|
opts ||= {}
|
@@ -1,172 +1,174 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/sfs_worker')
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
3
|
+
module SmartfoxJruby
|
4
|
+
|
5
|
+
class SfsAdapter
|
6
|
+
include IEventListener
|
7
|
+
attr_reader :opts
|
8
|
+
attr_reader :smart_fox
|
9
|
+
attr_reader :worker
|
10
|
+
attr_reader :username
|
11
|
+
DEBUG = false
|
12
|
+
|
13
|
+
def initialize(opts = {})
|
14
|
+
@opts = opts
|
15
|
+
@smart_fox = SmartFox.new(false)
|
16
|
+
@connected = false
|
17
|
+
@worker = opts[:worker]
|
18
|
+
@login_as = opts[:login_as] || {}
|
19
|
+
@opts[:timeout] ||= 20
|
20
|
+
@opts[:logger] ||= Logger.new(STDOUT)
|
21
|
+
SFSEvent.constants.each do |evt|
|
22
|
+
evt_value = SFSEvent.const_get(evt)
|
23
|
+
debug "Registering event adapter to self for event '#{evt}' --> '#{evt_value}'..."
|
24
|
+
smart_fox.add_event_listener(evt_value, self)
|
25
|
+
end
|
26
|
+
debug "initializing sfs adapter..."
|
24
27
|
end
|
25
|
-
end
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
def connect!(opt = {})
|
30
|
+
opts.reverse_merge!(opt)
|
31
|
+
raise "host and port are required to connect SfsAdapter!" if opts[:host].blank? || opts[:port].blank?
|
32
|
+
debug "connecting to smartfox at #{opts[:host]}:#{opts[:port]} ..."
|
33
|
+
smart_fox.connect(opts[:host], opts[:port])
|
34
|
+
end
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
def dispatch(event)
|
37
|
+
debug "got event #{event.type}: #{event}"
|
38
|
+
callback = "on_#{event.type.try(:underscore)}_event"
|
39
|
+
if respond_to?(callback, true)
|
40
|
+
send(callback, event)
|
41
|
+
else
|
42
|
+
debug "Unknown event caught #{event.type} (No method '#{callback}' in #{self})"
|
43
|
+
end
|
41
44
|
end
|
42
|
-
end
|
43
45
|
|
44
|
-
|
45
|
-
|
46
|
-
|
46
|
+
def disconnect!
|
47
|
+
smart_fox.disconnect
|
48
|
+
end
|
47
49
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
50
|
+
def process!(wrk = nil, &block)
|
51
|
+
wait_with_timeout(@opts[:timeout]) { connected? }
|
52
|
+
@worker = wrk || opts[:worker]
|
53
|
+
if block_given? && connected?
|
54
|
+
instance_eval(&block)
|
55
|
+
else
|
56
|
+
raise "Worker is null!" if @worker.blank?
|
57
|
+
raise "Not connected!" unless connected?
|
58
|
+
end
|
59
|
+
worker.perform!
|
56
60
|
end
|
57
|
-
worker.perform!
|
58
|
-
end
|
59
61
|
|
60
|
-
|
61
|
-
|
62
|
-
|
62
|
+
def connected?
|
63
|
+
@connected
|
64
|
+
end
|
63
65
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
66
|
+
def on_connect(&block)
|
67
|
+
@on_connect ||= []
|
68
|
+
@on_connect << block if block_given?
|
69
|
+
end
|
68
70
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
71
|
+
def on_login(&block)
|
72
|
+
@on_login ||= []
|
73
|
+
@on_login << block if block_given?
|
74
|
+
end
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
76
|
+
def login_as(username, password, params = {})
|
77
|
+
params = params.to_sfsobject if params.is_a?(Hash)
|
78
|
+
@login_as = {:username => username, :password => password, :params => params}
|
79
|
+
end
|
78
80
|
|
79
|
-
|
81
|
+
private
|
80
82
|
|
81
|
-
|
82
|
-
|
83
|
+
###############
|
84
|
+
### HELPERS ###
|
83
85
|
|
84
|
-
|
85
|
-
|
86
|
-
|
86
|
+
def request(*args)
|
87
|
+
worker.request(*args)
|
88
|
+
end
|
87
89
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
90
|
+
def worker(opts = {})
|
91
|
+
@worker ||= SfsWorker::Worker.new(@smart_fox, opts)
|
92
|
+
@worker
|
93
|
+
end
|
92
94
|
|
93
|
-
|
94
|
-
|
95
|
-
|
95
|
+
def sfs_send(req)
|
96
|
+
smart_fox.send(req)
|
97
|
+
end
|
96
98
|
|
97
|
-
|
98
|
-
|
99
|
+
#########################
|
100
|
+
### EVENTS PROCESSORS ###
|
99
101
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
102
|
+
def on_extension_response_event(event)
|
103
|
+
debug "extension_response #{event.arguments.get("cmd")}"
|
104
|
+
@worker.response(event.arguments.get("cmd"), event.arguments.get("params").try(:to_hash) || {}) unless @worker.blank?
|
105
|
+
end
|
104
106
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
107
|
+
def on_connection_event(event)
|
108
|
+
debug "on_connection #{event}"
|
109
|
+
@on_connect.each { |block|
|
110
|
+
block.call(event) if block.is_a?(Proc)
|
111
|
+
} unless @on_connect.blank?
|
112
|
+
sfs_send(LoginRequest.new(@login_as[:username], @login_as[:password], opts[:zone],
|
113
|
+
(@login_as[:params] || {}.to_sfsobject)));
|
114
|
+
end
|
113
115
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
116
|
+
def on_login_event(event)
|
117
|
+
args = event.arguments.get("data").to_hash
|
118
|
+
user = event.arguments.get("user")
|
119
|
+
debug("on_login, args=#{args.to_json}")
|
120
|
+
unless user.blank?
|
121
|
+
info "connected as #{user.name}"
|
122
|
+
@username = user.name
|
123
|
+
@connected = true
|
124
|
+
@on_login.each { |block|
|
125
|
+
block.call(@username) if block.is_a?(Proc)
|
126
|
+
} unless @on_login.blank?
|
127
|
+
else
|
128
|
+
raise "login error '#{args[Aimy::Param.ERROR_MESSAGE]}'"
|
129
|
+
end
|
127
130
|
end
|
128
|
-
end
|
129
131
|
|
130
|
-
|
131
|
-
|
132
|
-
|
132
|
+
def on_login_error_event(event)
|
133
|
+
error("error while logging-in: #{event.arguments}")
|
134
|
+
end
|
133
135
|
|
134
|
-
|
135
|
-
|
136
|
-
|
136
|
+
def on_connection_lost_event(event)
|
137
|
+
# nothing to do
|
138
|
+
end
|
137
139
|
|
138
|
-
|
139
|
-
|
140
|
-
|
140
|
+
def on_handshake_event(event)
|
141
|
+
# nothing to do
|
142
|
+
end
|
141
143
|
|
142
144
|
|
143
|
-
|
144
|
-
|
145
|
+
#######################
|
146
|
+
### SERVICE HELPERS ###
|
145
147
|
|
146
|
-
|
147
|
-
|
148
|
-
|
148
|
+
def logger
|
149
|
+
opts[:logger]
|
150
|
+
end
|
149
151
|
|
150
|
-
|
151
|
-
|
152
|
-
|
152
|
+
def debug_enabled?
|
153
|
+
opts[:debug] || DEBUG
|
154
|
+
end
|
153
155
|
|
154
|
-
|
155
|
-
|
156
|
-
|
156
|
+
def debug(msg)
|
157
|
+
logger.debug "#{msg}" if debug_enabled?
|
158
|
+
end
|
157
159
|
|
158
|
-
|
159
|
-
|
160
|
-
|
160
|
+
def info(msg)
|
161
|
+
logger.info "#{msg}"
|
162
|
+
end
|
161
163
|
|
162
|
-
|
163
|
-
|
164
|
-
|
164
|
+
def log(msg)
|
165
|
+
logger.info "#{msg}"
|
166
|
+
end
|
165
167
|
|
166
|
-
|
167
|
-
|
168
|
-
|
168
|
+
def error(msg)
|
169
|
+
logger.error "#{msg}"
|
170
|
+
end
|
169
171
|
|
172
|
+
end
|
170
173
|
|
171
174
|
end
|
172
|
-
|
@@ -3,120 +3,123 @@ require File.expand_path(File.dirname(__FILE__) + '/common')
|
|
3
3
|
java_import java.lang.Runtime
|
4
4
|
java_import java.lang.System
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
6
|
+
module SmartfoxJruby
|
7
|
+
class SfsRunner
|
8
|
+
|
9
|
+
def initialize(home_dir, opts = {})
|
10
|
+
@home_dir = home_dir
|
11
|
+
@opts = opts
|
12
|
+
@launched = false
|
13
|
+
@fault = false
|
14
|
+
@pid = nil
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
17
|
+
def run!
|
18
|
+
Thread.new do
|
19
|
+
begin
|
20
|
+
info "Changing dir to #{work_dir}"
|
21
|
+
Dir.chdir(work_dir) do
|
22
|
+
info "Running cmd #{cmd}"
|
23
|
+
IO.popen(cmd) do |output|
|
24
|
+
@pid = output.pid
|
25
|
+
info "Running child with pid=#{output.pid}..."
|
26
|
+
output.each do |line|
|
27
|
+
debug(line.gsub(/\n/, ""))
|
28
|
+
@launched = true if line =~ /SmartFoxServer 2X \(.+\) READY!/
|
29
|
+
end
|
28
30
|
end
|
31
|
+
@fault = true
|
29
32
|
end
|
30
|
-
|
33
|
+
rescue Exception => e
|
34
|
+
error "#{e}"
|
31
35
|
end
|
32
|
-
rescue Exception => e
|
33
|
-
error "#{e}"
|
34
36
|
end
|
35
37
|
end
|
36
|
-
end
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
39
|
+
def kill!
|
40
|
+
info "Checking running processes: #{pids.join(",")}"
|
41
|
+
pids.each { |pid|
|
42
|
+
pid = pid.try(:strip).try(:to_i)
|
43
|
+
info "Killing the process with pid=#{pid}..."
|
44
|
+
Process.kill("KILL", pid) if Process.alive?(pid)
|
45
|
+
wait_with_timeout(5) { !Process.alive?(pid) } rescue ""
|
46
|
+
}
|
47
|
+
end
|
47
48
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
49
|
+
def run_and_wait!(opts = {})
|
50
|
+
run!
|
51
|
+
wait_until_launched_or_fault(opts[:timeout])
|
52
|
+
end
|
52
53
|
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
55
|
+
def kill_and_wait!(opts = {})
|
56
|
+
kill!
|
57
|
+
wait_until_terminated(opts[:timeout])
|
58
|
+
end
|
58
59
|
|
59
|
-
|
60
|
-
|
61
|
-
|
60
|
+
def running?
|
61
|
+
!pids.blank? && pids.map { |pid| Process.alive?(pid.to_i) }.include?(true)
|
62
|
+
end
|
62
63
|
|
63
|
-
|
64
|
-
|
65
|
-
|
64
|
+
def launched?
|
65
|
+
@launched
|
66
|
+
end
|
66
67
|
|
67
|
-
|
68
|
-
|
69
|
-
|
68
|
+
def fault?
|
69
|
+
@fault
|
70
|
+
end
|
70
71
|
|
71
|
-
|
72
|
-
|
73
|
-
|
72
|
+
def wait_until_terminated(timeout = nil)
|
73
|
+
wait_with_timeout(timeout) { !running? }
|
74
|
+
end
|
74
75
|
|
75
|
-
|
76
|
-
|
77
|
-
|
76
|
+
def wait_until_launched_or_fault(timeout = nil)
|
77
|
+
wait_with_timeout(timeout) { launched? or fault? }
|
78
|
+
end
|
78
79
|
|
79
|
-
|
80
|
+
private
|
80
81
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
82
|
+
def pids
|
83
|
+
pids_out = `pgrep -f "#{work_dir}"`
|
84
|
+
(pids_out.try(:split, "\n")) || []
|
85
|
+
end
|
85
86
|
|
86
|
-
|
87
|
-
|
88
|
-
|
87
|
+
def error(msg)
|
88
|
+
@opts[:logger].error(msg) unless @opts[:logger].blank?
|
89
|
+
end
|
89
90
|
|
90
|
-
|
91
|
-
|
92
|
-
|
91
|
+
def debug(msg)
|
92
|
+
@opts[:logger].debug(msg) unless @opts[:logger].blank?
|
93
|
+
end
|
93
94
|
|
94
|
-
|
95
|
-
|
96
|
-
|
95
|
+
def info(msg)
|
96
|
+
@opts[:logger].info(msg) unless @opts[:logger].blank?
|
97
|
+
end
|
97
98
|
|
98
|
-
|
99
|
-
|
100
|
-
|
99
|
+
def work_dir
|
100
|
+
Pathname.new(@home_dir).join("SFS2X").to_s
|
101
|
+
end
|
101
102
|
|
102
|
-
|
103
|
-
|
104
|
-
|
103
|
+
def env
|
104
|
+
%W[].to_java :string
|
105
|
+
end
|
105
106
|
|
106
|
-
|
107
|
-
|
108
|
-
|
107
|
+
def cmd
|
108
|
+
%Q[#{java_bin} -cp #{classpath} #{java_opts} -Dsmartfox.work_dir="#{work_dir}" com.smartfoxserver.v2.Main]
|
109
|
+
end
|
109
110
|
|
110
|
-
|
111
|
-
|
112
|
-
|
111
|
+
def java_bin
|
112
|
+
Pathname.new(System.getProperty("java.home")).join("bin").join("java")
|
113
|
+
end
|
113
114
|
|
114
|
-
|
115
|
-
|
116
|
-
|
115
|
+
def java_opts
|
116
|
+
%Q[-XX:MaxPermSize=512m -Xms128m -Xms1024m]
|
117
|
+
end
|
118
|
+
|
119
|
+
def classpath
|
120
|
+
%Q[aimy:./:lib/*:lib/Jetty/*:extensions/__lib__/*]
|
121
|
+
end
|
117
122
|
|
118
|
-
def classpath
|
119
|
-
%Q[aimy:./:lib/*:lib/Jetty/*:extensions/__lib__/*]
|
120
123
|
end
|
121
124
|
|
122
125
|
end
|
@@ -1,256 +1,258 @@
|
|
1
1
|
require 'thread'
|
2
2
|
require File.expand_path(File.dirname(__FILE__) + '/common')
|
3
3
|
|
4
|
-
module SmartfoxJruby
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
4
|
+
module SmartfoxJruby
|
5
|
+
module SfsWorker
|
6
|
+
class Processor
|
7
|
+
attr_accessor :opts
|
8
|
+
attr_accessor :name
|
9
|
+
attr_accessor :chained
|
10
|
+
attr_accessor :current
|
11
|
+
attr_accessor :blocks
|
12
|
+
|
13
|
+
def initialize(name, opts = {}, &block)
|
14
|
+
@blocks = [block]
|
15
|
+
@name = name
|
16
|
+
@current = self
|
17
|
+
@chained = nil
|
18
|
+
@opts = opts
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
def chain(name, &block)
|
22
|
+
link.chained = Processor.new(name, @opts, &block)
|
23
|
+
self
|
24
|
+
end
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
def link
|
27
|
+
p = current
|
28
|
+
p = p.chained while (!p.try(:chained).blank?)
|
29
|
+
p
|
30
|
+
end
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
def append(&block)
|
33
|
+
unless link.blank?
|
34
|
+
link.blocks << block
|
35
|
+
else
|
36
|
+
current.blocks << block
|
37
|
+
end
|
38
|
+
self
|
36
39
|
end
|
37
|
-
self
|
38
|
-
end
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
def completed?
|
42
|
+
current.blank?
|
43
|
+
end
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
45
|
+
def mandatory?
|
46
|
+
@opts[:mandatory].nil? || @opts[:mandatory]
|
47
|
+
end
|
47
48
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
49
|
+
def event(name, data = {})
|
50
|
+
if @current.name.to_s == name.to_s
|
51
|
+
@current.blocks.each { |b| b.call(data) }
|
52
|
+
@current = (@current.chained.blank?) ? nil : @current.chained
|
53
|
+
return true
|
54
|
+
end
|
55
|
+
false
|
53
56
|
end
|
54
|
-
false
|
55
|
-
end
|
56
57
|
|
57
|
-
|
58
|
-
|
58
|
+
def to_s
|
59
|
+
"Proc[#{current.try(:name)}] --> #{current.try(:chained)}"
|
60
|
+
end
|
59
61
|
end
|
60
|
-
end
|
61
62
|
|
62
|
-
|
63
|
-
|
64
|
-
|
63
|
+
class Request
|
64
|
+
attr_reader :name
|
65
|
+
attr_reader :data
|
65
66
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
67
|
+
def initialize(name, data = {})
|
68
|
+
@name = name
|
69
|
+
@data = data
|
70
|
+
end
|
70
71
|
|
71
|
-
|
72
|
-
|
73
|
-
|
72
|
+
def to_extension_request
|
73
|
+
ExtensionRequest.new(@name.to_s, @data)
|
74
|
+
end
|
74
75
|
|
75
|
-
|
76
|
-
|
76
|
+
def to_s
|
77
|
+
"Req[#{@name}]#{data.to_json}"
|
78
|
+
end
|
77
79
|
end
|
78
|
-
end
|
79
80
|
|
80
|
-
|
81
|
-
|
82
|
-
|
81
|
+
class Response < Request
|
82
|
+
def to_s
|
83
|
+
"Resp[#{@name}]#{data.to_json}"
|
84
|
+
end
|
83
85
|
end
|
84
|
-
end
|
85
86
|
|
86
|
-
|
87
|
+
class ContextWorker
|
87
88
|
|
88
|
-
|
89
|
-
|
90
|
-
|
89
|
+
def request(name, data = {})
|
90
|
+
@worker.request(name, data, :context => @context)
|
91
|
+
end
|
91
92
|
|
92
|
-
|
93
|
-
|
94
|
-
|
93
|
+
def append_processor(opts = {}, &block)
|
94
|
+
@worker.append_processor(opts.merge(:context => @context), &block)
|
95
|
+
end
|
95
96
|
|
96
|
-
|
97
|
-
|
98
|
-
|
97
|
+
def expect(name, opts={}, &block)
|
98
|
+
@worker.expect(name, opts.merge(:context => @context), &block)
|
99
|
+
end
|
99
100
|
|
100
|
-
|
101
|
-
|
102
|
-
|
101
|
+
def initialize(context, worker)
|
102
|
+
@context = context
|
103
|
+
@worker = worker
|
104
|
+
end
|
103
105
|
end
|
104
|
-
end
|
105
106
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
107
|
+
class Worker
|
108
|
+
attr_reader :send_queue
|
109
|
+
attr_reader :events_queue
|
110
|
+
attr_reader :processors
|
111
|
+
attr_reader :smart_fox
|
112
|
+
attr_reader :opts
|
113
|
+
|
114
|
+
def initialize(smart_fox, opts = {})
|
115
|
+
@send_queue = []
|
116
|
+
@processors = []
|
117
|
+
@events_queue = []
|
118
|
+
@opts = opts
|
119
|
+
@opts[:timeout] ||= 20
|
120
|
+
@smart_fox = smart_fox
|
121
|
+
@mutex = Mutex.new
|
122
|
+
@send_qm = Mutex.new
|
123
|
+
end
|
123
124
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
125
|
+
def append_processor(opts = {}, &block)
|
126
|
+
debug "appending processor with context #{opts[:context]}"
|
127
|
+
if opts[:context]
|
128
|
+
context = opts[:context].append(&block)
|
129
|
+
else
|
130
|
+
context = processors.last.append(&block)
|
131
|
+
end
|
132
|
+
ContextWorker.new(context, self)
|
130
133
|
end
|
131
|
-
ContextWorker.new(context, self)
|
132
|
-
end
|
133
134
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
135
|
+
def request(name, data = {}, opts = {})
|
136
|
+
debug "create request #{name} with context #{opts[:context]}"
|
137
|
+
data = data.to_sfsobject(opts[:serialize_opts]) if data.is_a?(Hash)
|
138
|
+
req = Request.new(name, data)
|
139
|
+
if !opts[:context].blank? && opts[:context].is_a?(Processor)
|
140
|
+
debug "appending #{req} to processor #{opts[:context]}"
|
141
|
+
context = opts[:context].append {
|
142
|
+
@send_qm.synchronize { send_queue << req }
|
143
|
+
}
|
144
|
+
else
|
145
|
+
debug "adding #{req} to send_queue \n #{dump_state}"
|
146
|
+
context = req
|
141
147
|
@send_qm.synchronize { send_queue << req }
|
142
|
-
|
143
|
-
|
144
|
-
debug "adding #{req} to send_queue \n #{dump_state}"
|
145
|
-
context = req
|
146
|
-
@send_qm.synchronize { send_queue << req }
|
148
|
+
end
|
149
|
+
ContextWorker.new(context, self)
|
147
150
|
end
|
148
|
-
ContextWorker.new(context, self)
|
149
|
-
end
|
150
151
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
152
|
+
def expect(name, opts = {}, &block)
|
153
|
+
debug "Expecting to get response #{name} with context #{opts[:context]}"
|
154
|
+
unless opts[:context].blank?
|
155
|
+
if opts[:context].is_a?(Processor)
|
156
|
+
context = opts[:context].chain(name, &block)
|
157
|
+
elsif opts[:context].is_a?(Request)
|
158
|
+
context = Processor.new(name, :context => opts[:context], &block)
|
159
|
+
@mutex.synchronize { processors << context }
|
160
|
+
end
|
161
|
+
else
|
162
|
+
context = Processor.new(name, &block)
|
158
163
|
@mutex.synchronize { processors << context }
|
159
164
|
end
|
160
|
-
|
161
|
-
context = Processor.new(name, &block)
|
162
|
-
@mutex.synchronize { processors << context }
|
165
|
+
ContextWorker.new(context, self)
|
163
166
|
end
|
164
|
-
ContextWorker.new(context, self)
|
165
|
-
end
|
166
167
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
168
|
+
def response(name, data = {})
|
169
|
+
info "Got response #{name} (#{data.to_json})..."
|
170
|
+
@mutex.synchronize { events_queue << Response.new(name, data) }
|
171
|
+
end
|
171
172
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
173
|
+
def perform!
|
174
|
+
while !all_events_caught?
|
175
|
+
while !send_queue.blank?
|
176
|
+
req = nil
|
177
|
+
@send_qm.synchronize { req = send_queue.shift }
|
178
|
+
debug "sending request #{req.name}..."
|
179
|
+
smart_fox.send(req.to_extension_request) unless smart_fox.blank?
|
180
|
+
@last_act = Time.now.to_i
|
181
|
+
end
|
182
|
+
process_events
|
183
|
+
check_timeouts
|
180
184
|
end
|
181
|
-
process_events
|
182
|
-
check_timeouts
|
183
185
|
end
|
184
|
-
end
|
185
186
|
|
186
|
-
|
187
|
-
|
188
|
-
|
187
|
+
def all_events_caught?
|
188
|
+
processors.blank? || processors.collect { |p| p.mandatory? }.blank?
|
189
|
+
end
|
189
190
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
191
|
+
def wait_all_events_caught
|
192
|
+
debug "Waiting all events being caught..."
|
193
|
+
begin
|
194
|
+
wait_with_timeout { all_events_caught? }
|
195
|
+
rescue WaitTimeoutException => e
|
196
|
+
raise "Failed to catch all the events:"+ dump_state
|
197
|
+
end
|
196
198
|
end
|
197
|
-
end
|
198
199
|
|
199
|
-
|
200
|
+
private
|
200
201
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
202
|
+
def dump_state
|
203
|
+
"events_queue = \n\t-#{events_queue.join("\n\t-")}" +
|
204
|
+
" \n processors = \n\t-#{processors.join("\n\t-")}" +
|
205
|
+
" \n send_queue = \n\t-#{send_queue.join("\n\t-")}"
|
206
|
+
end
|
206
207
|
|
207
|
-
|
208
|
-
|
209
|
-
|
208
|
+
def check_timeouts
|
209
|
+
if !@last_act.blank? && Time.now.to_i > @last_act + opts[:timeout]
|
210
|
+
raise "Worker timeout! Latest interaction was #{Time.now.to_i - @last_act} sec ago!\n #{dump_state}"
|
211
|
+
end
|
210
212
|
end
|
211
|
-
end
|
212
213
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
214
|
+
def process_events
|
215
|
+
wait_with_timeout { !events_queue.blank? } rescue nil
|
216
|
+
ei = 0
|
217
|
+
debug "Processing events..."
|
218
|
+
while ei < events_queue.size
|
219
|
+
event = events_queue[ei]
|
220
|
+
pi = 0
|
221
|
+
debug "Processing event #{event.name}..."
|
222
|
+
while pi < processors.size
|
223
|
+
processor = processors[pi]
|
224
|
+
debug "Trying processor #{processor.name}..."
|
225
|
+
if processor.event(event.name, event.data)
|
226
|
+
@last_act = Time.now.to_i
|
227
|
+
debug "Processor found #{processor}"
|
228
|
+
@mutex.synchronize { events_queue.delete_at(ei) }
|
229
|
+
ei -= 1
|
230
|
+
if processor.completed?
|
231
|
+
debug "Processor completed #{processor.name}."
|
232
|
+
@mutex.synchronize { processors.delete_at(pi) }
|
233
|
+
pi -= 1
|
234
|
+
end
|
233
235
|
end
|
236
|
+
pi += 1
|
234
237
|
end
|
235
|
-
|
238
|
+
ei += 1
|
236
239
|
end
|
237
|
-
|
240
|
+
debug "Events processing finished. #{dump_state}"
|
238
241
|
end
|
239
|
-
debug "Events processing finished. #{dump_state}"
|
240
|
-
end
|
241
242
|
|
242
|
-
|
243
|
-
|
244
|
-
|
243
|
+
def debug(msg)
|
244
|
+
puts "[#{time}] DEBUG #{msg}" if opts[:debug]
|
245
|
+
end
|
245
246
|
|
246
|
-
|
247
|
-
|
248
|
-
|
247
|
+
def info(msg)
|
248
|
+
puts "[#{time}] INFO #{msg}"
|
249
|
+
end
|
249
250
|
|
250
|
-
|
251
|
-
|
251
|
+
def time
|
252
|
+
Time.now.strftime("%Y-%m-%d %H:%M:%S")
|
253
|
+
end
|
252
254
|
end
|
253
255
|
end
|
254
|
-
end
|
255
256
|
|
257
|
+
end
|
256
258
|
|
data/lib/smartfox_jruby.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'ostruct'
|
3
3
|
require 'pathname'
|
4
|
-
Dir[Pathname.new(File.dirname(File.expand_path(__FILE__))).join("#{File.basename(__FILE__)}").join("*.rb")].each { |f| require f }
|
5
4
|
|
6
5
|
####################################################
|
7
6
|
# Main module
|
8
7
|
module SmartfoxJruby
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
autoload :SfsRunner, 'smartfox_jruby/sfs_runner'
|
9
|
+
autoload :SfsAdapter, 'smartfox_jruby/sfs_adapter'
|
10
|
+
autoload :SfsWorker, 'smartfox_jruby/sfs_worker'
|
11
|
+
autoload :SFSUtil, 'smartfox_jruby/common'
|
12
|
+
VERSION = "0.2.2"
|
12
13
|
|
13
14
|
end
|
14
15
|
|
metadata
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
name: smartfox_jruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.2.
|
5
|
+
version: 0.2.2
|
6
6
|
platform: java
|
7
7
|
authors:
|
8
8
|
- Ilya Sadykov
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-02-
|
12
|
+
date: 2013-02-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -113,9 +113,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
113
113
|
- !ruby/object:Gem::Version
|
114
114
|
version: !binary |-
|
115
115
|
MA==
|
116
|
-
segments:
|
117
|
-
- 0
|
118
|
-
hash: 2
|
119
116
|
none: false
|
120
117
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
118
|
requirements:
|