philotic 0.0.1 → 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 (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'