philotic 0.8.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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