batsir 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/.document +5 -0
  2. data/.rspec +3 -0
  3. data/.travis.yml +10 -0
  4. data/Gemfile +22 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +79 -0
  7. data/Rakefile +55 -0
  8. data/VERSION +1 -0
  9. data/batsir.gemspec +104 -0
  10. data/batsir.png +0 -0
  11. data/lib/batsir.rb +73 -0
  12. data/lib/batsir/acceptors/acceptor.rb +45 -0
  13. data/lib/batsir/acceptors/amqp_acceptor.rb +19 -0
  14. data/lib/batsir/amqp.rb +45 -0
  15. data/lib/batsir/chain.rb +33 -0
  16. data/lib/batsir/config.rb +34 -0
  17. data/lib/batsir/dsl/dsl_mappings.rb +96 -0
  18. data/lib/batsir/filter.rb +12 -0
  19. data/lib/batsir/filter_queue.rb +30 -0
  20. data/lib/batsir/logo.rb +36 -0
  21. data/lib/batsir/notifiers/amqp_notifier.rb +16 -0
  22. data/lib/batsir/notifiers/notifier.rb +39 -0
  23. data/lib/batsir/registry.rb +15 -0
  24. data/lib/batsir/stage.rb +94 -0
  25. data/lib/batsir/stage_worker.rb +86 -0
  26. data/lib/batsir/transformers/field_transformer.rb +40 -0
  27. data/lib/batsir/transformers/json_input_transformer.rb +9 -0
  28. data/lib/batsir/transformers/json_output_transformer.rb +9 -0
  29. data/lib/batsir/transformers/transformer.rb +15 -0
  30. data/spec/batsir/acceptors/acceptor_spec.rb +136 -0
  31. data/spec/batsir/acceptors/amqp_acceptor_spec.rb +169 -0
  32. data/spec/batsir/chain_spec.rb +31 -0
  33. data/spec/batsir/dsl/chain_mapping_spec.rb +117 -0
  34. data/spec/batsir/dsl/stage_mapping_spec.rb +435 -0
  35. data/spec/batsir/filter_queue_spec.rb +74 -0
  36. data/spec/batsir/filter_spec.rb +12 -0
  37. data/spec/batsir/notifiers/amqp_notifier_spec.rb +117 -0
  38. data/spec/batsir/notifiers/notifier_spec.rb +73 -0
  39. data/spec/batsir/stage_spec.rb +678 -0
  40. data/spec/batsir/stage_worker_spec.rb +128 -0
  41. data/spec/batsir/support/bunny_mocks.rb +62 -0
  42. data/spec/batsir/support/mock_filters.rb +43 -0
  43. data/spec/batsir/transformers/field_transformer_spec.rb +73 -0
  44. data/spec/batsir/transformers/json_input_transformer_spec.rb +22 -0
  45. data/spec/batsir/transformers/json_output_transformer_spec.rb +18 -0
  46. data/spec/batsir/transformers/transformer_spec.rb +22 -0
  47. data/spec/spec_helper.rb +22 -0
  48. metadata +220 -0
@@ -0,0 +1,45 @@
1
+ module Batsir
2
+ module AMQP
3
+ attr_accessor :queue
4
+ attr_accessor :host
5
+ attr_accessor :port
6
+ attr_accessor :username
7
+ attr_accessor :password
8
+ attr_accessor :vhost
9
+ attr_accessor :exchange
10
+
11
+ def bunny_options
12
+ {
13
+ :host => host,
14
+ :port => port,
15
+ :user => username,
16
+ :pass => password,
17
+ :vhost => vhost
18
+ }
19
+ end
20
+
21
+ def host
22
+ @host || 'localhost'
23
+ end
24
+
25
+ def port
26
+ @port || 5672
27
+ end
28
+
29
+ def username
30
+ @username || 'guest'
31
+ end
32
+
33
+ def password
34
+ @password || 'guest'
35
+ end
36
+
37
+ def vhost
38
+ @vhost || '/'
39
+ end
40
+
41
+ def exchange
42
+ @exchange || 'amq.direct'
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,33 @@
1
+ module Batsir
2
+ class Chain
3
+
4
+ def initialize(options = {})
5
+ options.each do |attr, value|
6
+ self.send("#{attr.to_s}=", value)
7
+ end
8
+ @stages = []
9
+ end
10
+
11
+ def stages
12
+ @stages
13
+ end
14
+
15
+ def add_stage(stage)
16
+ @stages << stage
17
+ end
18
+
19
+ def compile
20
+ generated = ""
21
+ stages.each do |stage|
22
+ generated << stage.compile
23
+ end
24
+ generated
25
+ end
26
+
27
+ def start
28
+ stages.each do | stage |
29
+ stage.start
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,34 @@
1
+ module Batsir
2
+ class Config
3
+ def initialize(data={})
4
+ @data = {}
5
+ update!(data)
6
+ end
7
+
8
+ def update!(data)
9
+ data.each do |key, value|
10
+ self[key] = value
11
+ end
12
+ end
13
+
14
+ def [](key)
15
+ @data[key.to_sym]
16
+ end
17
+
18
+ def []=(key, value)
19
+ if value.class == Hash
20
+ @data[key.to_sym] = Config.new(value)
21
+ else
22
+ @data[key.to_sym] = value
23
+ end
24
+ end
25
+
26
+ def method_missing(sym, *args)
27
+ if sym.to_s =~ /(.+)=$/
28
+ self[$1] = args.first
29
+ else
30
+ self[sym]
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,96 @@
1
+ module Batsir
2
+ module DSL
3
+ class ChainMapping < ::Blockenspiel::Base
4
+ def initialize
5
+ @chain = nil
6
+ end
7
+
8
+ def aggregator_chain(&block)
9
+ @chain = Batsir::Chain.new
10
+ ::Blockenspiel.invoke(block, self)
11
+ @chain
12
+ end
13
+
14
+ def stage(name, &block)
15
+ new_block = ::Proc.new do
16
+ stage name, &block
17
+ end
18
+ stage = ::Blockenspiel.invoke(new_block, Batsir::DSL::StageMapping.new)
19
+ stage.chain = @chain
20
+ @chain.add_stage(stage)
21
+ end
22
+ end
23
+
24
+ class StageMapping < ::Blockenspiel::Base
25
+ def initialize
26
+ @stage = nil
27
+ end
28
+
29
+ def stage(name, &block)
30
+ @stage = Batsir::Stage.new(:name => name)
31
+ ::Blockenspiel.invoke(block, self)
32
+ @stage
33
+ end
34
+
35
+ def filter(operation)
36
+ @stage.add_filter(operation)
37
+ end
38
+
39
+ def inbound(&block)
40
+ ::Blockenspiel.invoke(block, Batsir::DSL::InboundMapping.new(@stage))
41
+ end
42
+
43
+ def outbound(&block)
44
+ ::Blockenspiel.invoke(block, Batsir::DSL::OutboundMapping.new(@stage))
45
+ end
46
+ end
47
+
48
+ class InboundMapping < ::Blockenspiel::Base
49
+ def initialize(stage)
50
+ @stage = stage
51
+ end
52
+
53
+ def transformers(&block)
54
+ ::Blockenspiel.invoke(block, Batsir::DSL::InboundTransformerMapping.new(@stage))
55
+ end
56
+
57
+ def acceptor(acceptor_class, options = {})
58
+ @stage.add_acceptor(acceptor_class, options)
59
+ end
60
+ end
61
+
62
+ class InboundTransformerMapping < ::Blockenspiel::Base
63
+ def initialize(stage)
64
+ @stage = stage
65
+ end
66
+
67
+ def transformer(transformer, options = {})
68
+ @stage.add_acceptor_transformer(transformer, options)
69
+ end
70
+ end
71
+
72
+ class OutboundMapping < ::Blockenspiel::Base
73
+ def initialize(stage)
74
+ @stage = stage
75
+ end
76
+
77
+ def transformers(&block)
78
+ ::Blockenspiel.invoke(block, Batsir::DSL::OutboundTransformerMapping.new(@stage))
79
+ end
80
+
81
+ def notifier(notifier_class, options = {})
82
+ @stage.add_notifier(notifier_class, options)
83
+ end
84
+ end
85
+
86
+ class OutboundTransformerMapping < ::Blockenspiel::Base
87
+ def initialize(stage)
88
+ @stage = stage
89
+ end
90
+
91
+ def transformer(transformer, options = {})
92
+ @stage.add_notifier_transformer(transformer, options)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,12 @@
1
+ module Batsir
2
+ class Filter
3
+ def initialize(options = {})
4
+ options.each do |attr, value|
5
+ self.send("#{attr.to_s}=", value)
6
+ end
7
+ end
8
+
9
+ def execute(message)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,30 @@
1
+ module Batsir
2
+ class FilterQueue
3
+ include Enumerable
4
+
5
+ attr_accessor :filters
6
+ attr_accessor :notifiers
7
+
8
+ def initialize
9
+ @filters = []
10
+ @notifiers = []
11
+ end
12
+
13
+ def add(operation)
14
+ @filters << operation
15
+ end
16
+
17
+ def add_notifier(notifier)
18
+ @notifiers << notifier
19
+ end
20
+
21
+ def each
22
+ @filters.each {|op| yield op}
23
+ @notifiers.each {|n| yield n}
24
+ end
25
+
26
+ def empty?
27
+ !(@notifiers.any? || @filters.any?)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,36 @@
1
+ module Batsir
2
+ def self.logo
3
+ <<EOF
4
+
5
+
6
+
7
+
8
+
9
+ E ,.
10
+ ,,,agB8@f ,8v ,8L J88&gg,,,
11
+ .,a88888888@^ |8&,,,,,,88k ,88888888&g,,
12
+ ,+88888888888$t 8888888f''9@. ,888888888888g,
13
+ ,,88888888888888$; ,888888&` 8c ,888888888888888w,
14
+ ,a88888888888888888&,......|8888888&gg&|8k......,d88888888888888888&,
15
+ ,888888888888888888888888888888888qp8888|@8888888888888888888888888888y
16
+ ,888888888888888888888888888888`8` '' `8`|888888888888888888888888888888E
17
+ ,88888888888888888888888888888888 && 8|8888888888888888888888888888888c
18
+ |88888888888888888888888888888888888888888|8888888888888888888888888888888k
19
+ |88888888888888888888888888888888888888888|8888888888888888888888888888888k
20
+ ,888888888888888888888888888888888888888888888888888888888888888888888888!
21
+ j8888888888888888888888888888888888888888888888888888888888888888888888f
22
+ j8888888888888888@@88888888888888888888888888888888@@888888888888888@f
23
+ ,9888888888888@: `988M^ `?88888888888@f: |988M' .8888888888888M'
24
+ ,98888888888F jf J8888888@f jf ,888888888@f'
25
+ |98888888&. ,98888@' d888888@9"
26
+ `?9@888&, j88f ,d88$@9l'
27
+ `|?9t |f `9T"`
28
+
29
+
30
+
31
+
32
+
33
+
34
+ EOF
35
+ end
36
+ end
@@ -0,0 +1,16 @@
1
+ require 'batsir/amqp'
2
+
3
+ module Batsir
4
+ module Notifiers
5
+ class AMQPNotifier < Notifier
6
+ include Batsir::AMQP
7
+
8
+ def execute(message)
9
+ Bunny.run( bunny_options )do |bunny|
10
+ exc = bunny.exchange( exchange )
11
+ exc.publish( message, :key => queue )
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ module Batsir
2
+ module Notifiers
3
+ class Notifier
4
+ attr_accessor :field_mapping
5
+ attr_accessor :transformer_queue
6
+
7
+ def initialize(options = {})
8
+ fields = options.delete(:fields)
9
+
10
+ options.each do |option, value|
11
+ self.send("#{option}=", value)
12
+ end
13
+ @transformer_queue = []
14
+ if fields
15
+ add_transformer(Batsir::Transformers::FieldTransformer.new(:fields => fields))
16
+ end
17
+ end
18
+
19
+ def add_transformer(transformer)
20
+ @transformer_queue << transformer
21
+ end
22
+
23
+ def notify(message)
24
+ execute(transform(message))
25
+ end
26
+
27
+ def execute(message)
28
+
29
+ end
30
+
31
+ def transform(message)
32
+ transformer_queue.each do |transformer|
33
+ message = transformer.transform(message)
34
+ end
35
+ message
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,15 @@
1
+ module Batsir
2
+ class Registry
3
+ def self.register(name, klass)
4
+ registry[name] = klass
5
+ end
6
+
7
+ def self.registry
8
+ @registry ||= {}
9
+ end
10
+
11
+ def self.get(name)
12
+ registry.fetch(name)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,94 @@
1
+ module Batsir
2
+ class Stage
3
+ include Celluloid
4
+
5
+ FilterDeclaration = Struct.new(:filter, :options)
6
+ TransformerDeclaration = Struct.new(:transformer, :options)
7
+
8
+ attr_accessor :name
9
+ attr_accessor :chain
10
+ attr_accessor :cancellators
11
+ attr_reader :filter_declarations
12
+ attr_reader :notifiers
13
+ attr_reader :acceptors
14
+ attr_reader :running_acceptors
15
+ attr_reader :notifier_transformers
16
+ attr_reader :acceptor_transformers
17
+
18
+ def initialize(options = {})
19
+ options.each do |attr, value|
20
+ self.send("#{attr.to_s}=", value)
21
+ end
22
+ @cancellators = []
23
+ @acceptor_transformers = []
24
+ @running_acceptors = []
25
+ @acceptors = {}
26
+ @filter_declarations = []
27
+ @notifiers = {}
28
+ @notifier_transformers = []
29
+ @built = false
30
+ end
31
+
32
+ def built?
33
+ @built
34
+ end
35
+
36
+ def add_acceptor_transformer(transformer, options = {})
37
+ @acceptor_transformers << TransformerDeclaration.new(transformer, options)
38
+ end
39
+
40
+ def add_acceptor(acceptor, options = {})
41
+ @acceptors[acceptor] ||= Set.new
42
+ @acceptors[acceptor] << options
43
+ end
44
+
45
+ def add_filter(filter, options = {})
46
+ @filter_declarations << FilterDeclaration.new(filter, options)
47
+ end
48
+
49
+ def filters
50
+ @filter_declarations.map{ |filter_declaration| filter_declaration.filter }
51
+ end
52
+
53
+ def add_notifier(notifier, options = {})
54
+ @notifiers[notifier] ||= Set.new
55
+ @notifiers[notifier] << options
56
+ end
57
+
58
+ def add_notifier_transformer(transformer, options = {})
59
+ @notifier_transformers << TransformerDeclaration.new(transformer, options)
60
+ end
61
+
62
+ def compile
63
+ Batsir::StageWorker.compile_from(self)
64
+ end
65
+
66
+ def finalize
67
+ @cancellators.each do |cancellator|
68
+ cancellator.write "STOP"
69
+ end
70
+ end
71
+
72
+ def start
73
+ acceptors.each do |acceptor_class, options|
74
+ options.each do |acceptor_options|
75
+ cancellator_reader, cancellator_writer = ::IO.pipe
76
+ acceptor_options.merge!(:stage_name => self.name, :cancellator => cancellator_reader)
77
+ @cancellators << cancellator_writer
78
+ acceptor = acceptor_class.new(acceptor_options)
79
+ if acceptor_transformers.any?
80
+ acceptor_transformers.each do |transformer_declaration|
81
+ transformer = transformer_declaration.transformer.new(transformer_declaration.options)
82
+ acceptor.add_transformer(transformer)
83
+ end
84
+ else
85
+ acceptor.add_transformer(Batsir::Transformers::JSONInputTransformer.new)
86
+ end
87
+ @running_acceptors << acceptor
88
+ acceptor.start!
89
+ end
90
+ end
91
+ true
92
+ end
93
+ end
94
+ end