philotic 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -1
  3. data/Gemfile +0 -7
  4. data/README.md +2 -0
  5. data/Rakefile +1 -1
  6. data/examples/README.md +1 -1
  7. data/examples/creating_named_queues/manually.rb +8 -21
  8. data/examples/creating_named_queues/with_rake.rb +2 -2
  9. data/examples/publishing/publish.rb +26 -33
  10. data/examples/subscribing/acks.rb +25 -0
  11. data/examples/subscribing/anonymous_queue.rb +6 -10
  12. data/examples/subscribing/multiple_named_queues.rb +9 -24
  13. data/examples/subscribing/named_queue.rb +7 -17
  14. data/lib/philotic.rb +37 -81
  15. data/lib/philotic/config.rb +63 -24
  16. data/lib/philotic/connection.rb +35 -51
  17. data/lib/philotic/constants.rb +49 -0
  18. data/lib/philotic/event.rb +27 -14
  19. data/lib/philotic/logging.rb +8 -0
  20. data/lib/philotic/logging/event.rb +18 -0
  21. data/lib/philotic/logging/logger.rb +39 -0
  22. data/lib/philotic/publisher.rb +28 -31
  23. data/lib/philotic/routable.rb +40 -40
  24. data/lib/philotic/subscriber.rb +61 -42
  25. data/lib/philotic/tasks/init_queues.rb +4 -14
  26. data/lib/philotic/version.rb +1 -1
  27. data/philotic.gemspec +21 -10
  28. data/spec/philotic/config_spec.rb +40 -0
  29. data/spec/philotic/connection_spec.rb +58 -0
  30. data/spec/philotic/event_spec.rb +69 -0
  31. data/spec/philotic/logging/logger_spec.rb +26 -0
  32. data/spec/philotic/publisher_spec.rb +99 -0
  33. data/spec/{routable_spec.rb → philotic/routable_spec.rb} +15 -14
  34. data/spec/philotic/subscriber_spec.rb +111 -0
  35. data/spec/philotic_spec.rb +66 -0
  36. data/spec/spec_helper.rb +12 -4
  37. data/tasks/bump.rake +10 -10
  38. metadata +173 -36
  39. data/spec/connection_spec.rb +0 -19
  40. data/spec/event_spec.rb +0 -44
  41. data/spec/publisher_spec.rb +0 -102
  42. data/spec/subscriber_spec.rb +0 -72
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0d1256a8211bd2888c9d9d9652fe4a6fc89de284
4
- data.tar.gz: 20e5c1a6ffca4a788bafbc283bc3bcfbd3a868bc
3
+ metadata.gz: de975d7fba7ad019b6df767bc3214b8d3bae5f1f
4
+ data.tar.gz: 38d9c43d25a72d5832597728b400b39969cc4f33
5
5
  SHA512:
6
- metadata.gz: 7b7f720591f38592197ebca75e7d3cb5440d6659c87b43aa99ed04d5ce3f92c4983721f1c1ef8e91387665095a9b30f0771d6073d4b5f75d4a83d056bf032d22
7
- data.tar.gz: ea4267f99564ad426015b55b62ccefe22365a02f1ab8a28f35f3372e28a0c53f3116a1a6f576efd38bb77eddbf07ad493d0329a16b89b9bbbc57edb7d6df270c
6
+ metadata.gz: 24fa4c3529f7b607d6d87276ff5544e06cbf137e20290364fe67794f3334757621713858c28ede50585db9065e453a4a8c35e094cb9b8f1b3a288aba1ffd4d4a
7
+ data.tar.gz: 1ca179e1fdb748572551f501844c323253026284ec704a4d1212a05ac56a5074454d4b7aa0155bc3840bb7755fcaacb3e67c1313cf67ca7f31e495814aa58970
data/.travis.yml CHANGED
@@ -1,9 +1,14 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
- - 2.1.0
5
4
  - 2.0.0
5
+ - 2.1.0
6
6
  - jruby-19mode
7
7
  - ruby-head
8
+ - jruby-head
8
9
  script:
9
10
  - bundle exec rspec
11
+ addons:
12
+ code_climate:
13
+ repo_token:
14
+ secure: "D1HT1RpA+t8nZbXXD26rAyU8YJmaVFQXv+2yXmBmIca7d38zWz+SnJS8shtUXL48MRF31LC6ywTHjHi0JmCLKnwPQhddD8u8pecLGSOhc/wmdauDBTSlfYHo/2uErkVBix9oAgRvn/9b5sx7/yzq1PUWuhYgJhcnibECtQQQQkw="
data/Gemfile CHANGED
@@ -2,10 +2,3 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in philotic.gemspec
4
4
  gemspec
5
-
6
- group :development, :test do
7
- gem 'pry'
8
- gem 'rake'
9
- gem 'rspec'
10
- gem 'timecop'
11
- end
data/README.md CHANGED
@@ -3,5 +3,7 @@
3
3
  Lightweight, opinionated wrapper for using RabbitMQ headers exchanges
4
4
 
5
5
  [![Build Status](https://travis-ci.org/nkeyes/philotic.png?branch=master)](https://travis-ci.org/nkeyes/philotic)
6
+ [![Code Climate](https://codeclimate.com/github/nkeyes/philotic/badges/gpa.svg)](https://codeclimate.com/github/nkeyes/philotic)
7
+ [![Test Coverage](https://codeclimate.com/github/nkeyes/philotic/badges/coverage.svg)](https://codeclimate.com/github/nkeyes/philotic)
6
8
 
7
9
  Check out the [examples](https://github.com/nkeyes/philotic/tree/master/examples).
data/Rakefile CHANGED
@@ -14,7 +14,7 @@ end
14
14
 
15
15
  RSpec::Core::RakeTask.new(:rcov) do |spec|
16
16
  spec.pattern = 'spec/**/*_spec.rb'
17
- spec.rcov = true
17
+ spec.rcov = true
18
18
  end
19
19
 
20
20
  Dir["tasks/**/*.rake"].each { |ext| load ext }
data/examples/README.md CHANGED
@@ -6,7 +6,7 @@ Any project that includes Philotic can include the `philotic:init_queues[path/to
6
6
 
7
7
  For example:
8
8
  ```bash
9
- PHILOTIC_RABBIT_HOST=localhost bundle exec rake eb:init_queues[path/to/named_queues.yml]
9
+ PHILOTIC_RABBIT_HOST=localhost bundle exec rake philotic:init_queues[path/to/named_queues.yml]
10
10
  ```
11
11
 
12
12
 
@@ -1,26 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
- $:.unshift File.expand_path( '../../../lib', __FILE__ )
2
+ $:.unshift File.expand_path('../../../lib', __FILE__)
3
3
  $stdout.sync = true
4
4
 
5
5
  require 'philotic'
6
6
 
7
- EventMachine.run do
8
- # hit Control + C to stop
9
- Signal.trap("INT") { EventMachine.stop }
10
- Signal.trap("TERM") { EventMachine.stop }
11
-
12
- queue_after_initialize_handler = Proc.new do |q|
13
- Philotic.logger.info "Queue '#{q.name}' initialized: #{q.bindings}"
14
- end
15
- # consume ansible + subspace + new_message events
16
- ansible_arguments = {
17
- "x-match" => :all,
18
- philotic_product: :ansible,
19
- philotic_component: :subspace,
20
- philotic_event_type: :new_message,
21
- }
22
- Philotic.initialize_named_queue!('ansible.new_messages', ansible_arguments, &queue_after_initialize_handler)
23
-
24
-
25
- EM.add_timer(5) { EM.stop }
26
- end
7
+ # explicitly create named queues for this example
8
+ # ENV['INITIALIZE_NAMED_QUEUE'] must equal 'true' to run Philotic.initialize_named_queue!
9
+ ENV['INITIALIZE_NAMED_QUEUE'] = 'true'
10
+ Philotic.initialize_named_queue!('male_queue', bindings: [{:'x-match' => 'all', gender: :M, available: true}])
11
+ Philotic.initialize_named_queue!('female_queue', bindings: [{:'x-match' => 'all', gender: :F, available: true}])
12
+ Philotic.initialize_named_queue!('test_queue', bindings: [{ :'x-match' => 'any', gender: :M, available: true }])
13
+ Philotic.initialize_named_queue!('flaky_queue', bindings: [{ :'x-match' => 'any', gender: :M, available: true }])
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- $:.unshift File.expand_path( '../../../lib', __FILE__ )
2
+ $:.unshift File.expand_path('../../../lib', __FILE__)
3
3
  $stdout.sync = true
4
4
 
5
5
  require 'philotic'
@@ -8,4 +8,4 @@ require 'rake'
8
8
  require 'philotic/tasks'
9
9
  # equivelant of:
10
10
  # rake eb:init_queues[examples/creating_named_queues/philotic_named_queues.yml]
11
- Rake::Task["eb:init_queues"].invoke(File.join(File.dirname(__FILE__),".","philotic_named_queues.yml"))
11
+ Rake::Task["eb:init_queues"].invoke(File.join(File.dirname(__FILE__), ".", "philotic_named_queues.yml"))
@@ -2,50 +2,43 @@
2
2
  $:.unshift File.expand_path('../../../lib', __FILE__)
3
3
  $stdout.sync = true
4
4
 
5
- require 'pry'
6
-
7
5
  require 'philotic'
8
6
  require 'philotic/dummy_event'
9
7
 
10
- EventMachine.run do
11
- # hit Control + C to stop
12
- #Signal.trap("INT") { EventMachine.stop }
13
- #Signal.trap("TERM") { EventMachine.stop }
14
-
8
+ Philotic.logger= Logger.new('/dev/null')
15
9
 
16
- Philotic::Config.load_file(File.join(File.dirname(__FILE__), "../../", "philotic.yml"))
10
+ Philotic::Config.load_file(File.join(File.dirname(__FILE__), "../../", "philotic.yml.example"))
17
11
 
18
- #Philotic::Config.message_return_handler = Proc.new { |basic_return, metadata, payload|
19
- # p "overridden"
20
- # Philotic.logger.warn "#{JSON.parse payload} was returned! reply_code = #{basic_return.reply_code}, reply_text = #{basic_return.reply_text}"
21
- #}
12
+ #Philotic::Config.threaded_publish = true
13
+ #Philotic::Config.threaded_publish_pool_size = 3
22
14
 
15
+ Philotic::Connection.connect!
16
+ @event = Philotic::DummyEvent.new
23
17
 
24
- Philotic::Connection.connect! do
25
- def send_message number
26
- dummy_event = Philotic::DummyEvent.new
18
+ @event.philotic_firehose = true
19
+ @event.philotic_product = 'rabbit'
20
+ @event.philotic_component = 'speed_test'
21
+ @event.philotic_event_type = 'ping'
27
22
 
28
- dummy_event.philotic_firehose = true
29
- dummy_event.philotic_product = 'rabbit'
30
- dummy_event.philotic_component = 'speed_test'
31
- dummy_event.philotic_event_type = 'ping'
23
+ @event.subject = 'Hey'
24
+ @event.available = true
32
25
 
33
- dummy_event.subject = "Hey"
34
- dummy_event.available = true
35
- dummy_event.gender = [:F, :M].sample
26
+ @event.message_metadata = {mandatory: true}
27
+ @event.message_metadata = {app_id: 'PHX'}
36
28
 
29
+ def send_message number
30
+ @event.gender = [:F, :M].sample
31
+ @event.message = "Message #{number}: Hey #{@event.gender == :M ? 'dude' : 'dudette'}"
37
32
 
38
- dummy_event.message_metadata = {mandatory: true}
39
- dummy_event.message_metadata = {app_id: 'PHX'}
40
- dummy_event.message = "Message #{number}: Hey #{dummy_event.gender == :M ? 'dude' : 'dudette'}"
41
- dummy_event.publish
33
+ @event.publish
42
34
 
43
- EM.add_timer rand/10 do
44
- send_message number + 1
45
- end
46
- end
47
-
48
- send_message 1
35
+ end
49
36
 
50
- end
37
+ start = Time.now
38
+ i = 1
39
+ loop do
40
+ send_message i
41
+ print "Message rate: #{(i/(Time.now - start)).round(2)}/sec \r"
42
+ i+= 1
43
+ sleep 0.01
51
44
  end
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.expand_path('../../../lib', __FILE__)
3
+ $stdout.sync = true
4
+
5
+ require 'philotic'
6
+ require 'awesome_print'
7
+
8
+ # sometimes ack
9
+ Philotic::Subscriber.subscribe('flaky_queue', ack: true) do |metadata, message|
10
+ ap message[:attributes]
11
+ [true, false].sample ? Philotic::Subscriber.acknowledge(message) : Philotic::Subscriber.reject(message)
12
+ end
13
+
14
+ # always ack
15
+ Philotic::Subscriber.subscribe('flaky_queue', ack: true) do |metadata, message|
16
+ ap message[:attributes]
17
+ Philotic::Subscriber.acknowledge(message, true)
18
+ end
19
+
20
+ # always reject
21
+ Philotic::Subscriber.subscribe('flaky_queue', ack: true) do |metadata, message|
22
+ ap message[:attributes]
23
+ Philotic::Subscriber.reject message
24
+ end
25
+ Philotic::Subscriber.endure
@@ -3,17 +3,13 @@ $:.unshift File.expand_path('../../../lib', __FILE__)
3
3
  $stdout.sync = true
4
4
 
5
5
  require 'philotic'
6
+ require 'awesome_print'
6
7
 
7
- EventMachine.run do
8
- # hit Control + C to stop
9
- # Signal.trap("INT") { EventMachine.stop }
10
- # Signal.trap("TERM") { EventMachine.stop }
8
+ Philotic::Config.load_file(File.join(File.dirname(__FILE__), '../../', 'philotic.yml.example'))
11
9
 
12
- Philotic::Config.load_file(File.join(File.dirname(__FILE__), "../../", "philotic.yml"))
13
10
 
14
-
15
- Philotic::Subscriber.subscribe(philotic_fire_hose: true) do |metadata, payload|
16
- p metadata.attributes
17
- p payload
18
- end
11
+ Philotic::Subscriber.subscribe(philotic_firehose: true) do |metadata, message|
12
+ ap message[:attributes]
19
13
  end
14
+
15
+ Philotic::Subscriber.endure
@@ -2,32 +2,17 @@
2
2
  $:.unshift File.expand_path('../../../lib', __FILE__)
3
3
  $stdout.sync = true
4
4
 
5
- require 'pry'
6
5
  require 'philotic'
6
+ require 'awesome_print'
7
7
 
8
- EventMachine.run do
9
- # hit Control + C to stop
10
- Signal.trap("INT") { EventMachine.stop }
11
- Signal.trap("TERM") { EventMachine.stop }
8
+ Philotic::Config.load_file(File.join(File.dirname(__FILE__), '../../', 'philotic.yml.example'))
12
9
 
13
- Philotic::Config.load_file(File.join(File.dirname(__FILE__), "../../", "philotic.yml"))
14
-
15
- # explicitly create named queues for this example
16
- # ENV['INITIALIZE_NAMED_QUEUE'] must equal 'true' to run Philotic.initialize_named_queue!
17
- ENV['INITIALIZE_NAMED_QUEUE'] = 'true'
18
- Philotic.initialize_named_queue!('male_queue', :"x-match" => 'all', gender: :M, available: true) do
19
- Philotic.initialize_named_queue!('female_queue', :"x-match" => 'all', gender: :F, available: true)
20
- end
10
+ Philotic::Subscriber.subscribe('female_queue') do |metadata, message|
11
+ ap message[:attributes]
12
+ end
21
13
 
22
- # give it time to actually create the queue, then subscribe
23
- EM.add_timer(3) do
24
- Philotic::Subscriber.subscribe('male_queue') do |metadata, payload|
25
- p metadata.attributes
26
- p payload
27
- end
28
- Philotic::Subscriber.subscribe('female_queue') do |metadata, payload|
29
- p metadata.attributes
30
- p payload
31
- end
32
- end
14
+ Philotic::Subscriber.subscribe('male_queue') do |metadata, message|
15
+ ap message[:attributes]
33
16
  end
17
+
18
+ Philotic::Subscriber.endure
@@ -1,23 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
- $:.unshift File.expand_path( '../../../lib', __FILE__ )
2
+ $:.unshift File.expand_path('../../../lib', __FILE__)
3
3
  $stdout.sync = true
4
4
 
5
- require 'pry'
6
5
  require 'philotic'
6
+ require 'awesome_print'
7
7
 
8
- EventMachine.run do
9
- # hit Control + C to stop
10
- Signal.trap("INT") { EventMachine.stop }
11
- Signal.trap("TERM") { EventMachine.stop }
12
-
13
- #explicitly create a named queue for this example
14
- Philotic.initialize_named_queue!('test_queue', :"x-match" => 'any', gender: :M, available: true)
15
-
16
- # give it time to actually create the queue, then subscribe
17
- EM.add_timer(3) do
18
- Philotic::Subscriber.subscribe('test_queue') do |metadata, payload|
19
- p metadata.attributes
20
- p payload
21
- end
22
- end
8
+
9
+ Philotic::Subscriber.subscribe('test_queue') do |metadata, message|
10
+ ap message[:attributes]
23
11
  end
12
+
13
+ Philotic::Subscriber.endure
data/lib/philotic.rb CHANGED
@@ -1,61 +1,13 @@
1
- require 'awesome_print'
2
1
  require 'active_support/all'
3
-
4
2
  require 'pathname'
5
-
6
3
  require 'logger'
7
4
 
5
+ require 'philotic/constants'
8
6
 
9
7
  module Philotic
10
8
  mattr_accessor :logger
11
9
  mattr_accessor :log_event_handler
12
10
 
13
- CONNECTION_OPTIONS = [
14
- :rabbit_host,
15
- :connection_failed_handler,
16
- :connection_loss_handler,
17
- :timeout,
18
- ]
19
- EXCHANGE_OPTIONS = [
20
- :exchange_name,
21
- :message_return_handler,
22
- ]
23
- MESSAGE_OPTIONS = [
24
- :routing_key,
25
- :persistent,
26
- # :immediate,
27
- :mandatory,
28
- :content_type,
29
- :content_encoding,
30
- :priority,
31
- :message_id,
32
- :correlation_id,
33
- :reply_to,
34
- :type,
35
- :user_id,
36
- :app_id,
37
- :timestamp,
38
- :expiration,
39
- ]
40
-
41
- PHILOTIC_HEADERS = [
42
- :philotic_firehose,
43
- :philotic_product,
44
- :philotic_component,
45
- :philotic_event_type,
46
- ]
47
-
48
- DEFAULT_NAMED_QUEUE_OPTIONS = {
49
- auto_delete: false,
50
- durable: true
51
- }
52
- DEFAULT_ANONYMOUS_QUEUE_OPTIONS = {
53
- auto_delete: true,
54
- durable: false
55
- }
56
-
57
- DEFAULT_SUBSCRIBE_OPTIONS = {}
58
-
59
11
  def self.root
60
12
  ::Pathname.new File.expand_path('../../', __FILE__)
61
13
  end
@@ -68,41 +20,44 @@ module Philotic
68
20
  Philotic::Connection.exchange
69
21
  end
70
22
 
71
- def self.initialize_named_queue!(queue_name, config, &block)
23
+ def self.initialize_named_queue!(queue_name, config)
24
+ Philotic.connect!
72
25
  config = config.deep_symbolize_keys
73
26
 
74
-
75
27
  raise "ENV['INITIALIZE_NAMED_QUEUE'] must equal 'true' to run Philotic.initialize_named_queue!" unless ENV['INITIALIZE_NAMED_QUEUE'] == 'true'
76
- connect! do
77
- queue_options = DEFAULT_NAMED_QUEUE_OPTIONS.dup
78
- queue_options.merge!(config[:options] || {})
79
-
80
- AMQP.channel.queue(queue_name, queue_options) do |old_queue|
81
- old_queue.delete do
82
- Philotic::Connection.close do
83
- connect! do
84
- Philotic.logger.info "deleted old queue. queue:#{queue_name}"
85
-
86
- bindings = Array(config[:bindings])
87
-
88
- queue_exchange = config[:exchange] ? AMQP.channel.headers(config[:exchange], durable: true) : exchange
89
-
90
- AMQP.channel.queue(queue_name, queue_options) do |q|
91
- Philotic.logger.info "Created queue. queue:#{q.name}"
92
- bindings.each_with_index do |arguments, arguments_index|
93
- q.bind(queue_exchange, { arguments: arguments }) do
94
- Philotic.logger.info "Added binding to queue. queue:#{q.name} binding:#{arguments}"
95
- if arguments_index >= bindings.size - 1
96
- Philotic.logger.info "Finished adding bindings to queue. queue:#{q.name}"
97
- block.call(q) if block
98
- end
99
- end
100
- end
101
- end
102
- end
103
- end
104
- end
105
- end
28
+
29
+ if Philotic::Connection.connection.queue_exists? queue_name
30
+ Philotic::Connection.channel.queue(queue_name, passive: true).delete
31
+ Philotic.logger.info "deleted old queue. queue: #{queue_name}"
32
+ end
33
+
34
+ queue = queue_from_config(queue_name, config)
35
+
36
+ bind_queue(queue, config)
37
+ yield queue if block_given?
38
+ end
39
+
40
+ def self.bind_queue(queue, config)
41
+ queue_exchange = exchange_from_config(config)
42
+ bindings = config[:bindings]
43
+ bindings.each do |arguments|
44
+ queue.bind(queue_exchange, {arguments: arguments})
45
+ Philotic.logger.info "Added binding to queue. queue: #{queue.name} binding: #{arguments}"
46
+ end
47
+
48
+ Philotic.logger.info "Finished adding bindings to queue. queue: #{queue.name}"
49
+ end
50
+
51
+ def self.exchange_from_config(config)
52
+ config[:exchange] ? Philotic::Connection.channel.headers(config[:exchange], durable: true) : exchange
53
+ end
54
+
55
+ def self.queue_from_config(queue_name, config)
56
+ queue_options = DEFAULT_NAMED_QUEUE_OPTIONS.dup
57
+ queue_options.merge!(config[:options] || {})
58
+
59
+ Philotic::Connection.channel.queue(queue_name, queue_options).tap do
60
+ Philotic.logger.info "Created queue. queue:#{queue_name}"
106
61
  end
107
62
  end
108
63
 
@@ -142,3 +97,4 @@ require 'philotic/routable'
142
97
  require 'philotic/event'
143
98
  require 'philotic/publisher'
144
99
  require 'philotic/subscriber'
100
+ require 'philotic/logging'