philotic 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +25 -0
- data/.rspec +2 -0
- data/.travis.yml +9 -0
- data/Gemfile +11 -0
- data/LICENSE +22 -0
- data/README.md +7 -0
- data/Rakefile +24 -0
- data/examples/README.md +13 -0
- data/examples/creating_named_queues/manually.rb +26 -0
- data/examples/creating_named_queues/philotic_named_queues.yml +6 -0
- data/examples/creating_named_queues/with_rake.rb +11 -0
- data/examples/publishing/publish.rb +51 -0
- data/examples/subscribing/anonymous_queue.rb +19 -0
- data/examples/subscribing/multiple_named_queues.rb +33 -0
- data/examples/subscribing/named_queue.rb +23 -0
- data/lib/philotic.rb +144 -0
- data/lib/philotic/config.rb +79 -0
- data/lib/philotic/connection.rb +83 -0
- data/lib/philotic/dummy_event.rb +8 -0
- data/lib/philotic/event.rb +69 -0
- data/lib/philotic/publisher.rb +58 -0
- data/lib/philotic/routable.rb +106 -0
- data/lib/philotic/subscriber.rb +67 -0
- data/lib/philotic/tasks.rb +1 -0
- data/lib/philotic/tasks/init_queues.rb +28 -0
- data/lib/philotic/version.rb +3 -0
- data/philotic.gemspec +24 -0
- data/philotic.yml.example +36 -0
- data/philotic_queues.yml.example +19 -0
- data/spec/connection_spec.rb +19 -0
- data/spec/event_spec.rb +44 -0
- data/spec/publisher_spec.rb +102 -0
- data/spec/routable_spec.rb +58 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/subscriber_spec.rb +72 -0
- data/tasks/bump.rake +30 -0
- metadata +157 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0d1256a8211bd2888c9d9d9652fe4a6fc89de284
|
4
|
+
data.tar.gz: 20e5c1a6ffca4a788bafbc283bc3bcfbd3a868bc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7b7f720591f38592197ebca75e7d3cb5440d6659c87b43aa99ed04d5ce3f92c4983721f1c1ef8e91387665095a9b30f0771d6073d4b5f75d4a83d056bf032d22
|
7
|
+
data.tar.gz: ea4267f99564ad426015b55b62ccefe22365a02f1ab8a28f35f3372e28a0c53f3116a1a6f576efd38bb77eddbf07ad493d0329a16b89b9bbbc57edb7d6df270c
|
data/.gitignore
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
.project
|
19
|
+
philotic.yml
|
20
|
+
philotic_queues.yml
|
21
|
+
.idea/
|
22
|
+
log/*.log
|
23
|
+
.rvmrc
|
24
|
+
.ruby-version
|
25
|
+
.ruby-gemset
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Nathan Keyes
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# Philotic
|
2
|
+
|
3
|
+
Lightweight, opinionated wrapper for using RabbitMQ headers exchanges
|
4
|
+
|
5
|
+
[![Build Status](https://travis-ci.org/nkeyes/philotic.png?branch=master)](https://travis-ci.org/nkeyes/philotic)
|
6
|
+
|
7
|
+
Check out the [examples](https://github.com/nkeyes/philotic/tree/master/examples).
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.setup :default, :test, :development
|
4
|
+
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
|
7
|
+
require 'rspec/core/rake_task'
|
8
|
+
|
9
|
+
require 'philotic/tasks'
|
10
|
+
|
11
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
12
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
13
|
+
end
|
14
|
+
|
15
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
16
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
17
|
+
spec.rcov = true
|
18
|
+
end
|
19
|
+
|
20
|
+
Dir["tasks/**/*.rake"].each { |ext| load ext }
|
21
|
+
|
22
|
+
task :spec
|
23
|
+
task default: :spec
|
24
|
+
|
data/examples/README.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Philotic Examples
|
2
|
+
Read the code, yo!
|
3
|
+
|
4
|
+
## (Re)Initializing Named Queues
|
5
|
+
Any project that includes Philotic can include the `philotic:init_queues[path/to/named_queues.yml]` task.
|
6
|
+
|
7
|
+
For example:
|
8
|
+
```bash
|
9
|
+
PHILOTIC_RABBIT_HOST=localhost bundle exec rake eb:init_queues[path/to/named_queues.yml]
|
10
|
+
```
|
11
|
+
|
12
|
+
|
13
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift File.expand_path( '../../../lib', __FILE__ )
|
3
|
+
$stdout.sync = true
|
4
|
+
|
5
|
+
require 'philotic'
|
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
|
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift File.expand_path( '../../../lib', __FILE__ )
|
3
|
+
$stdout.sync = true
|
4
|
+
|
5
|
+
require 'philotic'
|
6
|
+
require 'rake'
|
7
|
+
|
8
|
+
require 'philotic/tasks'
|
9
|
+
# equivelant of:
|
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"))
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift File.expand_path('../../../lib', __FILE__)
|
3
|
+
$stdout.sync = true
|
4
|
+
|
5
|
+
require 'pry'
|
6
|
+
|
7
|
+
require 'philotic'
|
8
|
+
require 'philotic/dummy_event'
|
9
|
+
|
10
|
+
EventMachine.run do
|
11
|
+
# hit Control + C to stop
|
12
|
+
#Signal.trap("INT") { EventMachine.stop }
|
13
|
+
#Signal.trap("TERM") { EventMachine.stop }
|
14
|
+
|
15
|
+
|
16
|
+
Philotic::Config.load_file(File.join(File.dirname(__FILE__), "../../", "philotic.yml"))
|
17
|
+
|
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
|
+
#}
|
22
|
+
|
23
|
+
|
24
|
+
Philotic::Connection.connect! do
|
25
|
+
def send_message number
|
26
|
+
dummy_event = Philotic::DummyEvent.new
|
27
|
+
|
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'
|
32
|
+
|
33
|
+
dummy_event.subject = "Hey"
|
34
|
+
dummy_event.available = true
|
35
|
+
dummy_event.gender = [:F, :M].sample
|
36
|
+
|
37
|
+
|
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
|
42
|
+
|
43
|
+
EM.add_timer rand/10 do
|
44
|
+
send_message number + 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
send_message 1
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift File.expand_path('../../../lib', __FILE__)
|
3
|
+
$stdout.sync = true
|
4
|
+
|
5
|
+
require 'philotic'
|
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
|
+
Philotic::Config.load_file(File.join(File.dirname(__FILE__), "../../", "philotic.yml"))
|
13
|
+
|
14
|
+
|
15
|
+
Philotic::Subscriber.subscribe(philotic_fire_hose: true) do |metadata, payload|
|
16
|
+
p metadata.attributes
|
17
|
+
p payload
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift File.expand_path('../../../lib', __FILE__)
|
3
|
+
$stdout.sync = true
|
4
|
+
|
5
|
+
require 'pry'
|
6
|
+
require 'philotic'
|
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
|
+
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
|
21
|
+
|
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
|
33
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift File.expand_path( '../../../lib', __FILE__ )
|
3
|
+
$stdout.sync = true
|
4
|
+
|
5
|
+
require 'pry'
|
6
|
+
require 'philotic'
|
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
|
23
|
+
end
|
data/lib/philotic.rb
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'awesome_print'
|
2
|
+
require 'active_support/all'
|
3
|
+
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
require 'logger'
|
7
|
+
|
8
|
+
|
9
|
+
module Philotic
|
10
|
+
mattr_accessor :logger
|
11
|
+
mattr_accessor :log_event_handler
|
12
|
+
|
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
|
+
def self.root
|
60
|
+
::Pathname.new File.expand_path('../../', __FILE__)
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.env
|
64
|
+
ENV['SERVICE_ENV'] || 'development'
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.exchange
|
68
|
+
Philotic::Connection.exchange
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.initialize_named_queue!(queue_name, config, &block)
|
72
|
+
config = config.deep_symbolize_keys
|
73
|
+
|
74
|
+
|
75
|
+
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
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.logger
|
110
|
+
@@logger ||= init_logger
|
111
|
+
end
|
112
|
+
|
113
|
+
def self.init_logger
|
114
|
+
Logger.new(STDOUT)
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.on_publish_event(&block)
|
118
|
+
@@log_event_handler = block
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.log_event_published(severity, metadata, payload, message)
|
122
|
+
if @@log_event_handler
|
123
|
+
@@log_event_handler.call(severity, metadata, payload, message)
|
124
|
+
else
|
125
|
+
logger.send(severity, "#{message}; message_metadata:#{metadata}, payload:#{payload.to_json}")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.connected?
|
130
|
+
Philotic::Connection.connected?
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.connect! &block
|
134
|
+
Philotic::Connection.connect! &block
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
require 'philotic/version'
|
139
|
+
require 'philotic/connection'
|
140
|
+
require 'philotic/config'
|
141
|
+
require 'philotic/routable'
|
142
|
+
require 'philotic/event'
|
143
|
+
require 'philotic/publisher'
|
144
|
+
require 'philotic/subscriber'
|