philotic 0.8.1 → 1.0.1

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 (39) hide show
  1. checksums.yaml +7 -7
  2. data/.travis.yml +5 -6
  3. data/README.md +10 -13
  4. data/examples/creating_named_queues/manually.rb +4 -4
  5. data/examples/creating_named_queues/with_rake.rb +4 -1
  6. data/examples/publishing/publish.rb +14 -14
  7. data/examples/simple_instance.rb +4 -4
  8. data/examples/simple_singleton.rb +3 -3
  9. data/examples/subscribing/acks.rb +6 -6
  10. data/examples/subscribing/anonymous_queue.rb +2 -2
  11. data/examples/subscribing/consumer.rb +47 -0
  12. data/examples/subscribing/multiple_named_queues.rb +4 -4
  13. data/examples/subscribing/named_queue.rb +3 -3
  14. data/lib/philotic.rb +2 -3
  15. data/lib/philotic/config.rb +1 -1
  16. data/lib/philotic/connection.rb +1 -0
  17. data/lib/philotic/constants.rb +1 -1
  18. data/lib/philotic/consumer.rb +93 -0
  19. data/lib/philotic/{dummy_event.rb → dummy_message.rb} +3 -3
  20. data/lib/philotic/logging.rb +1 -1
  21. data/lib/philotic/logging/logger.rb +6 -6
  22. data/lib/philotic/logging/{event.rb → message.rb} +2 -2
  23. data/lib/philotic/message.rb +146 -0
  24. data/lib/philotic/publisher.rb +24 -24
  25. data/lib/philotic/subscriber.rb +9 -12
  26. data/lib/philotic/version.rb +1 -1
  27. data/philotic.gemspec +8 -11
  28. data/philotic_queues.yml.example +8 -8
  29. data/spec/philotic/connection_spec.rb +2 -0
  30. data/spec/philotic/consumer_spec.rb +186 -0
  31. data/spec/philotic/logging/logger_spec.rb +15 -15
  32. data/spec/philotic/message_spec.rb +147 -0
  33. data/spec/philotic/publisher_spec.rb +39 -38
  34. data/spec/philotic/subscriber_spec.rb +6 -3
  35. metadata +173 -144
  36. data/lib/philotic/event.rb +0 -100
  37. data/lib/philotic/routable.rb +0 -98
  38. data/spec/philotic/event_spec.rb +0 -109
  39. data/spec/philotic/routable_spec.rb +0 -54
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 4b6c5ea9acde32413d17038555e1d6d4a47584f5
4
- data.tar.gz: 064a0af07b4f685a58bb4c7a4016ac929a4ff338
5
- SHA512:
6
- metadata.gz: 7c4bdeeeaab84fe4033d1f2df512677b4a5400c82cb01903b539b37d249285b4a6b33060153359154a87a0e3167936eeaf51a892a427128a658fca88356844fc
7
- data.tar.gz: e2894d10d9de9fd0186cfefcbbdabaa48863a8f3ac99fb4d18317338df5fc5bd383b7c0a09d9828f703dae1a97ca6faefea615c02a23da9cf424e82a42233f31
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2e126429cf9f92b56a49a1f1e609479736b965c1
4
+ data.tar.gz: 2b0f1b015e34e9e7d773973cee7b4d7657186229
5
+ SHA512:
6
+ metadata.gz: 18e0412f7f720e0a382e17f109d54472ec0d6328e5d739ed8eabdf45058e33f70eb322908335d28a8b3d1825f67d42f47a63f622b3bd0df19751b0648533c00a
7
+ data.tar.gz: 1f06ba6e3e167d1c4d79540c7555435754b8ebee2bc62a7e3787309ab4115ec815110f036d7a2c66819e68858f08eea4993447e396196f6fbb97086ccfa0f121
data/.travis.yml CHANGED
@@ -1,13 +1,12 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
4
3
  - 2.0.0
5
- - 2.1.0
6
- - rbx-2.2.10
7
- #- rbx-2.3.0
8
- - jruby-19mode
4
+ - 2.1
5
+ - 2.2
6
+ - rbx-2
7
+ # - jruby-19mode
9
8
  - ruby-head
10
- - jruby-head
9
+ # - jruby-head
11
10
  script:
12
11
  - bundle exec rspec
13
12
  addons:
data/README.md CHANGED
@@ -20,8 +20,8 @@ Philotic.config.message_return_handler = lambda do |basic_return, metadata, mess
20
20
  Philotic.logger.warn { "Message returned. reply_text: #{basic_return.reply_text}" }
21
21
  end
22
22
 
23
- Philotic.subscribe(header_key: 'header_1') do |message, metadata, queue|
24
- ap message[:attributes]
23
+ Philotic.subscribe(header_key: 'header_1') do |message|
24
+ ap message.attributes
25
25
  end
26
26
 
27
27
  # normally we'd do:
@@ -31,7 +31,7 @@ end
31
31
  # to keep the parent thread alive while the subscribers do their thing
32
32
  # but this infinite publish loop takes care of that
33
33
  loop do
34
- Philotic::Event.publish({header_key: "header_#{[1, 2].sample}"}, {payload_key: 'payload_value'})
34
+ Philotic::Message.publish({header_key: "header_#{[1, 2].sample}"}, {payload_key: 'payload_value'})
35
35
  # only send a message every two seconds so we can see whats going on
36
36
  sleep 2
37
37
  end
@@ -49,8 +49,8 @@ philotic.config.message_return_handler = lambda do |basic_return, metadata, mess
49
49
  philotic.logger.warn { "Message returned. reply_text: #{basic_return.reply_text}" }
50
50
  end
51
51
 
52
- philotic.subscribe(header_key: 'header_1') do |message, metadata, queue|
53
- ap message[:attributes]
52
+ philotic.subscribe(header_key: 'header_1') do |message|
53
+ ap message.attributes
54
54
  end
55
55
 
56
56
  # normally we'd do:
@@ -60,19 +60,16 @@ end
60
60
  # to keep the parent thread alive while the subscribers do their thing
61
61
  # but this infinite publish loop takes care of that
62
62
  loop do
63
- event = Philotic::Event.new({header_key: "header_#{[1, 2].sample}"}, {payload_key: 'payload_value'})
64
- philotic.publish event
63
+ message = Philotic::Message.new({header_key: "header_#{[1, 2].sample}"}, {payload_key: 'payload_value'})
64
+ philotic.publish message
65
65
  # only send a message every two seconds so we can see whats going on
66
66
  sleep 2
67
67
  end
68
68
  ```
69
69
 
70
70
  ### Tested with the following Rubies
71
- * 1.9.3
72
71
  * 2.0.0
73
- * 2.1.0
74
- * rbx-2.2.10
75
- * rbx-2.3.0
76
- * jruby-19mode
72
+ * 2.1.x
73
+ * 2.2.x
74
+ * rbx-2
77
75
  * ruby-head
78
- * jruby-head
@@ -8,7 +8,7 @@ require 'philotic'
8
8
  # Philotic.config.initialize_named_queues must be truthy to run Philotic.initialize_named_queue!
9
9
  Philotic.config.initialize_named_queues = true
10
10
 
11
- Philotic.initialize_named_queue!('male_queue', bindings: [{:'x-match' => 'all', gender: :M, available: true}])
12
- Philotic.initialize_named_queue!('female_queue', bindings: [{:'x-match' => 'all', gender: :F, available: true}])
13
- Philotic.initialize_named_queue!('test_queue', bindings: [{ :'x-match' => 'any', gender: :M, available: true }])
14
- Philotic.initialize_named_queue!('flaky_queue', bindings: [{ :'x-match' => 'any', gender: :M, available: true }])
11
+ Philotic.initialize_named_queue!('mauve_queue', bindings: [{:'x-match' => 'all', hue: :M, available: true}])
12
+ Philotic.initialize_named_queue!('fuchsia_queue', bindings: [{:'x-match' => 'all', hue: :F, available: true}])
13
+ Philotic.initialize_named_queue!('test_queue', bindings: [{ :'x-match' => 'any', hue: :M, available: true }])
14
+ Philotic.initialize_named_queue!('flaky_queue', bindings: [{ :'x-match' => 'any', hue: :M, available: true }])
@@ -7,5 +7,8 @@ require 'rake'
7
7
 
8
8
  require 'philotic/tasks'
9
9
  # equivelant of:
10
- # rake philotic:init_queues[examples/creating_named_queues/philotic_queues.yml]
10
+ # PHILOTIC_DELETE_EXISTING_QUEUES=true rake philotic:init_queues[examples/creating_named_queues/philotic_queues.yml]
11
+
12
+ # Philotic.config.self.config.delete_existing_queues must be truthy to redefine existing queues
13
+ ENV['PHILOTIC_DELETE_EXISTING_QUEUES'] = 'true'
11
14
  Rake::Task['philotic:init_queues'].invoke(File.join(File.dirname(__FILE__), 'philotic_queues.yml'))
@@ -3,29 +3,29 @@ $:.unshift File.expand_path('../../../lib', __FILE__)
3
3
  $stdout.sync = true
4
4
 
5
5
  require 'philotic'
6
- require 'philotic/dummy_event'
6
+ require 'philotic/dummy_message'
7
7
 
8
8
 
9
9
  Philotic.logger.level = Logger::WARN
10
10
 
11
- @event = Philotic::DummyEvent.new
11
+ @message = Philotic::DummyMessage.new
12
12
 
13
- @event.philotic_firehose = true
14
- @event.philotic_product = 'rabbit'
15
- @event.philotic_component = 'speed_test'
16
- @event.philotic_event_type = 'ping'
13
+ @message.philotic_firehose = true
14
+ @message.philotic_product = 'rabbit'
15
+ @message.philotic_component = 'speed_test'
16
+ @message.philotic_message_type = 'ping'
17
17
 
18
- @event.subject = 'Hey'
19
- @event.available = true
18
+ @message.subject = 'Hey'
19
+ @message.available = true
20
20
 
21
- @event.message_metadata = {mandatory: true}
22
- @event.message_metadata = {app_id: 'PHX'}
21
+ @message.metadata = {mandatory: true}
22
+ @message.metadata = {app_id: 'PHX'}
23
23
 
24
24
  def send_message number
25
- @event.gender = [:F, :M].sample
26
- @event.message = "Message #{number}: Hey #{@event.gender == :M ? 'dude' : 'dudette'}"
25
+ @message.hue = [:F, :M].sample
26
+ @message.message = "Message #{number}: Hue - #{@message.hue == :M ? 'mauve' : 'fuchsia'}"
27
27
 
28
- Philotic.publish @event
28
+ Philotic.publish @message
29
29
 
30
30
  end
31
31
 
@@ -35,5 +35,5 @@ loop do
35
35
  send_message i
36
36
  print "Message rate: #{(i/(Time.now - start)).round(2)}/sec \r"
37
37
  i+= 1
38
- sleep 0.01
38
+ sleep 0.001
39
39
  end
@@ -12,8 +12,8 @@ philotic.config.message_return_handler = lambda do |basic_return, metadata, mess
12
12
  philotic.logger.warn { "Message returned. reply_text: #{basic_return.reply_text}" }
13
13
  end
14
14
 
15
- philotic.subscribe(header_key: 'header_1') do |message, metadata, queue|
16
- ap message[:attributes]
15
+ philotic.subscribe(header_key: 'header_1') do |message|
16
+ ap message.attributes
17
17
  end
18
18
 
19
19
  # normally we'd do:
@@ -23,8 +23,8 @@ end
23
23
  # to keep the parent thread alive while the subscribers do their thing
24
24
  # but this infinite publish loop takes care of that
25
25
  loop do
26
- event = Philotic::Event.new({header_key: "header_#{[1, 2].sample}"}, {payload_key: 'payload_value'})
27
- philotic.publish event
26
+ message = Philotic::Message.new({header_key: "header_#{[1, 2].sample}"}, {payload_key: 'payload_value'})
27
+ philotic.publish message
28
28
  # only send a message every two seconds so we can see whats going on
29
29
  sleep 2
30
30
  end
@@ -10,8 +10,8 @@ Philotic.config.message_return_handler = lambda do |basic_return, metadata, mess
10
10
  Philotic.logger.warn { "Message returned. reply_text: #{basic_return.reply_text}" }
11
11
  end
12
12
 
13
- Philotic.subscribe(header_key: 'header_1') do |message, metadata, queue|
14
- ap message[:attributes]
13
+ Philotic.subscribe(header_key: 'header_1') do |message|
14
+ ap header_key: message.header_key, payload_key: message.payload_key, methods: message.methods - Philotic::Message.new.methods
15
15
  end
16
16
 
17
17
  # normally we'd do:
@@ -21,7 +21,7 @@ end
21
21
  # to keep the parent thread alive while the subscribers do their thing
22
22
  # but this infinite publish loop takes care of that
23
23
  loop do
24
- Philotic::Event.publish({header_key: "header_#{[1, 2].sample}"}, {payload_key: 'payload_value'})
24
+ Philotic::Message.publish({header_key: "header_#{[1, 2].sample}"}, {payload_key: 'payload_value'})
25
25
  # only send a message every two seconds so we can see whats going on
26
26
  sleep 2
27
27
  end
@@ -6,20 +6,20 @@ require 'philotic'
6
6
  require 'awesome_print'
7
7
 
8
8
  # sometimes ack
9
- Philotic.subscribe('flaky_queue', ack: true) do |message, metadata, queue|
10
- ap message[:attributes]
9
+ Philotic.subscribe('flaky_queue', ack: true) do |message|
10
+ ap message.attributes
11
11
  [true, false].sample ? acknowledge(message) : reject(message)
12
12
  end
13
13
 
14
14
  # always ack
15
- Philotic.subscribe('flaky_queue', ack: true) do |message, metadata, queue|
16
- ap message[:attributes]
15
+ Philotic.subscribe('flaky_queue', ack: true) do |message|
16
+ ap message.attributes
17
17
  acknowledge(message, true)
18
18
  end
19
19
 
20
20
  # always reject
21
- Philotic.subscribe('flaky_queue', ack: true) do |message, metadata, queue|
22
- ap message[:attributes]
21
+ Philotic.subscribe('flaky_queue', ack: true) do |message|
22
+ ap message.attributes
23
23
  reject message
24
24
  end
25
25
  Philotic.subscriber.endure
@@ -7,8 +7,8 @@ require 'awesome_print'
7
7
 
8
8
  Philotic.config.load_file(File.join(File.dirname(__FILE__), '../../', 'Philotic.yml.example'))
9
9
 
10
- Philotic.subscribe(philotic_firehose: true) do |message, metadata, queue|
11
- ap message[:attributes]
10
+ Philotic.subscribe(philotic_firehose: true) do |message|
11
+ ap message.attributes
12
12
  end
13
13
 
14
14
  Philotic.subscriber.endure
@@ -0,0 +1,47 @@
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
+ class NamedQueueConsumer < Philotic::Consumer
9
+
10
+ # subscribe to an existing named queue
11
+ subscribe_to :test_queue
12
+
13
+ #use acknowledgements
14
+ ack_messages
15
+
16
+ # REQUEUE the message with RabbitMQ if consume throws these errors. I.e., something went wrong with the consumer
17
+ # Only valid with ack_messages
18
+ requeueable_errors PossiblyTransientErrorOne, PossiblyTransientErrorTwo
19
+
20
+ # REJECT the message with RabbitMQ if consume throws these errors. I.e., The message is malformed/invalid
21
+ # Only valid with ack_messages
22
+ rejectable_errors BadMessageError
23
+
24
+ def consume(message)
25
+ ap named: message.attributes
26
+ end
27
+ end
28
+
29
+ class AnonymousQueueConsumer < Philotic::Consumer
30
+
31
+ # subscribe anonymously to a set of headers:
32
+ # subscribe_to header_1: 'value_1',
33
+ # header_2: 'value_2',
34
+ # header_3: 'value_3'
35
+ subscribe_to philotic_firehose: true
36
+
37
+ def consume(message)
38
+ ap anon: message.attributes
39
+ end
40
+ end
41
+
42
+ #run the consumers
43
+ AnonymousQueueConsumer.subscribe
44
+ NamedQueueConsumer.subscribe
45
+
46
+ # keep the parent thread alive
47
+ Philotic.endure
@@ -7,12 +7,12 @@ require 'awesome_print'
7
7
 
8
8
  Philotic.config.load_file(File.join(File.dirname(__FILE__), '../../', 'Philotic.yml.example'))
9
9
 
10
- Philotic.subscribe('female_queue') do |message, metadata, queue|
11
- ap message[:attributes]
10
+ Philotic.subscribe('fuchsia_queue') do |message|
11
+ ap message.attributes
12
12
  end
13
13
 
14
- Philotic.subscribe('male_queue') do |message, metadata, queue|
15
- ap message[:attributes]
14
+ Philotic.subscribe('mauve_queue') do |message|
15
+ ap message.attributes
16
16
  end
17
17
 
18
18
  Philotic.subscriber.endure
@@ -5,8 +5,8 @@ $stdout.sync = true
5
5
  require 'philotic'
6
6
  require 'awesome_print'
7
7
 
8
- Philotic.subscribe('test_queue') do |message, metadata, queue|
9
- ap message[:attributes]
8
+ Philotic.subscribe('test_queue') do |message|
9
+ ap message.attributes
10
10
  end
11
11
 
12
- Philotic.subscriber.endure
12
+ Philotic.subscriber.endure
data/lib/philotic.rb CHANGED
@@ -1,4 +1,3 @@
1
- require 'active_support/all'
2
1
  require 'pathname'
3
2
 
4
3
  module Philotic
@@ -16,8 +15,8 @@ require 'philotic/singleton'
16
15
  require 'philotic/connection'
17
16
  require 'philotic/version'
18
17
  require 'philotic/config'
19
- require 'philotic/routable'
20
- require 'philotic/event'
18
+ require 'philotic/message'
21
19
  require 'philotic/publisher'
22
20
  require 'philotic/subscriber'
21
+ require 'philotic/consumer'
23
22
  require 'philotic/logging'
@@ -144,7 +144,7 @@ module Philotic
144
144
 
145
145
  def load_file(filename, env = 'development')
146
146
  config = YAML.load_file(filename)
147
- load(config[env])
147
+ load_config(config[env])
148
148
  end
149
149
  end
150
150
  end
@@ -2,6 +2,7 @@ require 'json'
2
2
  require 'bunny'
3
3
  require 'logger'
4
4
  require 'bunny'
5
+ require 'active_support/all'
5
6
  require 'philotic/constants'
6
7
  require 'philotic/config'
7
8
  require 'philotic/publisher'
@@ -32,7 +32,7 @@ module Philotic
32
32
  :philotic_firehose,
33
33
  :philotic_product,
34
34
  :philotic_component,
35
- :philotic_event_type,
35
+ :philotic_message_type,
36
36
  ]
37
37
 
38
38
  DEFAULT_NAMED_QUEUE_OPTIONS = {
@@ -0,0 +1,93 @@
1
+ require 'philotic/singleton'
2
+ require 'philotic/subscriber'
3
+
4
+ module Philotic
5
+ class Consumer < Philotic::Subscriber
6
+
7
+ class << self
8
+
9
+ def subscribe_to(subscription)
10
+ @subscription = subscription
11
+ end
12
+
13
+ def subscription
14
+ @subscription
15
+ end
16
+
17
+ def ack_messages
18
+ @ack_messages = true
19
+ end
20
+
21
+ def exclusive
22
+ @exclusive = true
23
+ end
24
+
25
+ def ack_messages?
26
+ !!@ack_messages
27
+ end
28
+
29
+ def exclusive?
30
+ !!@exclusive
31
+ end
32
+
33
+ def requeueable_errors(*errors)
34
+ @requeueable_errors ||= Set.new
35
+ @requeueable_errors.merge errors
36
+ @requeueable_errors
37
+ end
38
+
39
+ def rejectable_errors(*errors)
40
+ @rejectable_errors ||= Set.new
41
+ @rejectable_errors.merge errors
42
+ @rejectable_errors
43
+ end
44
+
45
+ def subscribe
46
+ new(Philotic.connection).tap do |instance|
47
+ instance.subscribe
48
+ end
49
+ end
50
+
51
+ def subscription_options
52
+ {
53
+ manual_ack: ack_messages?,
54
+ exclusive: exclusive?,
55
+ }
56
+ end
57
+ end
58
+
59
+ def subscribe
60
+ super(self.class.subscription, self.class.subscription_options) do |message|
61
+ _consume(message)
62
+ end
63
+ end
64
+
65
+ def consume(message)
66
+ raise NotImplementedError
67
+ end
68
+
69
+ private
70
+
71
+ def _consume(message)
72
+ if self.class.ack_messages?
73
+ begin
74
+ consume(message)
75
+ rescue => e
76
+
77
+ if self.class.requeueable_errors.include? e.class
78
+ reject(message, true)
79
+ return
80
+ elsif self.class.rejectable_errors.include? e.class
81
+ reject(message, false)
82
+ return
83
+ else
84
+ raise e
85
+ end
86
+ end
87
+ acknowledge(message)
88
+ else
89
+ consume(message)
90
+ end
91
+ end
92
+ end
93
+ end