redstorm 0.6.6 → 0.7.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +6 -1
- data/README.md +8 -7
- data/examples/dsl/exclamation_topology.rb +2 -4
- data/examples/dsl/exclamation_topology2.rb +4 -5
- data/examples/dsl/hello_world_topology.rb +7 -0
- data/examples/dsl/kafka_topology.rb +5 -1
- data/examples/dsl/redis_word_count_topology.rb +5 -9
- data/examples/dsl/ruby_version_topology.rb +2 -0
- data/examples/dsl/word_count_topology.rb +4 -5
- data/examples/trident/word_count_query.rb +33 -0
- data/examples/trident/word_count_topology.rb +153 -0
- data/ivy/storm_dependencies.xml +1 -1
- data/ivy/topology_dependencies.xml +3 -2
- data/lib/red_storm.rb +5 -2
- data/lib/red_storm/configurator.rb +12 -0
- data/lib/red_storm/dsl/batch_bolt.rb +34 -0
- data/lib/red_storm/dsl/batch_committer_bolt.rb +9 -0
- data/lib/red_storm/dsl/batch_spout.rb +53 -0
- data/lib/red_storm/dsl/bolt.rb +7 -2
- data/lib/red_storm/dsl/output_collector.rb +8 -0
- data/lib/red_storm/dsl/spout.rb +3 -1
- data/lib/red_storm/dsl/topology.rb +2 -2
- data/lib/red_storm/dsl/tuple.rb +2 -0
- data/lib/red_storm/topology_launcher.rb +14 -10
- data/lib/red_storm/version.rb +1 -1
- data/redstorm.gemspec +1 -0
- data/src/main/redstorm/storm/jruby/JRubyBatchBolt.java +53 -35
- data/src/main/redstorm/storm/jruby/JRubyBatchSpout.java +77 -42
- data/src/main/redstorm/storm/jruby/JRubyBolt.java +54 -34
- data/src/main/redstorm/storm/jruby/JRubySpout.java +62 -40
- data/src/main/redstorm/storm/jruby/JRubyTransactionalBolt.java +57 -35
- data/src/main/redstorm/storm/jruby/JRubyTransactionalCommitterBolt.java +6 -17
- data/src/main/redstorm/storm/jruby/JRubyTransactionalCommitterSpout.java +14 -26
- data/src/main/redstorm/storm/jruby/JRubyTransactionalSpout.java +60 -37
- data/src/main/redstorm/storm/jruby/JRubyTridentFunction.java +66 -0
- metadata +16 -23
- data/lib/red_storm/proxy/batch_bolt.rb +0 -63
- data/lib/red_storm/proxy/batch_committer_bolt.rb +0 -52
- data/lib/red_storm/proxy/batch_spout.rb +0 -59
- data/lib/red_storm/proxy/bolt.rb +0 -63
- data/lib/red_storm/proxy/proxy_function.rb +0 -40
- data/lib/red_storm/proxy/spout.rb +0 -87
- data/lib/red_storm/proxy/transactional_committer_spout.rb +0 -47
- data/lib/red_storm/proxy/transactional_spout.rb +0 -46
- data/src/main/redstorm/storm/jruby/JRubyProxyFunction.java +0 -51
@@ -8,81 +8,101 @@ import backtype.storm.tuple.Tuple;
|
|
8
8
|
import backtype.storm.tuple.Fields;
|
9
9
|
import java.util.Map;
|
10
10
|
|
11
|
+
import org.jruby.Ruby;
|
12
|
+
import org.jruby.RubyObject;
|
13
|
+
import org.jruby.runtime.Helpers;
|
14
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
15
|
+
import org.jruby.javasupport.JavaUtil;
|
16
|
+
import org.jruby.RubyModule;
|
17
|
+
import org.jruby.exceptions.RaiseException;
|
18
|
+
|
11
19
|
/**
|
12
|
-
* the JRubyBolt class is a
|
13
|
-
* this proxy is required to bypass the serialization/deserialization
|
14
|
-
*
|
15
|
-
* (Java serialization call on a JRuby class).
|
20
|
+
* the JRubyBolt class is a proxy class to the actual bolt implementation in JRuby.
|
21
|
+
* this proxy is required to bypass the serialization/deserialization issues of JRuby objects.
|
22
|
+
* JRuby classes do not support Java serialization.
|
16
23
|
*
|
17
|
-
* Note that the JRuby bolt
|
18
|
-
* deserialization at the worker and in the declareOutputFields
|
19
|
-
* serialization at topology creation.
|
24
|
+
* Note that the JRuby bolt class is instanciated in the prepare method which is called after
|
25
|
+
* deserialization at the worker and in the declareOutputFields & getComponentConfiguration
|
26
|
+
* methods which are called once before serialization at topology creation.
|
20
27
|
*/
|
21
28
|
public class JRubyBolt implements IRichBolt {
|
22
|
-
|
23
|
-
String
|
24
|
-
String
|
25
|
-
|
29
|
+
private final String _realBoltClassName;
|
30
|
+
private final String[] _fields;
|
31
|
+
private final String _bootstrap;
|
32
|
+
|
33
|
+
// transient to avoid serialization
|
34
|
+
private transient IRubyObject _ruby_bolt;
|
35
|
+
private transient Ruby __ruby__;
|
26
36
|
|
27
37
|
/**
|
28
38
|
* create a new JRubyBolt
|
29
|
-
*
|
30
|
-
* @param baseClassPath the topology/project base JRuby class file path
|
39
|
+
*
|
40
|
+
* @param baseClassPath the topology/project base JRuby class file path
|
31
41
|
* @param realBoltClassName the fully qualified JRuby bolt implementation class name
|
42
|
+
* @param fields the output fields names
|
32
43
|
*/
|
33
44
|
public JRubyBolt(String baseClassPath, String realBoltClassName, String[] fields) {
|
34
|
-
_baseClassPath = baseClassPath;
|
35
45
|
_realBoltClassName = realBoltClassName;
|
36
46
|
_fields = fields;
|
47
|
+
_bootstrap = "require '" + baseClassPath + "'";
|
37
48
|
}
|
38
49
|
|
39
50
|
@Override
|
40
|
-
public void prepare(final Map
|
41
|
-
|
42
|
-
|
43
|
-
|
51
|
+
public void prepare(final Map conf, final TopologyContext context, final OutputCollector collector) {
|
52
|
+
_ruby_bolt = initialize_ruby_bolt();
|
53
|
+
IRubyObject ruby_conf = JavaUtil.convertJavaToRuby(__ruby__, conf);
|
54
|
+
IRubyObject ruby_context = JavaUtil.convertJavaToRuby(__ruby__, context);
|
55
|
+
IRubyObject ruby_collector = JavaUtil.convertJavaToRuby(__ruby__, collector);
|
56
|
+
Helpers.invoke(__ruby__.getCurrentContext(), _ruby_bolt, "prepare", ruby_conf, ruby_context, ruby_collector);
|
44
57
|
}
|
45
58
|
|
46
59
|
@Override
|
47
60
|
public void execute(Tuple input) {
|
48
|
-
|
61
|
+
IRubyObject ruby_input = JavaUtil.convertJavaToRuby(__ruby__, input);
|
62
|
+
Helpers.invoke(__ruby__.getCurrentContext(), _ruby_bolt, "execute", ruby_input);
|
49
63
|
}
|
50
64
|
|
51
65
|
@Override
|
52
66
|
public void cleanup() {
|
53
|
-
|
67
|
+
Helpers.invoke(__ruby__.getCurrentContext(), _ruby_bolt, "cleanup");
|
54
68
|
}
|
55
69
|
|
56
70
|
@Override
|
57
71
|
public void declareOutputFields(OutputFieldsDeclarer declarer) {
|
58
72
|
// declareOutputFields is executed in the topology creation time, before serialisation.
|
59
|
-
//
|
60
|
-
|
73
|
+
// just create tmp bolt instance to call declareOutputFields.
|
74
|
+
|
61
75
|
if (_fields.length > 0) {
|
62
76
|
declarer.declare(new Fields(_fields));
|
63
77
|
} else {
|
64
|
-
|
65
|
-
|
78
|
+
IRubyObject ruby_bolt = initialize_ruby_bolt();
|
79
|
+
IRubyObject ruby_declarer = JavaUtil.convertJavaToRuby(__ruby__, declarer);
|
80
|
+
Helpers.invoke(__ruby__.getCurrentContext(), ruby_bolt, "declare_output_fields", ruby_declarer);
|
66
81
|
}
|
67
82
|
}
|
68
83
|
|
69
84
|
@Override
|
70
85
|
public Map<String, Object> getComponentConfiguration() {
|
71
86
|
// getComponentConfiguration is executed in the topology creation time, before serialisation.
|
72
|
-
//
|
73
|
-
|
74
|
-
|
75
|
-
|
87
|
+
// just create tmp bolt instance to call getComponentConfiguration.
|
88
|
+
|
89
|
+
IRubyObject ruby_bolt = initialize_ruby_bolt();
|
90
|
+
IRubyObject ruby_result = Helpers.invoke(__ruby__.getCurrentContext(), ruby_bolt, "get_component_configuration");
|
91
|
+
return (Map)ruby_result.toJava(Map.class);
|
76
92
|
}
|
77
|
-
|
78
93
|
|
79
|
-
private
|
94
|
+
private IRubyObject initialize_ruby_bolt() {
|
95
|
+
__ruby__ = Ruby.getGlobalRuntime();
|
96
|
+
|
97
|
+
RubyModule ruby_class;
|
80
98
|
try {
|
81
|
-
|
82
|
-
return proxy;
|
99
|
+
ruby_class = __ruby__.getClassFromPath(_realBoltClassName);
|
83
100
|
}
|
84
|
-
catch (
|
85
|
-
|
101
|
+
catch (RaiseException e) {
|
102
|
+
// after deserialization we need to recreate ruby environment
|
103
|
+
__ruby__.evalScriptlet(_bootstrap);
|
104
|
+
ruby_class = __ruby__.getClassFromPath(_realBoltClassName);
|
86
105
|
}
|
106
|
+
return Helpers.invoke(__ruby__.getCurrentContext(), ruby_class, "new");
|
87
107
|
}
|
88
108
|
}
|
@@ -8,100 +8,122 @@ import backtype.storm.tuple.Tuple;
|
|
8
8
|
import backtype.storm.tuple.Fields;
|
9
9
|
import java.util.Map;
|
10
10
|
|
11
|
+
import org.jruby.Ruby;
|
12
|
+
import org.jruby.RubyObject;
|
13
|
+
import org.jruby.runtime.Helpers;
|
14
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
15
|
+
import org.jruby.javasupport.JavaUtil;
|
16
|
+
import org.jruby.RubyModule;
|
17
|
+
import org.jruby.exceptions.RaiseException;
|
18
|
+
|
11
19
|
/**
|
12
|
-
* the JRubySpout class is a
|
13
|
-
* this proxy is required to bypass the serialization/deserialization
|
14
|
-
*
|
15
|
-
* (Java serialization call on a JRuby class).
|
20
|
+
* the JRubySpout class is a proxy class to the actual spout implementation in JRuby.
|
21
|
+
* this proxy is required to bypass the serialization/deserialization issues of JRuby objects.
|
22
|
+
* JRuby classes do not support Java serialization.
|
16
23
|
*
|
17
|
-
* Note that the JRuby spout
|
18
|
-
* deserialization at the worker and in
|
19
|
-
* are called once before serialization at topology creation.
|
24
|
+
* Note that the JRuby spout class is instanciated in the open method which is called after
|
25
|
+
* deserialization at the worker and in the declareOutputFields & getComponentConfiguration
|
26
|
+
* methods which are called once before serialization at topology creation.
|
20
27
|
*/
|
21
28
|
public class JRubySpout implements IRichSpout {
|
22
|
-
|
23
|
-
String
|
24
|
-
String
|
25
|
-
|
29
|
+
private final String _realSpoutClassName;
|
30
|
+
private final String[] _fields;
|
31
|
+
private final String _bootstrap;
|
32
|
+
|
33
|
+
// transient to avoid serialization
|
34
|
+
private transient IRubyObject _ruby_spout;
|
35
|
+
private transient Ruby __ruby__;
|
26
36
|
|
27
37
|
/**
|
28
38
|
* create a new JRubySpout
|
29
|
-
*
|
30
|
-
* @param baseClassPath the topology/project base JRuby class file path
|
39
|
+
*
|
40
|
+
* @param baseClassPath the topology/project base JRuby class file path
|
31
41
|
* @param realSpoutClassName the fully qualified JRuby spout implementation class name
|
42
|
+
* @param fields the output fields names
|
32
43
|
*/
|
33
44
|
public JRubySpout(String baseClassPath, String realSpoutClassName, String[] fields) {
|
34
|
-
_baseClassPath = baseClassPath;
|
35
45
|
_realSpoutClassName = realSpoutClassName;
|
36
46
|
_fields = fields;
|
47
|
+
_bootstrap = "require '" + baseClassPath + "'";
|
37
48
|
}
|
38
49
|
|
39
50
|
@Override
|
40
51
|
public void open(final Map conf, final TopologyContext context, final SpoutOutputCollector collector) {
|
41
|
-
|
42
|
-
|
43
|
-
|
52
|
+
_ruby_spout = initialize_ruby_spout();
|
53
|
+
IRubyObject ruby_conf = JavaUtil.convertJavaToRuby(__ruby__, conf);
|
54
|
+
IRubyObject ruby_context = JavaUtil.convertJavaToRuby(__ruby__, context);
|
55
|
+
IRubyObject ruby_collector = JavaUtil.convertJavaToRuby(__ruby__, collector);
|
56
|
+
Helpers.invoke(__ruby__.getCurrentContext(), _ruby_spout, "open", ruby_conf, ruby_context, ruby_collector);
|
44
57
|
}
|
45
58
|
|
46
59
|
@Override
|
47
60
|
public void close() {
|
48
|
-
|
61
|
+
Helpers.invoke(__ruby__.getCurrentContext(), _ruby_spout, "close");
|
49
62
|
}
|
50
63
|
|
51
64
|
@Override
|
52
65
|
public void activate() {
|
53
|
-
|
66
|
+
Helpers.invoke(__ruby__.getCurrentContext(), _ruby_spout, "activate");
|
54
67
|
}
|
55
68
|
|
56
69
|
@Override
|
57
70
|
public void deactivate() {
|
58
|
-
|
71
|
+
Helpers.invoke(__ruby__.getCurrentContext(), _ruby_spout, "deactivate");
|
59
72
|
}
|
60
73
|
|
61
74
|
@Override
|
62
75
|
public void nextTuple() {
|
63
|
-
|
76
|
+
Helpers.invoke(__ruby__.getCurrentContext(), _ruby_spout, "next_tuple");
|
64
77
|
}
|
65
78
|
|
66
79
|
@Override
|
67
80
|
public void ack(Object msgId) {
|
68
|
-
|
81
|
+
IRubyObject ruby_msg_id = JavaUtil.convertJavaToRuby(__ruby__, msgId);
|
82
|
+
Helpers.invoke(__ruby__.getCurrentContext(), _ruby_spout, "ack", ruby_msg_id);
|
69
83
|
}
|
70
84
|
|
71
85
|
@Override
|
72
86
|
public void fail(Object msgId) {
|
73
|
-
|
87
|
+
IRubyObject ruby_msg_id = JavaUtil.convertJavaToRuby(__ruby__, msgId);
|
88
|
+
Helpers.invoke(__ruby__.getCurrentContext(), _ruby_spout, "fail", ruby_msg_id);
|
74
89
|
}
|
75
90
|
|
76
91
|
@Override
|
77
92
|
public void declareOutputFields(OutputFieldsDeclarer declarer) {
|
78
|
-
// declareOutputFields is executed in the topology creation time before serialisation.
|
79
|
-
//
|
80
|
-
|
93
|
+
// declareOutputFields is executed in the topology creation time, before serialisation.
|
94
|
+
// just create tmp spout instance to call declareOutputFields.
|
95
|
+
|
81
96
|
if (_fields.length > 0) {
|
82
97
|
declarer.declare(new Fields(_fields));
|
83
98
|
} else {
|
84
|
-
|
85
|
-
|
99
|
+
IRubyObject ruby_spout = initialize_ruby_spout();
|
100
|
+
IRubyObject ruby_declarer = JavaUtil.convertJavaToRuby(__ruby__, declarer);
|
101
|
+
Helpers.invoke(__ruby__.getCurrentContext(), ruby_spout, "declare_output_fields", ruby_declarer);
|
86
102
|
}
|
87
|
-
}
|
103
|
+
}
|
88
104
|
|
89
105
|
@Override
|
90
106
|
public Map<String, Object> getComponentConfiguration() {
|
91
|
-
// getComponentConfiguration is executed in the topology creation time before serialisation.
|
92
|
-
//
|
93
|
-
|
94
|
-
|
95
|
-
|
107
|
+
// getComponentConfiguration is executed in the topology creation time, before serialisation.
|
108
|
+
// just create tmp spout instance to call getComponentConfiguration.
|
109
|
+
|
110
|
+
IRubyObject ruby_spout = initialize_ruby_spout();
|
111
|
+
IRubyObject ruby_result = Helpers.invoke(__ruby__.getCurrentContext(), ruby_spout, "get_component_configuration");
|
112
|
+
return (Map)ruby_result.toJava(Map.class);
|
96
113
|
}
|
97
|
-
|
98
|
-
private
|
114
|
+
|
115
|
+
private IRubyObject initialize_ruby_spout() {
|
116
|
+
__ruby__ = Ruby.getGlobalRuntime();
|
117
|
+
|
118
|
+
RubyModule ruby_class;
|
99
119
|
try {
|
100
|
-
|
101
|
-
return proxy;
|
120
|
+
ruby_class = __ruby__.getClassFromPath(_realSpoutClassName);
|
102
121
|
}
|
103
|
-
catch (
|
104
|
-
|
122
|
+
catch (RaiseException e) {
|
123
|
+
// after deserialization we need to recreate ruby environment
|
124
|
+
__ruby__.evalScriptlet(_bootstrap);
|
125
|
+
ruby_class = __ruby__.getClassFromPath(_realSpoutClassName);
|
105
126
|
}
|
127
|
+
return Helpers.invoke(__ruby__.getCurrentContext(), ruby_class, "new");
|
106
128
|
}
|
107
129
|
}
|
@@ -11,80 +11,102 @@ import backtype.storm.tuple.Tuple;
|
|
11
11
|
import backtype.storm.tuple.Fields;
|
12
12
|
import java.util.Map;
|
13
13
|
|
14
|
+
import org.jruby.Ruby;
|
15
|
+
import org.jruby.RubyObject;
|
16
|
+
import org.jruby.runtime.Helpers;
|
17
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
18
|
+
import org.jruby.javasupport.JavaUtil;
|
19
|
+
import org.jruby.RubyModule;
|
20
|
+
import org.jruby.exceptions.RaiseException;
|
21
|
+
|
14
22
|
/**
|
15
|
-
* the JRubyBolt class is a
|
16
|
-
* this proxy is required to bypass the serialization/deserialization
|
17
|
-
*
|
18
|
-
* (Java serialization call on a JRuby class).
|
23
|
+
* the JRubyBolt class is a proxy class to the actual bolt implementation in JRuby.
|
24
|
+
* this proxy is required to bypass the serialization/deserialization issues of JRuby objects.
|
25
|
+
* JRuby classes do not support Java serialization.
|
19
26
|
*
|
20
|
-
* Note that the JRuby bolt
|
21
|
-
* deserialization at the worker and in the declareOutputFields
|
22
|
-
* serialization at topology creation.
|
27
|
+
* Note that the JRuby bolt class is instanciated in the prepare method which is called after
|
28
|
+
* deserialization at the worker and in the declareOutputFields & getComponentConfiguration
|
29
|
+
* methods which are called once before serialization at topology creation.
|
23
30
|
*/
|
24
31
|
public class JRubyTransactionalBolt extends BaseTransactionalBolt {
|
25
|
-
|
26
|
-
String
|
27
|
-
String
|
28
|
-
|
32
|
+
private final String _realBoltClassName;
|
33
|
+
private final String[] _fields;
|
34
|
+
private final String _bootstrap;
|
35
|
+
|
36
|
+
// transient to avoid serialization
|
37
|
+
protected transient IRubyObject _ruby_bolt;
|
38
|
+
protected transient Ruby __ruby__;
|
29
39
|
|
30
|
-
|
40
|
+
/**
|
31
41
|
* create a new JRubyBolt
|
32
|
-
*
|
33
|
-
* @param baseClassPath the topology/project base JRuby class file path
|
42
|
+
*
|
43
|
+
* @param baseClassPath the topology/project base JRuby class file path
|
34
44
|
* @param realBoltClassName the fully qualified JRuby bolt implementation class name
|
45
|
+
* @param fields the output fields names
|
35
46
|
*/
|
36
47
|
public JRubyTransactionalBolt(String baseClassPath, String realBoltClassName, String[] fields) {
|
37
|
-
_baseClassPath = baseClassPath;
|
38
48
|
_realBoltClassName = realBoltClassName;
|
39
49
|
_fields = fields;
|
50
|
+
_bootstrap = "require '" + baseClassPath + "'";
|
40
51
|
}
|
41
52
|
|
42
53
|
@Override
|
43
|
-
public void prepare(final Map
|
44
|
-
|
45
|
-
|
46
|
-
|
54
|
+
public void prepare(final Map conf, final TopologyContext context, final BatchOutputCollector collector, final TransactionAttempt id) {
|
55
|
+
_ruby_bolt = initialize_ruby_bolt();
|
56
|
+
IRubyObject ruby_conf = JavaUtil.convertJavaToRuby(__ruby__, conf);
|
57
|
+
IRubyObject ruby_context = JavaUtil.convertJavaToRuby(__ruby__, context);
|
58
|
+
IRubyObject ruby_collector = JavaUtil.convertJavaToRuby(__ruby__, collector);
|
59
|
+
IRubyObject ruby_id = JavaUtil.convertJavaToRuby(__ruby__, id);
|
60
|
+
Helpers.invoke(__ruby__.getCurrentContext(), _ruby_bolt, "prepare", ruby_conf, ruby_context, ruby_collector, ruby_id);
|
47
61
|
}
|
48
62
|
|
49
63
|
@Override
|
50
64
|
public void execute(Tuple input) {
|
51
|
-
|
65
|
+
IRubyObject ruby_input = JavaUtil.convertJavaToRuby(__ruby__, input);
|
66
|
+
Helpers.invoke(__ruby__.getCurrentContext(), _ruby_bolt, "execute", ruby_input);
|
52
67
|
}
|
53
68
|
|
54
69
|
@Override
|
55
70
|
public void finishBatch() {
|
56
|
-
|
71
|
+
Helpers.invoke(__ruby__.getCurrentContext(), _ruby_bolt, "finish_batch");
|
57
72
|
}
|
58
73
|
|
59
74
|
@Override
|
60
75
|
public void declareOutputFields(OutputFieldsDeclarer declarer) {
|
61
76
|
// declareOutputFields is executed in the topology creation time, before serialisation.
|
62
|
-
//
|
63
|
-
|
77
|
+
// just create tmp bolt instance to call declareOutputFields.
|
78
|
+
|
64
79
|
if (_fields.length > 0) {
|
65
80
|
declarer.declare(new Fields(_fields));
|
66
81
|
} else {
|
67
|
-
|
68
|
-
|
82
|
+
IRubyObject ruby_bolt = initialize_ruby_bolt();
|
83
|
+
IRubyObject ruby_declarer = JavaUtil.convertJavaToRuby(__ruby__, declarer);
|
84
|
+
Helpers.invoke(__ruby__.getCurrentContext(), ruby_bolt, "declare_output_fields", ruby_declarer);
|
69
85
|
}
|
70
86
|
}
|
71
87
|
|
72
88
|
@Override
|
73
89
|
public Map<String, Object> getComponentConfiguration() {
|
74
90
|
// getComponentConfiguration is executed in the topology creation time, before serialisation.
|
75
|
-
//
|
76
|
-
|
77
|
-
|
78
|
-
|
91
|
+
// just create tmp bolt instance to call getComponentConfiguration.
|
92
|
+
|
93
|
+
IRubyObject ruby_bolt = initialize_ruby_bolt();
|
94
|
+
IRubyObject ruby_result = Helpers.invoke(__ruby__.getCurrentContext(), ruby_bolt, "get_component_configuration");
|
95
|
+
return (Map)ruby_result.toJava(Map.class);
|
79
96
|
}
|
80
|
-
|
81
|
-
|
97
|
+
|
98
|
+
protected IRubyObject initialize_ruby_bolt() {
|
99
|
+
__ruby__ = Ruby.getGlobalRuntime();
|
100
|
+
|
101
|
+
RubyModule ruby_class;
|
82
102
|
try {
|
83
|
-
|
84
|
-
return proxy;
|
103
|
+
ruby_class = __ruby__.getClassFromPath(_realBoltClassName);
|
85
104
|
}
|
86
|
-
catch (
|
87
|
-
|
105
|
+
catch (RaiseException e) {
|
106
|
+
// after deserialization we need to recreate ruby environment
|
107
|
+
__ruby__.evalScriptlet(_bootstrap);
|
108
|
+
ruby_class = __ruby__.getClassFromPath(_realBoltClassName);
|
88
109
|
}
|
110
|
+
return Helpers.invoke(__ruby__.getCurrentContext(), ruby_class, "new");
|
89
111
|
}
|
90
112
|
}
|
@@ -5,27 +5,16 @@ import backtype.storm.transactional.TransactionAttempt;
|
|
5
5
|
import backtype.storm.transactional.ICommitter;
|
6
6
|
|
7
7
|
/**
|
8
|
-
* the JRubyBolt class is a
|
9
|
-
* this proxy is required to bypass the serialization/deserialization
|
10
|
-
*
|
11
|
-
* (Java serialization call on a JRuby class).
|
8
|
+
* the JRubyBolt class is a proxy class to the actual bolt implementation in JRuby.
|
9
|
+
* this proxy is required to bypass the serialization/deserialization issues of JRuby objects.
|
10
|
+
* JRuby classes do not support Java serialization.
|
12
11
|
*
|
13
|
-
* Note that the JRuby bolt
|
14
|
-
* deserialization at the worker and in the declareOutputFields
|
15
|
-
* serialization at topology creation.
|
12
|
+
* Note that the JRuby bolt class is instanciated in the prepare method which is called after
|
13
|
+
* deserialization at the worker and in the declareOutputFields & getComponentConfiguration
|
14
|
+
* methods which are called once before serialization at topology creation.
|
16
15
|
*/
|
17
16
|
public class JRubyTransactionalCommitterBolt extends JRubyTransactionalBolt implements ICommitter {
|
18
17
|
public JRubyTransactionalCommitterBolt(String baseClassPath, String realBoltClassName, String[] fields) {
|
19
18
|
super(baseClassPath, realBoltClassName, fields);
|
20
19
|
}
|
21
|
-
|
22
|
-
private static IBatchBolt newProxyBolt(String baseClassPath, String realBoltClassName) {
|
23
|
-
try {
|
24
|
-
redstorm.proxy.BatchCommitterBolt proxy = new redstorm.proxy.BatchCommitterBolt(baseClassPath, realBoltClassName);
|
25
|
-
return proxy;
|
26
|
-
}
|
27
|
-
catch (Exception e) {
|
28
|
-
throw new RuntimeException(e);
|
29
|
-
}
|
30
|
-
}
|
31
20
|
}
|