redstorm 0.6.6 → 0.7.0.beta1
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/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
|
}
|