batsir 0.1.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.
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