event-pub-sub 1.1.6

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 73f22c5c6e9637d5795f7d8730690d760eaca0a9
4
+ data.tar.gz: dfb2258f9b8981dacc99a8d295c6e2ac4c8a65d3
5
+ SHA512:
6
+ metadata.gz: faab525873900f49e3d36ef61d949a4c0c8fe742bd30d6e5d7592425816d2299797b26f2b8130e3dba643f8101a84115e14b2b66395d9be6e1c19da2f1765dac
7
+ data.tar.gz: 5f2051b5550451e5b5ead0c7a01b2da6bf5f0e91a5f528f6cd8b622226dd9f0b6d9d4c40965397dc0daa8a1ad038d65076af020bdc980d1be6e09be57426cdf2
data/.gitignore ADDED
@@ -0,0 +1,64 @@
1
+ *.rbc
2
+ capybara-*.html
3
+ /log
4
+ /tmp
5
+ /db/*.sqlite3
6
+ /public/system
7
+ /coverage/
8
+ /spec/tmp
9
+ run_test.sh
10
+ **.orig
11
+ rerun.txt
12
+ pickle-email-*.html
13
+
14
+ # TODO Comment out these rules if you are OK with secrets being uploaded to the repo
15
+ config/initializers/secret_token.rb
16
+ config/secrets.yml
17
+
18
+ ## Environment normalisation:
19
+ /.bundle
20
+ /vendor/bundle
21
+
22
+ # these should all be checked in to normalise the environment:
23
+ # Gemfile.lock, .ruby-version, .ruby-gemset
24
+
25
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
26
+ .rvmrc
27
+
28
+ # if using bower-rails ignore default bower_components path bower.json files
29
+ /vendor/assets/bower_components
30
+ *.bowerrc
31
+ bower.json
32
+ # See https://help.github.com/articles/ignoring-files for more about ignoring files.
33
+ #
34
+ # If you find yourself ignoring temporary files generated by your text editor
35
+ # or operating system, you probably want to add a global ignore instead:
36
+ # git config --global core.excludesfile '~/.gitignore_global'
37
+
38
+ # Ignore bundler config.
39
+ /.bundle
40
+
41
+ # Ignore the default SQLite database.
42
+ /db/*.sqlite3
43
+ /db/*.sqlite3-journal
44
+
45
+ # Ignore all logfiles and tempfiles.
46
+ /log/*
47
+ !/log/.keep
48
+ /tmp
49
+
50
+ *.swp
51
+ *.swo
52
+ *.swn
53
+
54
+ # Ignore redis dump file
55
+ dump.rdb
56
+
57
+ # .ruby-gemset e .ruby-version nas engines
58
+ engines/**/.ruby-*
59
+
60
+ .editorconfig
61
+ tags
62
+ .byebug_history
63
+
64
+ .idea
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --color
2
+ --require spec_helper
3
+ --drb
4
+ --format doc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in event.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,94 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ event-pub-sub (1.1.6)
5
+ activesupport (= 4.2.5.2)
6
+ bunny (= 2.3.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activesupport (4.2.5.2)
12
+ i18n (~> 0.7)
13
+ json (~> 1.7, >= 1.7.7)
14
+ minitest (~> 5.1)
15
+ thread_safe (~> 0.3, >= 0.3.4)
16
+ tzinfo (~> 1.1)
17
+ amq-protocol (2.0.1)
18
+ bunny (2.3.0)
19
+ amq-protocol (>= 2.0.1)
20
+ byebug (8.2.1)
21
+ celluloid (0.16.0)
22
+ timers (~> 4.0.0)
23
+ coderay (1.1.0)
24
+ diff-lcs (1.2.5)
25
+ ffi (1.9.6)
26
+ formatador (0.2.5)
27
+ guard (2.11.1)
28
+ formatador (>= 0.2.4)
29
+ listen (~> 2.7)
30
+ lumberjack (~> 1.0)
31
+ nenv (~> 0.1)
32
+ notiffany (~> 0.0)
33
+ pry (>= 0.9.12)
34
+ shellany (~> 0.0)
35
+ thor (>= 0.18.1)
36
+ guard-compat (1.2.1)
37
+ guard-rspec (4.5.0)
38
+ guard (~> 2.1)
39
+ guard-compat (~> 1.1)
40
+ rspec (>= 2.99.0, < 4.0)
41
+ hitimes (1.2.2)
42
+ i18n (0.7.0)
43
+ json (1.8.3)
44
+ listen (2.8.5)
45
+ celluloid (>= 0.15.2)
46
+ rb-fsevent (>= 0.9.3)
47
+ rb-inotify (>= 0.9)
48
+ lumberjack (1.0.9)
49
+ method_source (0.8.2)
50
+ minitest (5.8.4)
51
+ nenv (0.2.0)
52
+ notiffany (0.0.3)
53
+ nenv (~> 0.1)
54
+ shellany (~> 0.0)
55
+ pry (0.10.1)
56
+ coderay (~> 1.1.0)
57
+ method_source (~> 0.8.1)
58
+ slop (~> 3.4)
59
+ rake (10.4.2)
60
+ rb-fsevent (0.9.4)
61
+ rb-inotify (0.9.5)
62
+ ffi (>= 0.5.0)
63
+ rspec (3.2.0)
64
+ rspec-core (~> 3.2.0)
65
+ rspec-expectations (~> 3.2.0)
66
+ rspec-mocks (~> 3.2.0)
67
+ rspec-core (3.2.0)
68
+ rspec-support (~> 3.2.0)
69
+ rspec-expectations (3.2.0)
70
+ diff-lcs (>= 1.2.0, < 2.0)
71
+ rspec-support (~> 3.2.0)
72
+ rspec-mocks (3.2.0)
73
+ diff-lcs (>= 1.2.0, < 2.0)
74
+ rspec-support (~> 3.2.0)
75
+ rspec-support (3.2.1)
76
+ shellany (0.0.1)
77
+ slop (3.6.0)
78
+ thor (0.19.1)
79
+ thread_safe (0.3.5)
80
+ timers (4.0.1)
81
+ hitimes
82
+ tzinfo (1.2.2)
83
+ thread_safe (~> 0.1)
84
+
85
+ PLATFORMS
86
+ ruby
87
+
88
+ DEPENDENCIES
89
+ bundler (~> 1.7)
90
+ byebug (= 8.2.1)
91
+ event-pub-sub!
92
+ guard-rspec (= 4.5.0)
93
+ rake (~> 10.0)
94
+ rspec (= 3.2.0)
data/Guardfile ADDED
@@ -0,0 +1,51 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ #directories %w(lib config spec)
6
+
7
+ ## Uncomment to clear the screen before every task
8
+ # clearing :on
9
+
10
+ ## Guard internally checks for changes in the Guardfile and exits.
11
+ ## If you want Guard to automatically start up again, run guard in a
12
+ ## shell loop, e.g.:
13
+ ##
14
+ ## $ while bundle exec guard; do echo "Restarting Guard..."; done
15
+ ##
16
+ ## Note: if you are using the `directories` clause above and you are not
17
+ ## watching the project directory ('.'), the you will want to move the Guardfile
18
+ ## to a watched dir and symlink it back, e.g.
19
+ #
20
+ # $ mkdir config
21
+ # $ mv Guardfile config/
22
+ # $ ln -s config/Guardfile .
23
+ #
24
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
25
+
26
+ # Note: The cmd option is now required due to the increasing number of ways
27
+ # rspec may be run, below are examples of the most common uses.
28
+ # * bundler: 'bundle exec rspec'
29
+ # * bundler binstubs: 'bin/rspec'
30
+ # * spring: 'bin/rspec' (This will use spring if running and you have
31
+ # installed the spring binstubs per the docs)
32
+ # * zeus: 'zeus rspec' (requires the server to be started separately)
33
+ # * 'just' rspec: 'rspec'
34
+
35
+ guard :rspec, cmd: "bundle exec rspec" do
36
+ watch(%r{^lib/(.+)\.rb$}) do |m|
37
+ [
38
+ "spec/unit/#{m[1]}_spec.rb",
39
+ "spec/integration/#{m[1]}_spec.rb"
40
+ ]
41
+ end
42
+ #models
43
+ watch(%r{^lib/event/(.+)\.rb$}) do |m|
44
+ [
45
+ "spec/unit/#{m[1]}_spec.rb",
46
+ "spec/integration/#{m[1]}_spec.rb"
47
+ ]
48
+ end
49
+
50
+ watch(%r{^spec/.+_spec\.rb$})
51
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Sergio Azevedo
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,167 @@
1
+ [![Build Status](https://semaphoreapp.com/api/v1/projects/3b801a94-a652-4c1d-b347-ff6006adaf43/364951/shields_badge.svg)](https://semaphoreapp.com/darkseid/event)
2
+ # Event
3
+
4
+ O objetivo desta GEM é permitir que as Engines que compõem a nova Plataforma da Estante Virutal possam se comunicar sem que estas precisem "se conhecer", garantindo assim um baixo acoplamento entre as Engines.
5
+
6
+ A solução é baseada no pattern Publish-Subscribe Channel descrito pelo Fowler em seu livro Enterprise Integration Patterns. No caso, o papel do MessageChannel será exercido pelo RabbitMQ.
7
+
8
+ ## Instalação
9
+
10
+ Como dito anteriormente, esta gem utiliza o RabbitMQ. Por isso precisamos ter esta dependência instalada. Para realizar a instalação basta seguir o passo a passo descrito neste [link](https://www.rabbitmq.com/download.html)
11
+
12
+ Depois, você precisa adicionar um novo source ao seu Gemfile. Este novo source deve ser a primeira linha do seu Gemfile:
13
+
14
+ ```ruby
15
+ source 'https://repo.fury.io/sergioazevedo'
16
+ source 'https://rubygems.org'
17
+ ```
18
+
19
+ Se vc estiver instalando em uma Engine deve alterar o arquivo 'suaengine.gemspec' e adicionar a dependencia
20
+
21
+ ```ruby
22
+ s.add_dependency "event","~>1.0.0"
23
+ ```
24
+
25
+ Caso seja um projeto Ruby normal ou uma Rails app adicione a linha abaixo no seu Gemfile:
26
+
27
+ ```ruby
28
+ gem "event","~>1.0.0"
29
+ ```
30
+
31
+ E executar:
32
+ $ bundle
33
+
34
+ ## Configuração
35
+ Os arquivos abaixo são necessários para se configurar esta gem.
36
+ ```
37
+ config/event.yml
38
+ config/initializes/setup_event.rb
39
+ ```
40
+
41
+ Para gerá-los basta rodar a rake task: ```rake app:event:install```.
42
+
43
+ ####config/event.yml
44
+ Neste arquivo você deve fornecer as configuracoes para conexão com o Broker RabbitMQ.
45
+ Mas este arquivo contém uma configuração muito importante, e está na chave: **base_routing_key**. Você **precisa** usar nesta chave o nome da sua engine _(ou algo semelhante, que identifique o módulo)_.
46
+ Exemplo:
47
+ Imagine o modulo de Ecommerce
48
+
49
+ ```yaml
50
+ development:
51
+ base_routing_key: ecommerce
52
+ broker:
53
+ ip: localhost
54
+ port: 5672
55
+ username: guest
56
+ password: guest
57
+ ```
58
+
59
+ ####config/initializers/setup_event.rb
60
+ Você só vai precisar alterar este arquivo no caso de querer "assinar" algum evento.
61
+
62
+ ## Utilização
63
+
64
+ ### Publicando Eventos / Enviando mensagens
65
+ Publicar eventos é muito fácil, basta usar Event.pubish.
66
+
67
+ ```ruby
68
+ Event.publish(:sku_added, name: 'Caneta Azul', price: 1.99, qty: 10 )
69
+ ```
70
+ No exempo acima o nome do evento é **:sku_added** e os dados do evento estão no hash: **{name: 'Caneta Azul', price: 1.99, qty: 10}**
71
+
72
+ ###Sobre os Eventos
73
+ Eventos são sempre coisas que já aconteceram, por este motivo é de boa prática que os nomes dos eventos descrevam claramente que fato ocorreu e com quem. Exemplos abaixo:
74
+ - Um produto novo sku foi adicionado - :new_product_added
75
+ - Um sku novo foi adicionado - :new_sku_added
76
+ - Um sku foi vendido - :sku_saled
77
+ - Produto teve seu preço alterado - product_price_updated
78
+
79
+ Sobre os dados do evento, isto fica a cargo de quem publica o evento. Mas em geral é bacana enviar informações sobre o contexto do evento.
80
+
81
+ Exemplo:
82
+
83
+ - Um sku foi vendido
84
+ ```ruby
85
+ Event.publish(:sku_saled, sku_id: 10 )
86
+ ```
87
+ - Preço de um sku foi alterado
88
+ ```ruby
89
+ Event.publish(:sku_price_changed, sku_id: 10, old_price: 1.99, new_price: 2.87 )
90
+ ```
91
+
92
+ ### Assinando os Eventos / Recebendo mensagens
93
+
94
+ Assinar eventos é um processo de duas etapas:
95
+
96
+ 1. Escrever uma classe Listener para o evento desejado
97
+ 2. Registrar o Listener para o evento desejado em config/initializes/setup_event.rb
98
+
99
+ ####1. Escrever uma classe Listener para o evento desejado
100
+ Como dito antes você vai precisar escrever uma classe para cada listener que desejar.
101
+ Esta classe não precisa herdar de nada, basta que ela tenha os métodos **#initialize** e **notify**. O Listener é como um [Observer _GoF_](http://en.wikipedia.org/wiki/Observer_pattern).
102
+
103
+ Atenção, o listener deve receber toda a informação necessária para sua excução no método de inicialização (new), ou seja, os dados do evento/mensagem.
104
+
105
+ Exemplo de Listener:
106
+
107
+ Considere a mensagem abaixo:
108
+
109
+ ```ruby
110
+ Event.publish(:sku_price_changed, sku_id: 10, old_price: 1.99, new_price: 2.87 )
111
+ ```
112
+
113
+
114
+ ```ruby
115
+ class SkuPriceChangedListener
116
+ def initialize(data={})
117
+ @sku_id = data[:sku_id]
118
+ @old_price = data[:old_price]
119
+ @new_price = data[:new_price]
120
+ end
121
+
122
+ def notify
123
+ #aqui vai o seu código.
124
+ #vc pode, e em geral vai acontecer isso, instanciar um UseCase e executa-lo.
125
+ end
126
+ end
127
+ ````
128
+
129
+ ##### As Operações executadas por um listener devem ser Idempotentes sempre!!!
130
+ Por razões de segurança, e para garantia da consistencia dos nossos dados, as operações realizadas por um Listener deve ser idempontentes.
131
+
132
+ >Idempotente quer dizer que múltiplas requisições ao mesmo recurso usando o método devem ter o mesmo resultado que teria uma requisição apenas. A título de curiosidade, idempotente é a propriedade de um número que, multiplicado por ele mesmo, tem ele mesmo como resultado (n x n = n), em termos de números reais, apenas 0 e 1 têm essa propriedade. Em termos de métodos de requisição HTTP, os métodos GET, HEAD, PUT e DELETE são os que possuem a propriedade de ser idempotentes
133
+ - <cite>[Dicionario Informal](http://www.dicionarioinformal.com.br/idempotente/)</cite>
134
+
135
+ ##### Onde colocar meus listeners
136
+ Em geral, costuma-se criar dentro de app/ uma pasta chamada listeners ou event_listeners.
137
+
138
+ ####2. Registrar o Listener para o evento
139
+ No arquivo setup_events.rb existe uma seção dedicada ao registro dos listeners.
140
+ Esta seção vem toda comentada por padrão, veja:
141
+ ```ruby
142
+ # Register your listeners Here!!!! Example:
143
+ # Event.register_listeners do |config|
144
+ # config.add_listeners(:event_name, ['EventNameListener'])
145
+ # config.add_listeners(:another_event_name, ['AnotherEventListener1', 'Listner2'])
146
+ # end
147
+ ```
148
+ Basta descomentar e seguir como no exemplo. Imaginando que queremos registrar o nosso SkuPriceChangedListener, esta configuracao ficaria assim:
149
+
150
+ ```ruby
151
+ # Register your listeners Here!!!! Example:
152
+ Event.register_listeners do |config|
153
+ config.add_listeners(:sku_price_changed, ['SkuPriceChanged'])
154
+ end
155
+ ```
156
+
157
+ **Note que você sempre deve fornecer o nome do Listener com uma String dentro de um Array.**
158
+
159
+ **Observação:** Como este arquivo setup_events.rb é carregado na inicialização da aplicação, toda vez que você registrar um evento novo vai precisar reinicar a app.
160
+
161
+
162
+ ## Contributing
163
+ 1. Fork it ( https://github.com/[my-github-username]/event/fork )
164
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
165
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
166
+ 4. Push to the branch (`git push origin my-new-feature`)
167
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+ # coding: utf-8
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'event_pub_sub/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'event-pub-sub'
9
+ spec.version = EventPubSub::VERSION
10
+ spec.authors = ['Estante Virutal']
11
+ spec.email = ['equipe_ti@estantevirtual.com.br']
12
+ spec.summary = %q{Pub/Sub de Eventos baseado em RabbitMQ.}
13
+ spec.description = %q{Pub/Sub de Eventos baseado em RabbitMQ.}
14
+ spec.homepage = 'http://www.estantevirtual.com.br'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'bunny', '2.3.0'
22
+ spec.add_dependency 'activesupport', '4.2.5.2'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.7'
25
+ spec.add_development_dependency 'rake', '~> 10.0'
26
+ spec.add_development_dependency 'rspec', '3.2.0'
27
+ spec.add_development_dependency 'guard-rspec', '4.5.0'
28
+ spec.add_development_dependency 'byebug', '8.2.1'
29
+
30
+ end
@@ -0,0 +1,31 @@
1
+ development:
2
+ base_routing_key: module_name
3
+ broker:
4
+ ip: localhost
5
+ port: 5672
6
+ username: guest
7
+ password: guest
8
+
9
+ test:
10
+ base_routing_key: module_name
11
+ broker:
12
+ ip: localhost
13
+ port: 5672
14
+ username: guest
15
+ password: guest
16
+
17
+ staging:
18
+ base_routing_key: module_name
19
+ broker:
20
+ ip: <%=ENV['BROKER_IP'] %>
21
+ port: <%=ENV['BROKER_PORT'] %>
22
+ username: <%=ENV['BROKER_USERNAME'] %>
23
+ password: <%=ENV['BROKER_PASSWORD'] %>
24
+
25
+ production:
26
+ base_routing_key: module_name
27
+ broker:
28
+ ip: <%=ENV['BROKER_IP'] %>
29
+ port: <%=ENV['BROKER_PORT'] %>
30
+ username: <%=ENV['BROKER_USERNAME'] %>
31
+ password: <%=ENV['BROKER_PASSWORD'] %>
@@ -0,0 +1,26 @@
1
+ # require 'event'
2
+ # require 'yaml'
3
+
4
+ # module YourModuleNameHere
5
+ # class Event
6
+ # broker_data = File.read( File.expand_path('../../event.yml',__FILE__) )
7
+ # broker_config = YAML.load(ERB.new(broker_data).result).with_indifferent_access
8
+ # @@message_producer = ::Event::MessageProducer.new(broker_config[Rails.env], Rails.logger)
9
+
10
+ # if !Rails.env.test?
11
+ # listener_data = File.read( File.expand_path('../../listeners.yml',__FILE__) )
12
+ # listeners = YAML.load(listener_data).with_indifferent_access
13
+
14
+ # if listeners.any?
15
+ # Thread.new do
16
+ # consumer = ::Event::MessageConsumer.new(broker_config[Rails.env], Rails.logger)
17
+ # consumer.execute(listeners)
18
+ # end
19
+ # end
20
+ # end
21
+
22
+ # def self.publish(event_name, data={})
23
+ # @@message_producer.publish(event_name.to_sym, data)
24
+ # end
25
+ # end
26
+ # end
@@ -0,0 +1,7 @@
1
+ #event: ['ClassName']
2
+ #event: ['Module::ClassName']
3
+ ### - Se vc tiver um caso onde um ou mais listeners precisam ser executados para qualquer evento,
4
+ ### ou seja, se indepentende do evento que aconteceu vc quer que aquele listener rode use a sintaxe abaixo:
5
+ #any_event: [ClassName]
6
+
7
+ ##PS: as sintaxes acimma nao são excludentes, vc pode usar as duas em conjunto
@@ -0,0 +1,14 @@
1
+ require 'time'
2
+ require 'bunny'
3
+ require 'logger'
4
+ require "event_pub_sub/version"
5
+ require 'event_pub_sub/broker_handler'
6
+ require 'event_pub_sub/message_producer'
7
+ require 'event_pub_sub/message_consumer'
8
+ require 'event_pub_sub/listener'
9
+ require 'json'
10
+ require 'securerandom'
11
+
12
+ module EventPubSub
13
+
14
+ end
@@ -0,0 +1,65 @@
1
+ module EventPubSub
2
+ class BrokerHandler
3
+
4
+ def initialize(config, logger)
5
+ raise ArgumentError, "missing broker ip" unless config[:ip]
6
+ raise ArgumentError, "missing broker port" unless config[:port]
7
+ raise ArgumentError, "missing broker username" unless config[:username]
8
+ raise ArgumentError, "missing broker password" unless config[:password]
9
+ @config = config
10
+ @logger = logger
11
+ end
12
+
13
+ def start_connection
14
+ @connection = build_connection
15
+ @connection.start
16
+ rescue => e
17
+ @logger.error "#{e.message} - #{e.class}\n #{e.backtrace.join("\n")}"
18
+ end
19
+
20
+ def close_connection
21
+ @connection.close
22
+ end
23
+
24
+ def publish(message, routing_key)
25
+ topic.publish( message, persistent: true, routing_key: routing_key )
26
+ end
27
+
28
+ def setup_queue(queue_name)
29
+ @queue = channel.queue(queue_name, durable: true, auto_delete: false)
30
+ @queue.bind(topic, routing_key: '#')
31
+ end
32
+
33
+ def subscribe(consumer_name, params={ack: true, block: true}, &block)
34
+ params[:consumer_tag] = consumer_name
35
+ @queue.subscribe(params) do |delivery_info, properties, payload|
36
+ begin
37
+ block.call(delivery_info, properties, payload)
38
+ channel.ack(delivery_info.delivery_tag)
39
+ rescue => e
40
+ channel.nack(delivery_info.delivery_tag, false, true)
41
+ raise e
42
+ end
43
+ end
44
+ end
45
+
46
+ private
47
+ def build_connection
48
+ Bunny.new(
49
+ host: @config[:ip],
50
+ port: @config[:port],
51
+ user: @config[:username],
52
+ pass: @config[:password]
53
+ )
54
+ end
55
+
56
+ def topic
57
+ @topic ||= channel.topic('topic_events', durable: true)
58
+ end
59
+
60
+
61
+ def channel
62
+ @channel ||= @connection.create_channel
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,7 @@
1
+ module EventPubSub
2
+ class Listener
3
+ def notify
4
+ fail NotImplementedError, "You must implement notify method in #{self.class}"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,65 @@
1
+ module EventPubSub
2
+ class MessageConsumer
3
+ def initialize(config, logger)
4
+ raise ArgumentError, "missing module base_routing_key " unless config[:base_routing_key]
5
+ @queue_name = config[:base_routing_key]
6
+ @logger = logger
7
+ @broker_handler = BrokerHandler.new(config[:broker], @logger)
8
+ @logger.info '[MessageConsumer] - Starting Connection'
9
+ @broker_handler.start_connection
10
+ @broker_handler.setup_queue(@queue_name)
11
+ end
12
+
13
+ def execute(all_listeners)
14
+ @logger.info '[MessageConsumer] - Waiting Messages...'
15
+ consumer_name = "#{@queue_name}_event_consumer"
16
+ @broker_handler.subscribe(consumer_name) do |delivery_info, properties, payload|
17
+ message = JSON.parse(payload).with_indifferent_access
18
+ event_name = message['event_name']
19
+ @logger.debug "[MessageConsumer] - Message Received: #{event_name}"
20
+ listeners_to_execute = get_listeners_of(event_name, all_listeners)
21
+ fire_listeners(listeners_to_execute, message)
22
+ end
23
+ end
24
+
25
+ def close_connection
26
+ @logger.info '[MessageConsumer] - Closing Connection'
27
+ @broker_handler.close_conection
28
+ end
29
+
30
+ def get_listeners_of(event_name, listeners_definitions)
31
+ listeners = listeners_definitions[event_name.to_sym] || []
32
+ if has_mappings_for_any_event?(listeners_definitions)
33
+ listeners.concat get_listeners_for_any_event(listeners_definitions)
34
+ end
35
+
36
+ listeners
37
+ end
38
+
39
+ private
40
+ def fire_listeners(listeners_to_execute, data)
41
+ if listeners_to_execute
42
+ listeners_to_execute.each do |listener_klass_name|
43
+ @logger.info "[Event Handling] - using listener class '#{listener_klass_name}'"
44
+ @logger.debug "[Event Handling] - notify event '#{@event_name}' using listener class '#{listener_klass_name}' with args '#{data}'"
45
+ begin
46
+ listener_klass = Object.const_get(listener_klass_name)
47
+ listener_klass.new(data).notify
48
+ rescue => e
49
+ @logger.error "[Event Handling] - #{e} \n #{e.backtrace.join("\n")}"
50
+ raise e
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ def has_mappings_for_any_event?(listeners_definitions)
57
+ listeners_definitions[:any_event] && listeners_definitions[:any_event].any?
58
+ end
59
+
60
+ def get_listeners_for_any_event(listeners_definitions)
61
+ listeners_definitions[:any_event]
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,36 @@
1
+ module EventPubSub
2
+ class MessageProducer
3
+ def initialize(config, logger)
4
+ raise ArgumentError, "missing module base_routing_key " unless config[:base_routing_key]
5
+ @base_routing_key = config[:base_routing_key]
6
+ @logger = logger
7
+
8
+ @broker_handler = BrokerHandler.new(config[:broker], @logger)
9
+ @logger.info '[MessageProducer] - Starting Connection'
10
+ @broker_handler.start_connection
11
+ end
12
+
13
+ def publish(event_name, msg={})
14
+ key = routing_key(event_name)
15
+ enrich_message(event_name, msg)
16
+ @logger.info "[MessageProducer] - Sending event: #{event_name}"
17
+ @logger.debug "[MessageProducer] - Sending event: #{event_name} with data: #{msg.inspect} using as routing_key: #{key}"
18
+ @broker_handler.publish( JSON.generate(msg), key )
19
+ end
20
+
21
+ private
22
+ def routing_key(event_name)
23
+ "#{@base_routing_key}.#{event_name}"
24
+ end
25
+
26
+ def enrich_message(event_name, msg)
27
+ msg[:event_id] = SecureRandom.uuid
28
+ msg[:event_name] = event_name
29
+ if defined?(Rails)
30
+ msg[:event_date] = Time.zone.now
31
+ else
32
+ msg[:event_date] = Time.now.utc
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,11 @@
1
+ require 'event'
2
+ require 'rails'
3
+ module EventPubSub
4
+ class Railtie < Rails::Railtie
5
+ railtie_name :event_bus
6
+
7
+ rake_tasks do
8
+ load "tasks/event_tasks.rake"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module EventPubSub
2
+ VERSION = "1.1.6"
3
+ end
@@ -0,0 +1,21 @@
1
+ require 'fileutils'
2
+ namespace :event do
3
+ desc "Installs required stuff to event"
4
+ task :install do
5
+ Rails.logger = Logger.new(STDOUT)
6
+ source = File.join(Gem.loaded_specs["event"].full_gem_path, "lib/config", "event.yml")
7
+ target = File.join("config", "event.yml")
8
+ Rails.logger.info "Creating file #{target}"
9
+ FileUtils.cp_r(source, target)
10
+
11
+ source = File.join(Gem.loaded_specs["event"].full_gem_path, "lib/config", "listeners.yml")
12
+ target = File.join("config", "listeners.yml")
13
+ Rails.logger.info "Creating file #{target}"
14
+ FileUtils.cp_r(source, target)
15
+
16
+ source = File.join(Gem.loaded_specs["event"].full_gem_path, "lib/config/initializers", "setup_event.rb")
17
+ target = File.join("config/initializers", "setup_event.rb")
18
+ Rails.logger.info "Creating file #{target}"
19
+ FileUtils.cp_r(source, target)
20
+ end
21
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+ module EventPubSub
3
+ describe BrokerHandler do
4
+ let(:logger){ double('logger', debug: true)}
5
+ let(:running_server_config) do
6
+ {
7
+ ip: "localhost",
8
+ port: "5672",
9
+ username: "guest",
10
+ password: "guest",
11
+ }
12
+ end
13
+
14
+ let(:stopped_server_config) do
15
+ {
16
+ ip: "localhost",
17
+ port: "4000",
18
+ username: "guest",
19
+ password: "guest",
20
+ }
21
+ end
22
+
23
+ describe "#start_connection" do
24
+ context "given a up and running RabbitMQ server at localhost:5672" do
25
+ subject{ BrokerHandler.new(running_server_config, logger) }
26
+ it "stabilish connection" do
27
+ expect{subject.start_connection}.to_not raise_error
28
+ end
29
+ end
30
+
31
+ context "given a stoped RabbitMQ server" do
32
+ subject{ BrokerHandler.new(stopped_server_config, logger) }
33
+ it "raise error" do
34
+ expect{ subject.start_connection }.to raise_error
35
+ end
36
+ end
37
+ end
38
+
39
+ describe "#close_connection" do
40
+ context "given a up and running RabbitMQ server at localhost:5672" do
41
+ subject{ BrokerHandler.new(running_server_config, logger) }
42
+
43
+ it "closes connection" do
44
+ subject.start_connection
45
+ expect{subject.close_connection}.to_not raise_error
46
+ end
47
+
48
+ it "closes the channel" do
49
+ channel = subject.start_connection
50
+ expect(channel).to receive(:close).once
51
+ subject.close_connection
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "#publish" do
57
+ context "given a up and running RabbitMQ server at localhost:5672" do
58
+ subject do
59
+ bus = BrokerHandler.new(running_server_config, logger)
60
+ bus.start_connection
61
+
62
+ bus
63
+ end
64
+ it "publish the event using base_routing_key" do
65
+ expect{ subject.publish( "'data': 'sample data'", 'routing.key') }.to_not raise_error
66
+ end
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+
@@ -0,0 +1,6 @@
1
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
2
+ require 'bundler'
3
+ Bundler.setup(:default, :test)
4
+ require 'event_pub_sub'
5
+ require 'pry'
6
+ require 'byebug'
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ module EventPubSub
4
+ describe BrokerHandler do
5
+ let(:logger) { double(:log, debug: true) }
6
+ let(:config) do
7
+ {
8
+ ip: "localhost",
9
+ port: "5672",
10
+ username: "guest",
11
+ password: "guest"
12
+ }
13
+ end
14
+
15
+ describe "API" do
16
+ subject{ BrokerHandler.new(config, logger)}
17
+ it { should respond_to :start_connection }
18
+ it { should respond_to :publish }
19
+ it { should respond_to :close_connection }
20
+ end
21
+
22
+ describe "initialize" do
23
+ it "raise Argument Error when no config is given" do
24
+ expect{BrokerHandler.new}.to raise_error ArgumentError
25
+ end
26
+
27
+ it "raise ArgumentError error with a invalid config" do
28
+ expect{BrokerHandler.new('aaaaa')}.to raise_error ArgumentError
29
+ end
30
+
31
+ it "raise ArgumentError error with a incomplete config" do
32
+ expect{BrokerHandler.new({})}.to raise_error ArgumentError
33
+ expect{BrokerHandler.new({ip: 1})}.to raise_error ArgumentError
34
+ expect{BrokerHandler.new({ip: 1, port: 2})}.to raise_error ArgumentError
35
+ expect{BrokerHandler.new({ip: 1, port: 2, username: 'a'})}.to raise_error ArgumentError
36
+ end
37
+
38
+ it "not raise error with a valid config" do
39
+ expect{BrokerHandler.new(config, logger)}.to_not raise_error
40
+ end
41
+ end
42
+
43
+ describe "#start_connection" do
44
+ context "Given a RabbitMQ Broker and a BrokerHandler with valid configuration" do
45
+ let(:mocked_rabbitmq_lib){double}
46
+ let(:connection){ double }
47
+ subject{ BrokerHandler.new(config, logger) }
48
+
49
+ it "returns a RabbitMQ Connection" do
50
+ expect(subject).to receive(:build_connection).once.and_return(mocked_rabbitmq_lib)
51
+ expect(mocked_rabbitmq_lib).to receive(:start).once.and_return(connection)
52
+ expect(subject.start_connection).to be connection
53
+ end
54
+ end
55
+ end
56
+
57
+ describe "#close_connection" do
58
+ context "Given BrokerHandler with a open connection" do
59
+ let(:mocked_rabbitmq_lib){double}
60
+ let(:connection){ double }
61
+
62
+ before do
63
+ allow(subject).to receive(:build_connection).and_return(mocked_rabbitmq_lib)
64
+ allow(mocked_rabbitmq_lib).to receive(:start).once.and_return(connection)
65
+ end
66
+
67
+ subject{ BrokerHandler.new(config, logger) }
68
+
69
+ it "closes a RabbitMQ Connection" do
70
+ subject.start_connection
71
+ expect(mocked_rabbitmq_lib).to receive(:close).once
72
+ subject.close_connection
73
+ end
74
+ end
75
+ end
76
+
77
+ describe "#publish" do
78
+ context "given a up and running RabbitMQ server at localhost:5672" do
79
+ let(:mocked_rabbitmq_lib){double(:bunny_mock)}
80
+ let(:channel){double(:channel, topic: true)}
81
+ let(:connection){double(:connection_mock)}
82
+ let(:topic){double(:topic_mock)}
83
+ before do
84
+ allow(subject).to receive(:build_connection).and_return(mocked_rabbitmq_lib)
85
+ allow(mocked_rabbitmq_lib).to receive(:start).once.and_return(connection)
86
+ allow(mocked_rabbitmq_lib).to receive(:create_channel).and_return(channel)
87
+ allow(channel).to receive(:topic).and_return(topic)
88
+ end
89
+ subject{ BrokerHandler.new(config, logger) }
90
+
91
+ it "publish the event using base_routing_key" do
92
+ subject.start_connection
93
+ expect(topic).to receive(:publish).once
94
+ subject.publish('message', 'routing.key')
95
+ end
96
+ end
97
+ end
98
+
99
+
100
+ end
101
+ end
102
+
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ module EventPubSub
4
+ describe Listener do
5
+ describe "api" do
6
+ it { is_expected.to respond_to :notify }
7
+ end
8
+
9
+ describe "#notify" do
10
+ it "raises NotImplementedError in order to remember the developer to override this operation on subclasses" do
11
+ expect{suject.notify}.to raise_error
12
+ end
13
+ end
14
+ end
15
+ end
16
+
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ module EventPubSub
4
+
5
+ describe MessageConsumer do
6
+ let(:logger) { double(:log, debug: true, info: true) }
7
+ let(:config) do
8
+ { broker: {
9
+ ip: "localhost",
10
+ port: "5672",
11
+ username: "guest",
12
+ password: "guest"
13
+ },
14
+ base_routing_key: "module_name"
15
+ }
16
+ end
17
+
18
+ describe "API" do
19
+ subject{ MessageConsumer.new(config, logger) }
20
+ it { should respond_to(:execute) }
21
+ it { should respond_to(:get_listeners_of) }
22
+ end
23
+
24
+ describe ".initialize" do
25
+ it "raise ArgumentError when no config was given" do
26
+ expect{ MessageConsumer.new }.to raise_error(ArgumentError)
27
+ end
28
+
29
+ it "raise ArgumentError if invalid config was given" do
30
+ expect{ MessageConsumer.new({}) }.to raise_error(ArgumentError)
31
+ end
32
+
33
+ it "no raise error if a valid config was given" do
34
+ expect{ MessageConsumer.new(config, logger) }.to_not raise_error
35
+ end
36
+ end
37
+
38
+ describe "#get_listeners_of" do
39
+ context "Given a event called new_sku_added with ExampleListener class associated" do
40
+ let(:listener_definitions) do
41
+ { new_sku_added: ["ExampleListenerClass"] }
42
+ end
43
+
44
+ subject{ MessageConsumer.new(config, logger) }
45
+
46
+ it "returns [ExampleListenerClass]" do
47
+ result = subject.get_listeners_of('new_sku_added', listener_definitions)
48
+ expect(result).to eql ['ExampleListenerClass']
49
+ end
50
+ end
51
+
52
+ context "Given a listener called AllEventsListener mapped for any event" do
53
+ let(:listener_definitions) do
54
+ { any_event: ["AllEventListenerClass"] }
55
+ end
56
+
57
+ subject{ MessageConsumer.new(config, logger) }
58
+
59
+ it "returns [AllEventListenerClass]" do
60
+ result = subject.get_listeners_of('foo_bar_updated', listener_definitions)
61
+ expect(result).to eql ['AllEventListenerClass']
62
+ end
63
+ end
64
+
65
+ context "Given a listener called AllEventsListener mapped for any event and new_sku_added mapped to ExampleListener" do
66
+ let(:listener_definitions) do
67
+ { new_sku_added: ["ExampleListenerClass"], any_event: ["AllEventListenerClass"] }
68
+ end
69
+
70
+ subject{ MessageConsumer.new(config, logger) }
71
+
72
+ it "for 'new_sku_added' event returns [ExampleListenerClass, AllEventListenerClass]" do
73
+ result = subject.get_listeners_of('new_sku_added', listener_definitions)
74
+ expect(result).to eql ['ExampleListenerClass', 'AllEventListenerClass']
75
+ end
76
+
77
+ it "for 'product_selled' event returns [AllEventListenerClass]" do
78
+ result = subject.get_listeners_of('product_selled', listener_definitions)
79
+ expect(result).to eql ['AllEventListenerClass']
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+ module EventPubSub
3
+ describe MessageProducer do
4
+ let(:logger) { double(:log, debug: true, info: true) }
5
+ let(:config) do
6
+ {
7
+ broker: {
8
+ ip: "localhost",
9
+ port: "5672",
10
+ username: "guest",
11
+ password: "guest"
12
+ },
13
+ base_routing_key: "module_name"
14
+ }
15
+ end
16
+
17
+ describe "API" do
18
+ subject{ MessageProducer.new(config, logger)}
19
+ it { should respond_to :publish }
20
+ end
21
+
22
+ describe "initialize" do
23
+ it "raise Argument Error when no config is given" do
24
+ expect{MessageProducer.new}.to raise_error ArgumentError
25
+ end
26
+
27
+ it "raise ArgumentError error with a invalid config" do
28
+ expect{MessageProducer.new('aaaaa')}.to raise_error ArgumentError
29
+ end
30
+
31
+ it "raise ArgumentError error with a incomplete config" do
32
+ expect{MessageProducer.new({})}.to raise_error ArgumentError
33
+ expect{MessageProducer.new({ip: 1})}.to raise_error ArgumentError
34
+ expect{MessageProducer.new({ip: 1, port: 2})}.to raise_error ArgumentError
35
+ expect{MessageProducer.new({ip: 1, port: 2, username: 'a'})}.to raise_error ArgumentError
36
+ expect{MessageProducer.new({ip: 1, port: 2, username: 'a', password: "123"})}.to raise_error ArgumentError
37
+ end
38
+
39
+ it "not raise error with a valid config" do
40
+ expect{MessageProducer.new(config, logger)}.to_not raise_error
41
+ end
42
+ end
43
+
44
+ describe "#publish" do
45
+ context "Given a event named 'sku_created' with data => {code: 10, price: 20.87, product_id: 2}" do
46
+ let(:event_name){ :sku_created }
47
+ let(:event_data) do
48
+ { code: 10, price: 20.87, product_id: 2, event_name: 'sku_created' }
49
+ end
50
+ let(:expected_message){ JSON.generate(event_data) }
51
+ let(:fake_broker){double('broker', start_connection: true )}
52
+
53
+ subject{ MessageProducer.new(config, logger)}
54
+
55
+ it "calls BrokerHandler#publish with message => {code: 10, price: 20.87, product_id: 2} and routing_key => module_name.sku_created" do
56
+ allow(BrokerHandler).to receive(:new).and_return fake_broker
57
+ expect(fake_broker).to receive(:publish).once
58
+ subject.publish(event_name, event_data)
59
+ end
60
+ end
61
+ end
62
+
63
+ end
64
+ end
65
+
metadata ADDED
@@ -0,0 +1,173 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: event-pub-sub
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.6
5
+ platform: ruby
6
+ authors:
7
+ - Estante Virutal
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-03-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bunny
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 2.3.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 2.3.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 4.2.5.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 4.2.5.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.7'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 3.2.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 3.2.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard-rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '='
88
+ - !ruby/object:Gem::Version
89
+ version: 4.5.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '='
95
+ - !ruby/object:Gem::Version
96
+ version: 4.5.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: byebug
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 8.2.1
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '='
109
+ - !ruby/object:Gem::Version
110
+ version: 8.2.1
111
+ description: Pub/Sub de Eventos baseado em RabbitMQ.
112
+ email:
113
+ - equipe_ti@estantevirtual.com.br
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rspec"
120
+ - Gemfile
121
+ - Gemfile.lock
122
+ - Guardfile
123
+ - LICENSE.txt
124
+ - README.md
125
+ - Rakefile
126
+ - event_pub_sub.gemspec
127
+ - lib/config/event.yml
128
+ - lib/config/initializers/setup_event.rb
129
+ - lib/config/listeners.yml
130
+ - lib/event_pub_sub.rb
131
+ - lib/event_pub_sub/broker_handler.rb
132
+ - lib/event_pub_sub/listener.rb
133
+ - lib/event_pub_sub/message_consumer.rb
134
+ - lib/event_pub_sub/message_producer.rb
135
+ - lib/event_pub_sub/railtie.rb
136
+ - lib/event_pub_sub/version.rb
137
+ - lib/tasks/event_tasks.rake
138
+ - spec/integration/broker_handler_spec.rb
139
+ - spec/spec_helper.rb
140
+ - spec/unit/broker_handler_spec.rb
141
+ - spec/unit/listener_spec.rb
142
+ - spec/unit/message_consumer_spec.rb
143
+ - spec/unit/message_producer_spec.rb
144
+ homepage: http://www.estantevirtual.com.br
145
+ licenses: []
146
+ metadata: {}
147
+ post_install_message:
148
+ rdoc_options: []
149
+ require_paths:
150
+ - lib
151
+ required_ruby_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ required_rubygems_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ requirements: []
162
+ rubyforge_project:
163
+ rubygems_version: 2.4.6
164
+ signing_key:
165
+ specification_version: 4
166
+ summary: Pub/Sub de Eventos baseado em RabbitMQ.
167
+ test_files:
168
+ - spec/integration/broker_handler_spec.rb
169
+ - spec/spec_helper.rb
170
+ - spec/unit/broker_handler_spec.rb
171
+ - spec/unit/listener_spec.rb
172
+ - spec/unit/message_consumer_spec.rb
173
+ - spec/unit/message_producer_spec.rb