redstorm 0.2.1 → 0.4.0

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.
@@ -12,4 +12,11 @@
12
12
  - more doc in README
13
13
 
14
14
  # 0.2.1, 11-23-2011
15
- - gems support in production cluster
15
+ - gems support in production cluster
16
+
17
+ # 0.3.0, 12-08-2011
18
+ - Storm 0.6.0
19
+
20
+ # 0.4.0, 02-08-2012
21
+ - Storm 0.6.2
22
+ - JRuby 1.6.6
data/README.md CHANGED
@@ -1,17 +1,10 @@
1
- # RedStorm v0.2.1 - JRuby on Storm
1
+ # RedStorm v0.4.0 - JRuby on Storm
2
2
 
3
3
  RedStorm provides the JRuby integration for the [Storm][storm] distributed realtime computation system.
4
4
 
5
- ## Changes from 0.1.x
6
-
7
- - this release introduces the *simple* DSL. Topology, Spout and Bolt classes can inherit from the SimpleTopology, SimpleSpout and SimpleBolt classes which provides a very clean and consise DSL. See [examples/simple](https://github.com/colinsurprenant/redstorm/tree/master/examples/simple).
8
- - use the same SimpleTopology class for local development cluster or remote production cluster.
9
- - the `redstorm` command has a new syntax.
10
- - gems support in production cluster
11
-
12
5
  ## Dependencies
13
6
 
14
- This has been tested on OSX 10.6.8 and Linux 10.04 using Storm 0.5.4 and JRuby 1.6.5
7
+ This has been tested on OSX 10.6.8 and Linux 10.04 using Storm 0.6.2 and JRuby 1.6.6
15
8
 
16
9
  ## Installation
17
10
  ``` sh
@@ -241,7 +234,7 @@ configure topology_name do |env|
241
234
  end
242
235
  ```
243
236
 
244
- The `configure` statement is **optional**.
237
+ The `configure` statement is **required**.
245
238
 
246
239
  - `topology_name` — alternate topology name (**default** is topology class name)
247
240
  - `env` — is set to `:local` or `:cluster` for you to set enviroment specific configurations
@@ -463,10 +456,10 @@ end
463
456
 
464
457
  ### Requirements
465
458
 
466
- - JRuby 1.6.5
467
- - rake gem
468
- - ruby-maven gem
469
- - rspec gem
459
+ - JRuby 1.6.6
460
+ - rake gem ~> 0.9.2.2
461
+ - ruby-maven gem ~> 3.0.3.0.28.5
462
+ - rspec gem ~> 2.8.0
470
463
 
471
464
  ### Contribute
472
465
 
@@ -1,18 +1,25 @@
1
+ require 'red_storm'
1
2
  require 'examples/native/random_sentence_spout'
2
3
  require 'examples/native/split_sentence_bolt'
3
4
  require 'examples/native/word_count_bolt'
4
5
 
5
- class ClusterWordCountTopology
6
- def start(base_class_path, env)
7
- builder = TopologyBuilder.new
8
- builder.setSpout(1, JRubySpout.new(base_class_path, "RandomSentenceSpout"), 5)
9
- builder.setBolt(2, JRubyBolt.new(base_class_path, "SplitSentenceBolt"), 4).shuffleGrouping(1)
10
- builder.setBolt(3, JRubyBolt.new(base_class_path, "WordCountBolt"), 4).fieldsGrouping(2, Fields.new("word"))
6
+ module RedStorm
7
+ module Examples
8
+ class ClusterWordCountTopology
9
+ RedStorm::Configuration.topology_class = self
11
10
 
12
- conf = Config.new
13
- conf.setDebug(true)
14
- conf.setNumWorkers(20);
15
- conf.setMaxSpoutPending(1000);
16
- StormSubmitter.submitTopology("word-count", conf, builder.createTopology);
11
+ def start(base_class_path, env)
12
+ builder = TopologyBuilder.new
13
+ builder.setSpout('RandomSentenceSpout', JRubySpout.new(base_class_path, "RedStorm::Examples::RandomSentenceSpout"), 5)
14
+ builder.setBolt('SplitSentenceBolt', JRubyBolt.new(base_class_path, "RedStorm::Examples::SplitSentenceBolt"), 4).shuffleGrouping('RandomSentenceSpout')
15
+ builder.setBolt('WordCountBolt', JRubyBolt.new(base_class_path, "RedStorm::Examples::WordCountBolt"), 4).fieldsGrouping('SplitSentenceBolt', Fields.new("word"))
16
+
17
+ conf = Config.new
18
+ conf.setDebug(true)
19
+ conf.setNumWorkers(20);
20
+ conf.setMaxSpoutPending(1000);
21
+ StormSubmitter.submitTopology("word_count", conf, builder.createTopology);
22
+ end
23
+ end
17
24
  end
18
25
  end
@@ -1,14 +1,18 @@
1
- class ExclamationBolt
2
- def prepare(conf, context, collector)
3
- @collector = collector
4
- end
1
+ module RedStorm
2
+ module Examples
3
+ class ExclamationBolt
4
+ def prepare(conf, context, collector)
5
+ @collector = collector
6
+ end
5
7
 
6
- def execute(tuple)
7
- @collector.emit(tuple, Values.new(tuple.getString(0) + "!!!"))
8
- @collector.ack(tuple)
9
- end
8
+ def execute(tuple)
9
+ @collector.emit(tuple, Values.new(tuple.getString(0) + "!!!"))
10
+ @collector.ack(tuple)
11
+ end
10
12
 
11
- def declare_output_fields(declarer)
12
- declarer.declare(Fields.new("word"))
13
+ def declare_output_fields(declarer)
14
+ declarer.declare(Fields.new("word"))
15
+ end
16
+ end
13
17
  end
14
18
  end
@@ -1,23 +1,31 @@
1
1
  java_import 'backtype.storm.testing.TestWordSpout'
2
+
3
+ require 'lib/red_storm'
2
4
  require 'examples/native/exclamation_bolt'
3
5
 
4
6
  # this example topology uses the Storm TestWordSpout and our own JRuby ExclamationBolt
5
7
 
6
- class LocalExclamationTopology
7
- def start(base_class_path, env)
8
- builder = TopologyBuilder.new
9
-
10
- builder.setSpout(1, TestWordSpout.new, 10)
11
- builder.setBolt(2, JRubyBolt.new(base_class_path, "ExclamationBolt"), 3).shuffleGrouping(1)
12
- builder.setBolt(3, JRubyBolt.new(base_class_path, "ExclamationBolt"), 2).shuffleGrouping(2)
13
-
14
- conf = Config.new
15
- conf.setDebug(true)
16
-
17
- cluster = LocalCluster.new
18
- cluster.submitTopology("test", conf, builder.createTopology)
19
- sleep(5)
20
- cluster.killTopology("test")
21
- cluster.shutdown
8
+ module RedStorm
9
+ module Examples
10
+ class LocalExclamationTopology
11
+ RedStorm::Configuration.topology_class = self
12
+
13
+ def start(base_class_path, env)
14
+ builder = TopologyBuilder.new
15
+
16
+ builder.setSpout('TestWordSpout', TestWordSpout.new, 10)
17
+ builder.setBolt('ExclamationBolt1', JRubyBolt.new(base_class_path, 'RedStorm::Examples::ExclamationBolt'), 3).shuffleGrouping('TestWordSpout')
18
+ builder.setBolt('ExclamationBolt2', JRubyBolt.new(base_class_path, 'RedStorm::Examples::ExclamationBolt'), 3).shuffleGrouping('ExclamationBolt1')
19
+
20
+ conf = Config.new
21
+ conf.setDebug(true)
22
+
23
+ cluster = LocalCluster.new
24
+ cluster.submitTopology("exclamation", conf, builder.createTopology)
25
+ sleep(5)
26
+ cluster.killTopology("exclamation")
27
+ cluster.shutdown
28
+ end
29
+ end
22
30
  end
23
- end
31
+ end
@@ -1,37 +1,45 @@
1
1
  java_import 'backtype.storm.testing.TestWordSpout'
2
2
 
3
- class ExclamationBolt2
4
- def prepare(conf, context, collector)
5
- @collector = collector
6
- end
3
+ require 'lib/red_storm'
7
4
 
8
- def execute(tuple)
9
- @collector.emit(tuple, Values.new(tuple.getString(0) + "!!!"))
10
- @collector.ack(tuple)
11
- end
5
+ module RedStorm
6
+ module Examples
7
+ class ExclamationBolt2
8
+ def prepare(conf, context, collector)
9
+ @collector = collector
10
+ end
12
11
 
13
- def declare_output_fields(declarer)
14
- declarer.declare(Fields.new("word"))
15
- end
16
- end
12
+ def execute(tuple)
13
+ @collector.emit(tuple, Values.new("!#{tuple.getString(0)}!"))
14
+ @collector.ack(tuple)
15
+ end
16
+
17
+ def declare_output_fields(declarer)
18
+ declarer.declare(Fields.new("word"))
19
+ end
20
+ end
21
+
22
+ # this example topology uses the Storm TestWordSpout and our own JRuby ExclamationBolt
17
23
 
18
- # this example topology uses the Storm TestWordSpout and our own JRuby ExclamationBolt
24
+ class LocalExclamationTopology2
25
+ RedStorm::Configuration.topology_class = self
19
26
 
20
- class LocalExclamationTopology2
21
- def start(base_class_path, env)
22
- builder = TopologyBuilder.new
23
-
24
- builder.setSpout(1, TestWordSpout.new, 10)
25
- builder.setBolt(2, JRubyBolt.new(base_class_path, "ExclamationBolt2"), 3).shuffleGrouping(1)
26
- builder.setBolt(3, JRubyBolt.new(base_class_path, "ExclamationBolt2"), 2).shuffleGrouping(2)
27
-
28
- conf = Config.new
29
- conf.setDebug(true)
30
-
31
- cluster = LocalCluster.new
32
- cluster.submitTopology("test", conf, builder.createTopology)
33
- sleep(5)
34
- cluster.killTopology("test")
35
- cluster.shutdown
27
+ def start(base_class_path, env)
28
+ builder = TopologyBuilder.new
29
+
30
+ builder.setSpout('TestWordSpout', TestWordSpout.new, 10)
31
+ builder.setBolt('ExclamationBolt21', JRubyBolt.new(base_class_path, "RedStorm::Examples::ExclamationBolt2"), 3).shuffleGrouping('TestWordSpout')
32
+ builder.setBolt('ExclamationBolt22', JRubyBolt.new(base_class_path, "RedStorm::Examples::ExclamationBolt2"), 2).shuffleGrouping('ExclamationBolt21')
33
+
34
+ conf = Config.new
35
+ conf.setDebug(true)
36
+
37
+ cluster = LocalCluster.new
38
+ cluster.submitTopology("exclamation", conf, builder.createTopology)
39
+ sleep(5)
40
+ cluster.killTopology("exclamation")
41
+ cluster.shutdown
42
+ end
43
+ end
36
44
  end
37
45
  end
@@ -1,58 +1,65 @@
1
1
  require 'redis'
2
2
  require 'thread'
3
+ require 'lib/red_storm'
3
4
  require 'examples/native/word_count_bolt'
4
5
 
5
- # RedisWordSpout reads the Redis queue "test" on localhost:6379
6
- # and emits each word items pop'ed from the queue.
7
- class RedisWordSpout
8
- def open(conf, context, collector)
9
- @collector = collector
10
- @q = Queue.new
11
- @redis_reader = detach_redis_reader
12
- end
13
-
14
- def next_tuple
15
- # per doc nextTuple should not block, and sleep a bit when there's no data to process.
16
- if @q.size > 0
17
- @collector.emit(Values.new(@q.pop))
18
- else
19
- sleep(0.1)
20
- end
21
- end
6
+ module RedStorm
7
+ module Examples
8
+ # RedisWordSpout reads the Redis queue "test" on localhost:6379
9
+ # and emits each word items pop'ed from the queue.
10
+ class RedisWordSpout
11
+ def open(conf, context, collector)
12
+ @collector = collector
13
+ @q = Queue.new
14
+ @redis_reader = detach_redis_reader
15
+ end
16
+
17
+ def next_tuple
18
+ # per doc nextTuple should not block, and sleep a bit when there's no data to process.
19
+ if @q.size > 0
20
+ @collector.emit(Values.new(@q.pop))
21
+ else
22
+ sleep(0.1)
23
+ end
24
+ end
22
25
 
23
- def declare_output_fields(declarer)
24
- declarer.declare(Fields.new("word"))
25
- end
26
+ def declare_output_fields(declarer)
27
+ declarer.declare(Fields.new("word"))
28
+ end
26
29
 
27
- private
30
+ private
28
31
 
29
- def detach_redis_reader
30
- Thread.new do
31
- Thread.current.abort_on_exception = true
32
+ def detach_redis_reader
33
+ Thread.new do
34
+ Thread.current.abort_on_exception = true
32
35
 
33
- redis = Redis.new(:host => "localhost", :port => 6379)
34
- loop do
35
- if data = redis.blpop("test", 0)
36
- @q << data[1]
36
+ redis = Redis.new(:host => "localhost", :port => 6379)
37
+ loop do
38
+ if data = redis.blpop("test", 0)
39
+ @q << data[1]
40
+ end
41
+ end
37
42
  end
38
43
  end
39
44
  end
40
- end
41
- end
42
-
43
- class LocalRedisWordCountTopology
44
- def start(base_class_path, env)
45
- builder = TopologyBuilder.new
46
- builder.setSpout(1, JRubySpout.new(base_class_path, "RedisWordSpout"), 1)
47
- builder.setBolt(2, JRubyBolt.new(base_class_path, "WordCountBolt"), 3).fieldsGrouping(1, Fields.new("word"))
48
-
49
- conf = Config.new
50
- conf.setDebug(true)
51
- conf.setMaxTaskParallelism(3)
52
-
53
- cluster = LocalCluster.new
54
- cluster.submitTopology("redis-word-count", conf, builder.createTopology)
55
- sleep(600)
56
- cluster.shutdown
45
+
46
+ class LocalRedisWordCountTopology
47
+ RedStorm::Configuration.topology_class = self
48
+
49
+ def start(base_class_path, env)
50
+ builder = TopologyBuilder.new
51
+ builder.setSpout('RedisWordSpout', JRubySpout.new(base_class_path, "RedStorm::Examples::RedisWordSpout"), 1)
52
+ builder.setBolt('WordCountBolt', JRubyBolt.new(base_class_path, "RedStorm::Examples::WordCountBolt"), 3).fieldsGrouping('RedisWordSpout', Fields.new("word"))
53
+
54
+ conf = Config.new
55
+ conf.setDebug(true)
56
+ conf.setMaxTaskParallelism(3)
57
+
58
+ cluster = LocalCluster.new
59
+ cluster.submitTopology("redis_word_count", conf, builder.createTopology)
60
+ sleep(600)
61
+ cluster.shutdown
62
+ end
63
+ end
57
64
  end
58
65
  end
@@ -1,21 +1,27 @@
1
+ require 'lib/red_storm'
1
2
  require 'examples/native/random_sentence_spout'
2
3
  require 'examples/native/split_sentence_bolt'
3
4
  require 'examples/native/word_count_bolt'
4
5
 
5
- class LocalWordCountTopology
6
- def start(base_class_path, env)
7
- builder = TopologyBuilder.new
8
- builder.setSpout(1, JRubySpout.new(base_class_path, "RandomSentenceSpout"), 5)
9
- builder.setBolt(2, JRubyBolt.new(base_class_path, "SplitSentenceBolt"), 8).shuffleGrouping(1)
10
- builder.setBolt(3, JRubyBolt.new(base_class_path, "WordCountBolt"), 12).fieldsGrouping(2, Fields.new("word"))
11
6
 
12
- conf = Config.new
13
- conf.setDebug(true)
14
- conf.setMaxTaskParallelism(3)
7
+ module Examples
8
+ class LocalWordCountTopology
9
+ RedStorm::Configuration.topology_class = self
15
10
 
16
- cluster = LocalCluster.new
17
- cluster.submitTopology("word-count", conf, builder.createTopology)
18
- sleep(5)
19
- cluster.shutdown
11
+ def start(base_class_path, env)
12
+ builder = TopologyBuilder.new
13
+ builder.setSpout('RandomSentenceSpout', JRubySpout.new(base_class_path, "RedStorm::Examples::RandomSentenceSpout"), 5)
14
+ builder.setBolt('SplitSentenceBolt', JRubyBolt.new(base_class_path, "RedStorm::Examples::SplitSentenceBolt"), 8).shuffleGrouping('RandomSentenceSpout')
15
+ builder.setBolt('WordCountBolt', JRubyBolt.new(base_class_path, "RedStorm::Examples::WordCountBolt"), 12).fieldsGrouping('SplitSentenceBolt', Fields.new("word"))
16
+
17
+ conf = Config.new
18
+ conf.setDebug(true)
19
+ conf.setMaxTaskParallelism(3)
20
+
21
+ cluster = LocalCluster.new
22
+ cluster.submitTopology("word_count", conf, builder.createTopology)
23
+ sleep(5)
24
+ cluster.shutdown
25
+ end
20
26
  end
21
27
  end
@@ -1,26 +1,30 @@
1
- class RandomSentenceSpout
2
- attr_reader :is_distributed
1
+ module RedStorm
2
+ module Examples
3
+ class RandomSentenceSpout
4
+ attr_reader :is_distributed
3
5
 
4
- def initialize
5
- @is_distributed = true
6
- @sentences = [
7
- "the cow jumped over the moon",
8
- "an apple a day keeps the doctor away",
9
- "four score and seven years ago",
10
- "snow white and the seven dwarfs",
11
- "i am at two with nature"
12
- ]
13
- end
6
+ def initialize
7
+ @is_distributed = true
8
+ @sentences = [
9
+ "the cow jumped over the moon",
10
+ "an apple a day keeps the doctor away",
11
+ "four score and seven years ago",
12
+ "snow white and the seven dwarfs",
13
+ "i am at two with nature"
14
+ ]
15
+ end
14
16
 
15
- def open(conf, context, collector)
16
- @collector = collector
17
- end
18
-
19
- def next_tuple
20
- @collector.emit(Values.new(@sentences[rand(@sentences.length)]))
21
- end
17
+ def open(conf, context, collector)
18
+ @collector = collector
19
+ end
20
+
21
+ def next_tuple
22
+ @collector.emit(Values.new(@sentences[rand(@sentences.length)]))
23
+ end
22
24
 
23
- def declare_output_fields(declarer)
24
- declarer.declare(Fields.new("word"))
25
+ def declare_output_fields(declarer)
26
+ declarer.declare(Fields.new("word"))
27
+ end
28
+ end
25
29
  end
26
- end
30
+ end
@@ -1,13 +1,17 @@
1
- class SplitSentenceBolt
2
- def prepare(conf, context, collector)
3
- @collector = collector
4
- end
1
+ module RedStorm
2
+ module Examples
3
+ class SplitSentenceBolt
4
+ def prepare(conf, context, collector)
5
+ @collector = collector
6
+ end
5
7
 
6
- def execute(tuple)
7
- tuple.getString(0).split(" ").each {|w| @collector.emit(Values.new(w)) }
8
- end
8
+ def execute(tuple)
9
+ tuple.getString(0).split(" ").each {|w| @collector.emit(Values.new(w)) }
10
+ end
9
11
 
10
- def declare_output_fields(declarer)
11
- declarer.declare(Fields.new("word"))
12
+ def declare_output_fields(declarer)
13
+ declarer.declare(Fields.new("word"))
14
+ end
15
+ end
12
16
  end
13
17
  end
@@ -1,19 +1,23 @@
1
- class WordCountBolt
2
- def initialize
3
- @counts = Hash.new{|h, k| h[k] = 0}
4
- end
1
+ module RedStorm
2
+ module Examples
3
+ class WordCountBolt
4
+ def initialize
5
+ @counts = Hash.new{|h, k| h[k] = 0}
6
+ end
5
7
 
6
- def prepare(conf, context, collector)
7
- @collector = collector
8
- end
8
+ def prepare(conf, context, collector)
9
+ @collector = collector
10
+ end
9
11
 
10
- def execute(tuple)
11
- word = tuple.getString(0)
12
- @counts[word] += 1
13
- @collector.emit(Values.new(word, @counts[word]))
14
- end
12
+ def execute(tuple)
13
+ word = tuple.getString(0)
14
+ @counts[word] += 1
15
+ @collector.emit(Values.new(word, @counts[word]))
16
+ end
15
17
 
16
- def declare_output_fields(declarer)
17
- declarer.declare(Fields.new("word", "count"))
18
+ def declare_output_fields(declarer)
19
+ declarer.declare(Fields.new("word", "count"))
20
+ end
21
+ end
18
22
  end
19
23
  end
@@ -1,6 +1,10 @@
1
1
  require 'red_storm'
2
2
 
3
- class ExclamationBolt < RedStorm::SimpleBolt
4
- output_fields :word
5
- on_receive (:ack => true, :anchor => true) {|tuple| tuple.getString(0) + "!!!"}
3
+ module RedStorm
4
+ module Examples
5
+ class ExclamationBolt < RedStorm::SimpleBolt
6
+ output_fields :word
7
+ on_receive(:ack => true, :anchor => true) {|tuple| tuple.getString(0) + "!!!"}
8
+ end
9
+ end
6
10
  end
@@ -4,33 +4,36 @@ require 'examples/simple/exclamation_bolt'
4
4
 
5
5
  # this example topology uses the Storm TestWordSpout and our own JRuby ExclamationBolt
6
6
 
7
- class ExclamationTopology < RedStorm::SimpleTopology
8
- spout TestWordSpout, :parallelism => 10
9
-
10
- bolt ExclamationBolt, :parallelism => 3 do
11
- source TestWordSpout, :shuffle
12
- end
13
-
14
- bolt ExclamationBolt, :id => :ignore, :parallelism => 2 do
15
- source ExclamationBolt, :shuffle
16
- end
7
+ module RedStorm
8
+ module Examples
9
+ class ExclamationTopology < RedStorm::SimpleTopology
10
+ spout TestWordSpout, :parallelism => 10
11
+
12
+ bolt ExclamationBolt, :parallelism => 3 do
13
+ source TestWordSpout, :shuffle
14
+ end
15
+
16
+ bolt ExclamationBolt, :id => :ExclamationBolt2, :parallelism => 2 do
17
+ source ExclamationBolt, :shuffle
18
+ end
17
19
 
18
- configure do |env|
19
- case env
20
- when :local
21
- debug true
22
- max_task_parallelism 3
23
- when :cluster
24
- debug true
25
- num_workers 20
26
- max_spout_pending(1000);
27
- end
28
- end
20
+ configure do |env|
21
+ debug true
22
+ case env
23
+ when :local
24
+ max_task_parallelism 3
25
+ when :cluster
26
+ num_workers 20
27
+ max_spout_pending(1000);
28
+ end
29
+ end
29
30
 
30
- on_submit do |env|
31
- if env == :local
32
- sleep(5)
33
- cluster.shutdown
31
+ on_submit do |env|
32
+ if env == :local
33
+ sleep(5)
34
+ cluster.shutdown
35
+ end
36
+ end
34
37
  end
35
38
  end
36
39
  end
@@ -4,38 +4,41 @@ require 'red_storm'
4
4
  # this example topology uses the Storm TestWordSpout and our own JRuby ExclamationBolt
5
5
  # and a locally defined ExclamationBolt
6
6
 
7
- class ExclamationBolt < RedStorm::SimpleBolt
8
- output_fields :word
9
- on_receive(:ack => true, :anchor => true) {|tuple| "!#{tuple.getString(0)}!"}
10
- end
7
+ module RedStorm
8
+ module Examples
9
+ class ExclamationBolt < RedStorm::SimpleBolt
10
+ output_fields :word
11
+ on_receive(:ack => true, :anchor => true) {|tuple| "!#{tuple.getString(0)}!"}
12
+ end
11
13
 
12
- class ExclamationTopology2 < RedStorm::SimpleTopology
13
- spout TestWordSpout, :parallelism => 10
14
-
15
- bolt ExclamationBolt, :parallelism => 3 do
16
- source TestWordSpout, :shuffle
17
- end
18
-
19
- bolt ExclamationBolt, :id => :ignore, :parallelism => 2 do
20
- source ExclamationBolt, :shuffle
21
- end
14
+ class ExclamationTopology2 < RedStorm::SimpleTopology
15
+ spout TestWordSpout, :parallelism => 10
16
+
17
+ bolt ExclamationBolt, :parallelism => 3 do
18
+ source TestWordSpout, :shuffle
19
+ end
20
+
21
+ bolt ExclamationBolt, :id => :ExclamationBolt2, :parallelism => 2 do
22
+ source ExclamationBolt, :shuffle
23
+ end
22
24
 
23
- configure do |env|
24
- case env
25
- when :local
26
- debug true
27
- max_task_parallelism 3
28
- when :cluster
29
- debug true
30
- num_workers 20
31
- max_spout_pending(1000);
32
- end
33
- end
25
+ configure do |env|
26
+ debug true
27
+ case env
28
+ when :local
29
+ max_task_parallelism 3
30
+ when :cluster
31
+ num_workers 20
32
+ max_spout_pending(1000);
33
+ end
34
+ end
34
35
 
35
- on_submit do |env|
36
- if env == :local
37
- sleep(5)
38
- cluster.shutdown
36
+ on_submit do |env|
37
+ if env == :local
38
+ sleep(5)
39
+ cluster.shutdown
40
+ end
41
+ end
39
42
  end
40
43
  end
41
44
  end
@@ -1,18 +1,22 @@
1
1
  require 'red_storm'
2
2
 
3
- class RandomSentenceSpout < RedStorm::SimpleSpout
4
- set :is_distributed => true
5
- output_fields :word
3
+ module RedStorm
4
+ module Examples
5
+ class RandomSentenceSpout < RedStorm::SimpleSpout
6
+ set :is_distributed => true
7
+ output_fields :word
6
8
 
7
- on_send {@sentences[rand(@sentences.length)]}
9
+ on_send {@sentences[rand(@sentences.length)]}
8
10
 
9
- on_init do
10
- @sentences = [
11
- "the cow jumped over the moon",
12
- "an apple a day keeps the doctor away",
13
- "four score and seven years ago",
14
- "snow white and the seven dwarfs",
15
- "i am at two with nature"
16
- ]
11
+ on_init do
12
+ @sentences = [
13
+ "the cow jumped over the moon",
14
+ "an apple a day keeps the doctor away",
15
+ "four score and seven years ago",
16
+ "snow white and the seven dwarfs",
17
+ "i am at two with nature"
18
+ ]
19
+ end
20
+ end
17
21
  end
18
- end
22
+ end
@@ -5,51 +5,55 @@ require 'red_storm'
5
5
 
6
6
  require 'examples/simple/word_count_bolt'
7
7
 
8
- # RedisWordSpout reads the Redis queue "test" on localhost:6379
9
- # and emits each word items pop'ed from the queue.
8
+ module RedStorm
9
+ module Examples
10
10
 
11
- class RedisWordSpout < RedStorm::SimpleSpout
12
- output_fields :word
11
+ # RedisWordSpout reads the Redis queue "test" on localhost:6379
12
+ # and emits each word items pop'ed from the queue.
13
13
 
14
- on_send {@q.pop if @q.size > 0}
14
+ class RedisWordSpout < RedStorm::SimpleSpout
15
+ output_fields :word
15
16
 
16
- on_init do
17
- @q = Queue.new
18
- @redis_reader = detach_redis_reader
19
- end
20
-
21
- private
22
-
23
- def detach_redis_reader
24
- Thread.new do
25
- Thread.current.abort_on_exception = true
17
+ on_send {@q.pop if @q.size > 0}
26
18
 
27
- redis = Redis.new(:host => "localhost", :port => 6379)
28
- loop do
29
- if data = redis.blpop("test", 0)
30
- @q << data[1]
19
+ on_init do
20
+ @q = Queue.new
21
+ @redis_reader = detach_redis_reader
22
+ end
23
+
24
+ private
25
+
26
+ def detach_redis_reader
27
+ Thread.new do
28
+ Thread.current.abort_on_exception = true
29
+
30
+ redis = Redis.new(:host => "localhost", :port => 6379)
31
+ loop do
32
+ if data = redis.blpop("test", 0)
33
+ @q << data[1]
34
+ end
35
+ end
31
36
  end
32
37
  end
33
38
  end
34
- end
35
- end
36
39
 
37
- class RedisWordCountTopology < RedStorm::SimpleTopology
38
- spout RedisWordSpout
39
-
40
- bolt WordCountBolt, :parallelism => 3 do
41
- source RedisWordSpout, :fields => ["word"]
42
- end
40
+ class RedisWordCountTopology < RedStorm::SimpleTopology
41
+ spout RedisWordSpout
42
+
43
+ bolt WordCountBolt, :parallelism => 3 do
44
+ source RedisWordSpout, :fields => ["word"]
45
+ end
43
46
 
44
- configure do |env|
45
- case env
46
- when :local
47
- debug true
48
- max_task_parallelism 3
49
- when :cluster
50
- debug true
51
- num_workers 20
52
- max_spout_pending(1000);
47
+ configure do |env|
48
+ debug true
49
+ case env
50
+ when :local
51
+ max_task_parallelism 3
52
+ when :cluster
53
+ num_workers 20
54
+ max_spout_pending(1000);
55
+ end
56
+ end
53
57
  end
54
58
  end
55
59
  end
@@ -1,29 +1,33 @@
1
1
  require 'red_storm'
2
2
 
3
- class SplitSentenceBolt < RedStorm::SimpleBolt
4
- output_fields :word
3
+ module RedStorm
4
+ module Examples
5
+ class SplitSentenceBolt < RedStorm::SimpleBolt
6
+ output_fields :word
5
7
 
6
- # block declaration style using auto-emit (default)
7
- #
8
- on_receive {|tuple| tuple.getString(0).split(' ').map{|w| [w]}}
8
+ # block declaration style using auto-emit (default)
9
+ #
10
+ on_receive {|tuple| tuple.getString(0).split(' ').map{|w| [w]}}
9
11
 
10
- # block declaration style no auto-emit
11
- #
12
- # on_receive :emit => false do |tuple|
13
- # tuple.getString(0).split(' ').each{|w| unanchored_emit(w)}
14
- # end
12
+ # block declaration style no auto-emit
13
+ #
14
+ # on_receive :emit => false do |tuple|
15
+ # tuple.getString(0).split(' ').each{|w| unanchored_emit(w)}
16
+ # end
15
17
 
16
- # alternate declaration style using on_receive method
17
- #
18
- # on_receive :emit => true
19
- # def on_receive(tuple)
20
- # tuple.getString(0).split(' ').map{|w| [w]}
21
- # end
18
+ # alternate declaration style using on_receive method
19
+ #
20
+ # on_receive :emit => true
21
+ # def on_receive(tuple)
22
+ # tuple.getString(0).split(' ').map{|w| [w]}
23
+ # end
22
24
 
23
- # alternate declaration style using any specific method
24
- #
25
- # on_receive :my_method, :emit => true
26
- # def my_method(tuple)
27
- # tuple.getString(0).split(' ').map{|w| [w]}
28
- # end
25
+ # alternate declaration style using any specific method
26
+ #
27
+ # on_receive :my_method, :emit => true
28
+ # def my_method(tuple)
29
+ # tuple.getString(0).split(' ').map{|w| [w]}
30
+ # end
31
+ end
32
+ end
29
33
  end
@@ -1,15 +1,19 @@
1
1
  require 'red_storm'
2
2
 
3
- class WordCountBolt < RedStorm::SimpleBolt
4
- output_fields :word, :count
5
- on_init {@counts = Hash.new{|h, k| h[k] = 0}}
3
+ module RedStorm
4
+ module Examples
5
+ class WordCountBolt < RedStorm::SimpleBolt
6
+ output_fields :word, :count
7
+ on_init {@counts = Hash.new{|h, k| h[k] = 0}}
6
8
 
7
- # block declaration style using auto-emit (default)
8
- #
9
- on_receive do |tuple|
10
- word = tuple.getString(0)
11
- @counts[word] += 1
9
+ # block declaration style using auto-emit (default)
10
+ #
11
+ on_receive do |tuple|
12
+ word = tuple.getString(0)
13
+ @counts[word] += 1
12
14
 
13
- [word, @counts[word]]
15
+ [word, @counts[word]]
16
+ end
17
+ end
14
18
  end
15
19
  end
@@ -2,33 +2,36 @@ require 'examples/simple/random_sentence_spout'
2
2
  require 'examples/simple/split_sentence_bolt'
3
3
  require 'examples/simple/word_count_bolt'
4
4
 
5
- class WordCountTopology < RedStorm::SimpleTopology
6
- spout RandomSentenceSpout, :parallelism => 5
7
-
8
- bolt SplitSentenceBolt, :parallelism => 8 do
9
- source RandomSentenceSpout, :shuffle
10
- end
11
-
12
- bolt WordCountBolt, :parallelism => 12 do
13
- source SplitSentenceBolt, :fields => ["word"]
14
- end
5
+ module RedStorm
6
+ module Examples
7
+ class WordCountTopology < SimpleTopology
8
+ spout RandomSentenceSpout, :parallelism => 5
9
+
10
+ bolt SplitSentenceBolt, :parallelism => 8 do
11
+ source RandomSentenceSpout, :shuffle
12
+ end
13
+
14
+ bolt WordCountBolt, :parallelism => 12 do
15
+ source SplitSentenceBolt, :fields => ["word"]
16
+ end
15
17
 
16
- configure :word_count do |env|
17
- case env
18
- when :local
19
- debug true
20
- max_task_parallelism 3
21
- when :cluster
22
- debug true
23
- num_workers 20
24
- max_spout_pending(1000);
25
- end
26
- end
18
+ configure :word_count do |env|
19
+ debug true
20
+ case env
21
+ when :local
22
+ max_task_parallelism 3
23
+ when :cluster
24
+ num_workers 20
25
+ max_spout_pending(1000);
26
+ end
27
+ end
27
28
 
28
- on_submit do |env|
29
- if env == :local
30
- sleep(5)
31
- cluster.shutdown
29
+ on_submit do |env|
30
+ if env == :local
31
+ sleep(5)
32
+ cluster.shutdown
33
+ end
34
+ end
32
35
  end
33
36
  end
34
37
  end
@@ -3,6 +3,7 @@ module RedStorm
3
3
  end
4
4
 
5
5
  require 'red_storm/version'
6
+ require 'red_storm/configuration'
6
7
  require 'red_storm/application'
7
8
  require 'red_storm/simple_bolt'
8
9
  require 'red_storm/simple_spout'
@@ -0,0 +1,16 @@
1
+ module RedStorm
2
+ module Configuration
3
+ extend self
4
+
5
+ @topology_class = nil
6
+
7
+ def topology_class=(clazz)
8
+ @topology_class = clazz
9
+ end
10
+
11
+ def topology_class
12
+ @topology_class
13
+ end
14
+
15
+ end
16
+ end
@@ -1,3 +1,5 @@
1
+ require 'red_storm/configuration'
2
+
1
3
  module RedStorm
2
4
 
3
5
  class SimpleTopology
@@ -8,11 +10,11 @@ module RedStorm
8
10
 
9
11
  class ComponentDefinition
10
12
  attr_reader :clazz, :parallelism
11
- attr_accessor :id
13
+ attr_accessor :id # ids are forced to string
12
14
 
13
15
  def initialize(component_class, id, parallelism)
14
16
  @clazz = component_class
15
- @id = id
17
+ @id = id.to_s
16
18
  @parallelism = parallelism
17
19
  end
18
20
  end
@@ -28,16 +30,16 @@ module RedStorm
28
30
  end
29
31
 
30
32
  def source(source_id, grouping)
31
- @sources << [source_id.is_a?(Class) ? SimpleTopology.underscore(source_id) : source_id, grouping.is_a?(Hash) ? grouping : {grouping => nil}]
33
+ @sources << [source_id.is_a?(Class) ? SimpleTopology.underscore(source_id) : source_id.to_s, grouping.is_a?(Hash) ? grouping : {grouping => nil}]
32
34
  end
33
35
 
34
36
  def define_grouping(declarer)
35
37
  @sources.each do |source_id, grouping|
36
38
  grouper, params = grouping.first
37
-
39
+ # declarer.fieldsGrouping(source_id, Fields.new())
38
40
  case grouper
39
41
  when :fields
40
- declarer.fieldsGrouping(source_id, Fields.new(*params))
42
+ declarer.fieldsGrouping(source_id, Fields.new(*([params].flatten.map(&:to_s))))
41
43
  when :global
42
44
  declarer.globalGrouping(source_id)
43
45
  when :shuffle
@@ -88,6 +90,7 @@ module RedStorm
88
90
  end
89
91
 
90
92
  def self.configure(name = nil, &configure_block)
93
+ Configuration.topology_class = self
91
94
  @topology_name = name if name
92
95
  @configure_block = configure_block if block_given?
93
96
  end
@@ -131,31 +134,13 @@ module RedStorm
131
134
  private
132
135
 
133
136
  def self.resolve_ids!(components)
134
- next_numeric_id = 1
135
- resolved_names = {}
136
-
137
- numeric_components, symbolic_components = components.partition{|c| c.id.is_a?(Fixnum)}
138
- numeric_ids = numeric_components.map(&:id)
139
-
140
- # assign numeric ids to symbolic ids
141
- symbolic_components.each do |component|
142
- id = component.id.to_s
143
- raise("duplicate symbolic id in #{component.clazz.name} on id=#{id}") if resolved_names.has_key?(id)
144
- next_numeric_id += 1 while numeric_ids.include?(next_numeric_id)
145
- numeric_ids << next_numeric_id
146
- resolved_names[id] = next_numeric_id
147
- end
148
-
149
- # reassign numeric ids to all components
150
- components.each do |component|
151
- unless component.id.is_a?(Fixnum)
152
- component.id = resolved_names[component.id.to_s] || raise("cannot resolve #{component.clazz.name} id=#{component.id.to_s}")
153
- end
137
+ # verify duplicate implicit ids
138
+ ids = components.map(&:id)
139
+ components.reverse.each do |component|
140
+ raise("duplicate id in #{component.clazz.name} on id=#{component.id}") if ids.select{|id| id == component.id}.size > 1
141
+ # verify source_id references
154
142
  if component.respond_to?(:sources)
155
- component.sources.map! do |source_id, grouping|
156
- id = source_id.is_a?(Fixnum) ? source_id : resolved_names[source_id.to_s] || raise("cannot resolve #{component.clazz.name} source id=#{source_id.to_s}")
157
- [id, grouping]
158
- end
143
+ component.sources.each{|source_id, grouping| raise("cannot resolve #{component.clazz.name} source id=#{source_id}") unless ids.include?(source_id)}
159
144
  end
160
145
  end
161
146
  end
@@ -24,7 +24,7 @@ java_import 'redstorm.storm.jruby.JRubySpout'
24
24
  java_package 'redstorm'
25
25
 
26
26
  # TopologyLauncher is the application entry point when launching a topology. Basically it will
27
- # call require on the specified Ruby topology/project class file path and call its start method
27
+ # call require on the specified Ruby topology class file path and call its start method
28
28
  class TopologyLauncher
29
29
 
30
30
  java_signature 'void main(String[])'
@@ -35,12 +35,12 @@ class TopologyLauncher
35
35
  end
36
36
  env = args[0].to_sym
37
37
  class_path = args[1]
38
- clazz = camel_case(class_path.split('/').last.split('.').first)
39
-
40
- puts("RedStorm v#{RedStorm::VERSION} starting topology #{clazz} in #{env.to_s} environment")
41
38
 
42
39
  require class_path
43
- Object.module_eval(clazz).new.start(class_path, env)
40
+
41
+ topology_name = RedStorm::Configuration.topology_class.respond_to?(:topology_name) ? "/#{RedStorm::Configuration.topology_class.topology_name}" : ''
42
+ puts("RedStorm v#{RedStorm::VERSION} starting topology #{RedStorm::Configuration.topology_class.name}#{topology_name} in #{env.to_s} environment")
43
+ RedStorm::Configuration.topology_class.new.start(class_path, env)
44
44
  end
45
45
 
46
46
  private
@@ -1,3 +1,3 @@
1
1
  module RedStorm
2
- VERSION = '0.2.1'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -15,6 +15,7 @@ TARGET_SRC_DIR = "#{TARGET_DIR}/src"
15
15
  TARGET_CLASSES_DIR = "#{TARGET_DIR}/classes"
16
16
  TARGET_DEPENDENCY_DIR = "#{TARGET_DIR}/dependency"
17
17
  TARGET_DEPENDENCY_UNPACKED_DIR = "#{TARGET_DIR}/dependency-unpacked"
18
+ TARGET_MARKERS_DIR = "#{TARGET_DIR}/dependency-markers"
18
19
  TARGET_GEMS_DIR = "#{TARGET_DIR}/gems"
19
20
  TARGET_CLUSTER_JAR = "#{TARGET_DIR}/cluster-topology.jar"
20
21
 
@@ -55,7 +56,7 @@ task :install => [:deps, :build] do
55
56
  end
56
57
 
57
58
  task :unpack do
58
- system("rmvn dependency:unpack -f #{RedStorm::REDSTORM_HOME}/pom.xml -DoutputDirectory=#{TARGET_DEPENDENCY_UNPACKED_DIR}")
59
+ system("rmvn dependency:unpack -f #{RedStorm::REDSTORM_HOME}/pom.xml -DoutputDirectory=#{TARGET_DEPENDENCY_UNPACKED_DIR} -DmarkersDirectory=#{TARGET_MARKERS_DIR}")
59
60
  end
60
61
 
61
62
  task :devjar => [:unpack, :clean_jar] do
@@ -111,7 +112,7 @@ task :examples do
111
112
  end
112
113
 
113
114
  task :deps do
114
- system("rmvn dependency:copy-dependencies -f #{RedStorm::REDSTORM_HOME}/pom.xml -DoutputDirectory=#{TARGET_DEPENDENCY_DIR}")
115
+ system("rmvn dependency:copy-dependencies -f #{RedStorm::REDSTORM_HOME}/pom.xml -DoutputDirectory=#{TARGET_DEPENDENCY_DIR} -DmarkersDirectory=#{TARGET_MARKERS_DIR}")
115
116
  end
116
117
 
117
118
  task :build => :setup do
@@ -148,5 +149,5 @@ end
148
149
 
149
150
  def build_jruby(source_path)
150
151
  puts("\n--> Compiling JRuby")
151
- system("cd #{RedStorm::REDSTORM_HOME}; jrubyc -t #{TARGET_SRC_DIR} --verbose --java -c \"#{TARGET_DEPENDENCY_DIR}/storm-0.5.3.jar\" -c \"#{TARGET_CLASSES_DIR}\" #{source_path}")
152
+ system("cd #{RedStorm::REDSTORM_HOME}; jrubyc -t #{TARGET_SRC_DIR} --verbose --java -c \"#{TARGET_DEPENDENCY_DIR}/storm-0.6.2.jar\" -c \"#{TARGET_CLASSES_DIR}\" #{source_path}")
152
153
  end
data/pom.xml CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  <groupId>redstorm</groupId>
6
6
  <artifactId>redstorm</artifactId>
7
- <version>0.2.1</version>
7
+ <version>0.4.0</version>
8
8
  <name>RedStorm JRuby on Storm</name>
9
9
 
10
10
  <properties>
@@ -27,13 +27,13 @@
27
27
  <dependency>
28
28
  <groupId>storm</groupId>
29
29
  <artifactId>storm</artifactId>
30
- <version>0.5.4</version>
30
+ <version>0.6.2</version>
31
31
  </dependency>
32
32
 
33
33
  <dependency>
34
34
  <groupId>org.jruby</groupId>
35
35
  <artifactId>jruby-complete</artifactId>
36
- <version>1.6.5</version>
36
+ <version>1.6.6</version>
37
37
  </dependency>
38
38
  </dependencies>
39
39
 
@@ -48,11 +48,12 @@
48
48
  <artifactItem>
49
49
  <groupId>org.jruby</groupId>
50
50
  <artifactId>jruby-complete</artifactId>
51
- <version>1.6.5</version>
51
+ <version>1.6.6</version>
52
52
  <type>jar</type>
53
53
  <overWrite>false</overWrite>
54
54
  </artifactItem>
55
55
  </artifactItems>
56
+ <markersDirectory>${markersDirectory}</markersDirectory>
56
57
  </configuration>
57
58
  <executions>
58
59
  <execution>
@@ -66,4 +67,4 @@
66
67
  </plugins>
67
68
  </build>
68
69
 
69
- </project>
70
+ </project>
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: redstorm
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.1
5
+ version: 0.4.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Colin Surprenant
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-11-23 00:00:00 Z
13
+ date: 2012-02-08 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rubyforge
@@ -57,6 +57,7 @@ extra_rdoc_files: []
57
57
  files:
58
58
  - lib/red_storm.rb
59
59
  - lib/red_storm/application.rb
60
+ - lib/red_storm/configuration.rb
60
61
  - lib/red_storm/simple_bolt.rb
61
62
  - lib/red_storm/simple_spout.rb
62
63
  - lib/red_storm/simple_topology.rb
@@ -114,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
115
  requirements: []
115
116
 
116
117
  rubyforge_project: redstorm
117
- rubygems_version: 1.8.9
118
+ rubygems_version: 1.8.15
118
119
  signing_key:
119
120
  specification_version: 3
120
121
  summary: JRuby on Storm