liebre 0.1.3

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 (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +51 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +47 -0
  5. data/LICENSE +22 -0
  6. data/README.md +268 -0
  7. data/lib/liebre.rb +24 -0
  8. data/lib/liebre/common.rb +7 -0
  9. data/lib/liebre/common/utils.rb +24 -0
  10. data/lib/liebre/config.rb +48 -0
  11. data/lib/liebre/connection_manager.rb +64 -0
  12. data/lib/liebre/publisher.rb +88 -0
  13. data/lib/liebre/runner.rb +59 -0
  14. data/lib/liebre/runner/consumers.rb +36 -0
  15. data/lib/liebre/runner/starter.rb +40 -0
  16. data/lib/liebre/runner/starter/consumer.rb +91 -0
  17. data/lib/liebre/runner/starter/consumer/handler.rb +35 -0
  18. data/lib/liebre/runner/starter/resources.rb +39 -0
  19. data/lib/liebre/runner/starter/resources/queue_builder.rb +58 -0
  20. data/lib/liebre/runner/starter/rpc.rb +45 -0
  21. data/lib/liebre/tasks.rb +12 -0
  22. data/lib/liebre/version.rb +5 -0
  23. data/liebre.gemspec +26 -0
  24. data/spec/config/liebre.yml +47 -0
  25. data/spec/config/rabbitmq.yml +35 -0
  26. data/spec/integration_spec.rb +73 -0
  27. data/spec/liebre/config_spec.rb +62 -0
  28. data/spec/liebre/connection_manager_spec.rb +40 -0
  29. data/spec/liebre/publisher_spec.rb +86 -0
  30. data/spec/liebre/runner/consumers_spec.rb +59 -0
  31. data/spec/liebre/runner/starter/consumer_spec.rb +140 -0
  32. data/spec/liebre/runner/starter/resources/queue_builder_spec.rb +69 -0
  33. data/spec/liebre/runner/starter/resources_spec.rb +36 -0
  34. data/spec/liebre/runner/starter/rpc_spec.rb +92 -0
  35. data/spec/liebre/runner/starter_spec.rb +59 -0
  36. data/spec/liebre/runner_spec.rb +50 -0
  37. data/spec/spec_helper.rb +23 -0
  38. metadata +172 -0
@@ -0,0 +1,39 @@
1
+ module Liebre
2
+ class Runner
3
+ class Starter
4
+ class Resources
5
+ autoload :QueueBuilder, "liebre/runner/starter/resources/queue_builder"
6
+
7
+ def initialize connection, config
8
+ @connection = connection
9
+ @config = config
10
+ end
11
+
12
+ def exchange
13
+ @exchange ||= queue_builder.exchange
14
+ end
15
+
16
+ def queue
17
+ @queue ||= queue_builder.queue
18
+ end
19
+
20
+ def channel
21
+ @channel ||= connection.create_channel(nil, pool_size)
22
+ end
23
+
24
+ private
25
+
26
+ def queue_builder
27
+ @queue_bilder ||= QueueBuilder.new(channel, config)
28
+ end
29
+
30
+ def pool_size
31
+ config.fetch("pool_size", 1)
32
+ end
33
+
34
+ attr_reader :connection, :config
35
+
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,58 @@
1
+ module Liebre
2
+ class Runner
3
+ class Starter
4
+ class Resources
5
+ class QueueBuilder
6
+
7
+ def initialize channel, config
8
+ @channel = channel
9
+ @config = config
10
+ end
11
+
12
+ def queue
13
+ q = channel.queue(queue_name, queue_opts)
14
+ routing_keys.each do |key|
15
+ q.bind(exchange, bind_opts.merge(:routing_key => key))
16
+ end
17
+ q
18
+ end
19
+
20
+ def exchange
21
+ Liebre::Common::Utils.create_exchange channel, exchange_config
22
+ end
23
+
24
+ private
25
+
26
+ def queue_name
27
+ queue_config.fetch("name")
28
+ end
29
+
30
+ def queue_opts
31
+ Liebre::Common::Utils.symbolize_keys queue_config.fetch("opts", {})
32
+ end
33
+
34
+ def exchange_config
35
+ config.fetch("exchange")
36
+ end
37
+
38
+ def queue_config
39
+ config.fetch("queue")
40
+ end
41
+
42
+ def routing_keys
43
+ bind_opts[:routing_key] ||= queue_name
44
+ bind_opts[:routing_key] = [*bind_opts[:routing_key]]
45
+ bind_opts.delete :routing_key
46
+ end
47
+
48
+ def bind_opts
49
+ @bind_opts ||= Liebre::Common::Utils.symbolize_keys config.fetch("bind", {})
50
+ end
51
+
52
+ attr_reader :channel, :config
53
+
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,45 @@
1
+ module Liebre
2
+ class Runner
3
+ class Starter
4
+ class RPC < Consumer
5
+
6
+ def call
7
+ queue.subscribe(:manual_ack => false) do |_info, meta, payload|
8
+ begin
9
+ logger.debug "Received message for #{klass.name}: #{payload} - #{meta}"
10
+ consumer = klass.new(payload, meta, callback(meta))
11
+ consumer.call
12
+ rescue => e
13
+ logger.error e.inspect
14
+ logger.error e.backtrace.join("\n")
15
+ end
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def callback meta
22
+ opts = {
23
+ :routing_key => meta.reply_to,
24
+ :correlation_id => meta.correlation_id,
25
+ :headers => meta.headers
26
+ }
27
+
28
+ lambda do |response|
29
+ logger.debug "Responding with #{response}"
30
+ exchange.publish(response, opts)
31
+ end
32
+ end
33
+
34
+ def exchange
35
+ channel.default_exchange
36
+ end
37
+
38
+ def parse_config
39
+ config
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,12 @@
1
+ require 'liebre'
2
+
3
+ task :environment
4
+
5
+ namespace :liebre do
6
+
7
+ desc "Starts Liebre:Runner"
8
+ task :run => :environment do
9
+ Liebre::Runner.new.start
10
+ end
11
+
12
+ end
@@ -0,0 +1,5 @@
1
+ module Liebre
2
+
3
+ VERSION = "0.1.3"
4
+
5
+ end
data/liebre.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'liebre/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "liebre"
8
+ spec.version = Liebre::VERSION
9
+ spec.authors = ["jcabotc", "graimon"]
10
+ spec.email = ["jcabot@gmail.com"]
11
+ spec.summary = %q{A gem to consume and publish to RabbitMQ based on Bunny, creates a thread for every consumer}
12
+ spec.homepage = "https://github.com/qustodian/liebre"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_runtime_dependency "bunny", '~> 2.5', '>= 2.5.1'
21
+
22
+ spec.add_development_dependency "bundler", '~> 1.6'
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "pry"
25
+ spec.add_development_dependency "rake"
26
+ end
@@ -0,0 +1,47 @@
1
+ rpc_request_timeout: 30
2
+
3
+ consumers:
4
+ some_consumer:
5
+ class_name: MyConsumer
6
+ rpc: false
7
+ pool_size: 1
8
+ num_threads: 3
9
+ exchange:
10
+ name: "consumer_exchange"
11
+ type: "fanout"
12
+ opts:
13
+ durable: false
14
+ queue:
15
+ name: "consumer_queue"
16
+ opts:
17
+ durable: false
18
+
19
+ some_rpc:
20
+ class_name: MyRPC
21
+ rpc: true
22
+ connection_name: rpc
23
+ pool_size: 1
24
+ exchange:
25
+ name: "rpc_exchange"
26
+ type: "fanout"
27
+ opts:
28
+ durable: false
29
+ queue:
30
+ name: "rpc_queue"
31
+ opts:
32
+ durable: false
33
+
34
+ publishers:
35
+ some_publisher:
36
+ exchange:
37
+ name: "consumer_exchange"
38
+ type: "fanout"
39
+ opts:
40
+ durable: false
41
+ rpc_publisher:
42
+ connection_name: rpc
43
+ exchange:
44
+ name: "rpc_exchange"
45
+ type: "fanout"
46
+ opts:
47
+ durable: false
@@ -0,0 +1,35 @@
1
+ development:
2
+ default:
3
+ :host: localhost
4
+ :port: 5672
5
+ :user: guest
6
+ :pass: guest
7
+ :vhost: /
8
+ :threaded: true
9
+ :heartbeat: 2
10
+ rpc:
11
+ :host: localhost
12
+ :port: 5672
13
+ :user: guest
14
+ :pass: guest
15
+ :vhost: /
16
+ :threaded: true
17
+ :heartbeat: 2
18
+
19
+ test:
20
+ default:
21
+ :host: localhost
22
+ :port: 5672
23
+ :user: guest
24
+ :pass: guest
25
+ :vhost: /
26
+ :threaded: true
27
+ :heartbeat: 2
28
+ rpc:
29
+ :host: localhost
30
+ :port: 5672
31
+ :user: guest
32
+ :pass: guest
33
+ :vhost: /
34
+ :threaded: true
35
+ :heartbeat: 2
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe "Integration" do
4
+
5
+ class MyConsumer
6
+
7
+ def initialize payload, meta
8
+ @payload = payload
9
+ @meta = meta
10
+ end
11
+
12
+ end
13
+
14
+ class MyRPC
15
+
16
+ def initialize payload, meta, callback
17
+ @payload = payload
18
+ @meta = meta
19
+ @callback = callback
20
+ end
21
+
22
+ def call
23
+ @callback.call(@payload)
24
+ end
25
+
26
+ end
27
+
28
+ let :config_path do
29
+ File.expand_path("../config/liebre.yml" ,__FILE__)
30
+ end
31
+
32
+ let :connection_path do
33
+ File.expand_path("../config/rabbitmq.yml" ,__FILE__)
34
+ end
35
+
36
+ before do
37
+ Liebre::Config.config_path = config_path
38
+ Liebre::Config.connection_path = connection_path
39
+ end
40
+
41
+ let(:consumer) { double 'consumer' }
42
+
43
+ it do
44
+
45
+ main_thread = Thread.new do
46
+ server = Liebre::Runner.new
47
+ server.start
48
+ end
49
+
50
+ publisher = Liebre::Publisher.new("some_publisher")
51
+
52
+ allow(MyConsumer).to receive(:new).with("hello", anything).and_return consumer
53
+
54
+ #the consumer returns first :ack, then :reject and the message gets requed, then :error, and the message turns dead-lettered
55
+ expect(consumer).to receive(:call).and_return :ack, :reject, :error
56
+
57
+ publisher.enqueue "hello", :routing_key => "consumer_queue" #:ack
58
+ publisher.enqueue "hello", :routing_key => "consumer_queue" #:reject then :error
59
+
60
+
61
+
62
+ rpc_publisher = Liebre::Publisher.new("rpc_publisher")
63
+
64
+ param = "return this string"
65
+
66
+ result = rpc_publisher.rpc param, :routing_key => "rpc_queue"
67
+
68
+ expect(result).to eq param
69
+
70
+ sleep 0.1
71
+ end
72
+
73
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Liebre::Config do
4
+
5
+ let :config_path do
6
+ File.expand_path("../../config/liebre.yml" ,__FILE__)
7
+ end
8
+
9
+ let :connection_path do
10
+ File.expand_path("../../config/rabbitmq.yml" ,__FILE__)
11
+ end
12
+
13
+ before do
14
+ described_class.config_path = config_path
15
+ described_class.connection_path = connection_path
16
+ described_class.env = "some_env"
17
+ end
18
+
19
+ subject { described_class.new }
20
+
21
+ describe '.config_path and .connection_path and .env' do
22
+
23
+ it do
24
+ expect(described_class.config_path).to eq config_path
25
+ expect(described_class.connection_path).to eq connection_path
26
+ expect(described_class.env).to eq "some_env"
27
+ end
28
+ end
29
+
30
+ describe '#consumers' do
31
+
32
+ let(:consumer_names) { %w{ some_consumer some_rpc } }
33
+
34
+ let(:consumer_config) do
35
+ {
36
+ 'class_name' => "MyConsumer",
37
+ 'rpc' => false
38
+ }
39
+ end
40
+
41
+ let(:rpc_config) do
42
+ {
43
+ 'class_name' => "MyRPC",
44
+ 'rpc' => true
45
+ }
46
+ end
47
+
48
+ it do
49
+
50
+ expect(subject.consumers.keys).to eq consumer_names
51
+
52
+ expect(subject.consumers['some_consumer']['class_name']).to eq consumer_config['class_name']
53
+ expect(subject.consumers['some_consumer']['rpc']).to eq consumer_config['rpc']
54
+
55
+ expect(subject.consumers['some_rpc']['class_name']).to eq rpc_config['class_name']
56
+ expect(subject.consumers['some_rpc']['rpc']).to eq rpc_config['rpc']
57
+
58
+ end
59
+
60
+ end
61
+
62
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Liebre::ConnectionManager do
4
+
5
+ let :connection_path do
6
+ File.expand_path("../../config/rabbitmq.yml" ,__FILE__)
7
+ end
8
+
9
+ subject { described_class.new connection_path }
10
+
11
+ describe '.start and .get' do
12
+
13
+ it do
14
+ subject.start
15
+
16
+ bunny = subject.get :default
17
+
18
+ expect(bunny.connected?).to be true
19
+
20
+ end
21
+ end
22
+
23
+ describe '.restart' do
24
+
25
+ before do
26
+ subject.start
27
+ end
28
+
29
+ it do
30
+
31
+ subject.restart
32
+
33
+ bunny = subject.get :rpc
34
+
35
+ expect(bunny.connected?).to be true
36
+
37
+ end
38
+ end
39
+
40
+ end