philotic 1.1.1 → 1.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b5aa6de95d72e998edad55939b1b194101189c96
4
- data.tar.gz: b1972e32e338076a218f18f96a32ca9150cb0ca1
3
+ metadata.gz: fb0f8544430bd4ed0961e39da04d9f8b31de77fb
4
+ data.tar.gz: 8179fe31b21760200bed1315dda3c2241998523b
5
5
  SHA512:
6
- metadata.gz: 3a3fc577e42079e2747e72b13905a831f1bdbccdfd7bbd6dae815e1fcb013fd1e8ee7e37d68444f4a773bea2c9005884c4f44d4be77ac20bae32de147f21a0a7
7
- data.tar.gz: 10075f5fd0473498dae8b45ea57eca725ffa48909eedb203cf31d9a8bcd7acb1a5f6b4642f275b313ccbb7f1a6f116ff0241b08b490187563357757461000cf0
6
+ metadata.gz: bf07ca965eb1503d85fa28910d37410d5076256f9dfe2f6d938643fa1cc0d43ce708541da7235f37172cd01da22520a695271d8b851248c7b9feb660a3e246b6
7
+ data.tar.gz: c37eedc369ed1c0f4257ba819f1596e6d41d177a0f4a1236f6fec432506b43f12f99a37b7a695532d7ef3ccf2c93f8fe9b517b4287c2003c75db32be1449cf3d
@@ -1,13 +1,17 @@
1
+ sudo: false
1
2
  language: ruby
2
3
  before_install: gem install bundler -v 1.10.6
3
4
  rvm:
4
5
  - 2.0.0
5
- - 2.1
6
- - 2.2
6
+ - 2.1.5
7
+ - 2.2.0
8
+ - 2.2.1
9
+ - 2.2.2
10
+ - 2.2.3
7
11
  - rbx-2
8
- # - jruby-19mode
12
+ - jruby-19mode
9
13
  - ruby-head
10
- # - jruby-head
14
+ - jruby-head
11
15
  script:
12
16
  - bundle exec rspec
13
17
  addons:
@@ -17,6 +21,11 @@ addons:
17
21
  notifications:
18
22
  hipchat:
19
23
  rooms:
20
- secure: akLY832/pt0+9Y2TFKpzW08bagPMY//AcQJ5JGzc0yd3hZbXTlkW4S8bMEclBeHBqLGCV6vaWeN90PiYwIBs4IWlxopPAop4BEWeqRvD8+B4fxarXYwejt54vH3v4iCnHhSNBpFJDbykyfL0f0g9fhvM48eHzhBXTxPZfpQ9nXs=
24
+ secure: HXE1RU8b95gp0/4QoQXws1dVSw+uHGg0wqb/q5EKBjvKXxaqfIrBWeZlTAn3ykz8HQja8YoUOlwFL7lpmwdbXlbmuSb0RPyqWURNvooDw3twn675E0dtf5vlKWbADsIK73Gs1LfR3Gpb0l/85T5P+/knNRkh9p43hqiRaW/LJ/M=
21
25
  template:
22
- - '%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message}'
26
+ - "%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message}"
27
+ matrix:
28
+ allow_failures:
29
+ - rvm: jruby-19mode
30
+ - rvm: jruby-head
31
+ - rvm: ruby-head
data/README.md CHANGED
@@ -69,7 +69,12 @@ end
69
69
 
70
70
  ### Tested with the following Rubies
71
71
  * 2.0.0
72
- * 2.1.x
73
- * 2.2.x
74
- * rbx-2
75
- * ruby-head
72
+ * 2.1.5
73
+ * 2.2.0
74
+ * 2.2.1
75
+ * 2.2.2
76
+ * 2.2.3
77
+ * rbx*2
78
+ * jruby*19mode
79
+ * ruby*head
80
+ * jruby*head
@@ -7,6 +7,8 @@ require 'awesome_print'
7
7
 
8
8
  philotic = Philotic::Connection.new
9
9
 
10
+ MessageClass = Class.new(Philotic::Message)
11
+
10
12
  # override the message return handler
11
13
  philotic.config.message_return_handler = lambda do |basic_return, metadata, message|
12
14
  philotic.logger.warn { "Message returned. reply_text: #{basic_return.reply_text}" }
@@ -23,7 +25,7 @@ end
23
25
  # to keep the parent thread alive while the subscribers do their thing
24
26
  # but this infinite publish loop takes care of that
25
27
  loop do
26
- message = Philotic::Message.new({header_key: "header_#{[1, 2].sample}"}, {payload_key: 'payload_value'})
28
+ message = MessageClass.new({header_key: "header_#{[1, 2].sample}"}, {payload_key: 'payload_value'})
27
29
  philotic.publish message
28
30
  # only send a message every two seconds so we can see whats going on
29
31
  sleep 2
@@ -1,12 +1,6 @@
1
1
  require 'pathname'
2
2
 
3
3
  module Philotic
4
- class << self
5
- def root
6
- ::Pathname.new File.expand_path('../../', __FILE__)
7
- end
8
- end
9
-
10
4
  end
11
5
 
12
6
  require 'philotic/constants'
@@ -17,6 +11,7 @@ require 'philotic/version'
17
11
  require 'philotic/config'
18
12
  require 'philotic/message'
19
13
  require 'philotic/publisher'
14
+ require 'philotic/serialization'
20
15
  require 'philotic/subscriber'
21
16
  require 'philotic/consumer'
22
17
  require 'philotic/logging'
@@ -1,46 +1,20 @@
1
1
  require 'yaml'
2
- require 'json'
2
+ require 'multi_json'
3
+ require 'oj'
3
4
  require 'singleton'
4
5
  require 'forwardable'
5
6
  require 'cgi'
6
7
  require 'bunny/session'
7
8
  require 'logger'
9
+ require 'philotic/config/defaults'
10
+ require 'active_support/inflections'
8
11
 
9
12
  module Philotic
10
13
  class Config
11
14
 
12
- ENV_PREFIX = 'PHILOTIC'
15
+ include Defaults
13
16
 
14
- DEFAULT_DISABLE_PUBLISH = false
15
- DEFAULT_INITIALIZE_NAMED_QUEUES = false
16
- DEFAULT_DELETE_EXISTING_QUEUES = false
17
- DEFAULT_LOG_LEVEL = Logger::DEBUG
18
- DEFAULT_RABBIT_SCHEME = 'amqp'
19
- DEFAULT_RABBIT_HOST = 'localhost'
20
- DEFAULT_RABBIT_PORT = 5672
21
- DEFAULT_RABBIT_USER = 'guest'
22
- DEFAULT_RABBIT_PASSWORD = 'guest'
23
- DEFAULT_RABBIT_VHOST = '%2f' # '/'
24
- DEFAULT_RABBIT_URL = "#{DEFAULT_RABBIT_SCHEME}://#{DEFAULT_RABBIT_USER}:#{DEFAULT_RABBIT_PASSWORD}@#{DEFAULT_RABBIT_HOST}:#{DEFAULT_RABBIT_PORT}/#{DEFAULT_RABBIT_VHOST}"
25
- DEFAULT_EXCHANGE_NAME = 'philotic.headers'
26
- DEFAULT_TIMEOUT = 2
27
- DEFAULT_ROUTING_KEY = nil
28
- DEFAULT_PERSISTENT = false
29
- DEFAULT_IMMEDIATE = false
30
- DEFAULT_MANDATORY = false
31
- DEFAULT_CONTENT_TYPE = 'application/json'
32
- DEFAULT_CONTENT_ENCODING = nil
33
- DEFAULT_PRIORITY = nil
34
- DEFAULT_MESSAGE_ID = nil
35
- DEFAULT_CORRELATION_ID = nil
36
- DEFAULT_REPLY_TO = nil
37
- DEFAULT_TYPE = nil
38
- DEFAULT_USER_ID = nil
39
- DEFAULT_APP_ID = nil
40
- DEFAULT_TIMESTAMP = nil
41
- DEFAULT_EXPIRATION = nil
42
- DEFAULT_CONNECTION_ATTEMPTS = 3
43
- DEFAULT_PREFETCH_COUNT = 0
17
+ ENV_PREFIX = 'PHILOTIC'
44
18
 
45
19
  attr_accessor :connection
46
20
 
@@ -53,29 +27,6 @@ module Philotic
53
27
  connection.logger
54
28
  end
55
29
 
56
- def defaults
57
- @defaults ||= Hash[Config.constants.select { |c| c.to_s.start_with? 'DEFAULT_' }.collect do |c|
58
- key = c.slice(8..-1).downcase.to_sym
59
-
60
- env_key = "#{ENV_PREFIX}_#{key}".upcase
61
-
62
- [key, ENV[env_key] || Config.const_get(c)]
63
- end
64
- ]
65
- end
66
-
67
- Config.constants.each do |c|
68
- if c.to_s.start_with? 'DEFAULT_'
69
- attr_symbol = c.slice(8..-1).downcase.to_sym
70
- attr_writer attr_symbol
71
- class_eval %Q{
72
- def #{attr_symbol}
73
- @#{attr_symbol} ||= defaults[:#{attr_symbol}]
74
- end
75
- }
76
- end
77
- end
78
-
79
30
  def log_level
80
31
  @log_level ||= defaults[:log_level].to_i
81
32
  end
@@ -88,20 +39,7 @@ module Philotic
88
39
  @prefetch_count ||= defaults[:prefetch_count].to_i
89
40
  end
90
41
 
91
- attr_writer :connection_failed_handler, :connection_loss_handler, :message_return_handler
92
-
93
- def connection_failed_handler
94
- @connection_failed_handler ||= lambda do |settings|
95
- logger.error { "RabbitMQ connection failure: #{sanitized_rabbit_url}" }
96
- end
97
- end
98
-
99
- def connection_loss_handler
100
- @connection_loss_handler ||= lambda do |conn, settings|
101
- logger.warn { "RabbitMQ connection loss: #{sanitized_rabbit_url}" }
102
- conn.reconnect(false, 2)
103
- end
104
- end
42
+ attr_writer :message_return_handler
105
43
 
106
44
  def message_return_handler
107
45
  @message_return_handler ||= lambda do |basic_return, metadata, payload|
@@ -118,7 +56,7 @@ module Philotic
118
56
  current_value = send("rabbit_#{setting}")
119
57
 
120
58
  # only use the value from the URI if the existing value is nil or the default
121
- if settings[setting] && [self.class.const_get("default_rabbit_#{setting}".upcase), nil].include?(current_value)
59
+ if settings[setting] && [Defaults.const_get("rabbit_#{setting}".upcase), nil].include?(current_value)
122
60
  send("rabbit_#{setting}=", settings[setting])
123
61
  end
124
62
  end
@@ -146,5 +84,14 @@ module Philotic
146
84
  config = YAML.load_file(filename)
147
85
  load_config(config[env])
148
86
  end
87
+
88
+ def serializations
89
+ self.serializations = MultiJson.load(defaults[:serializations]) unless @serializations
90
+ @serializations
91
+ end
92
+
93
+ def content_type
94
+ Philotic::Serialization::Serializer.factory(serializations.last).content_type
95
+ end
149
96
  end
150
- end
97
+ end
@@ -0,0 +1,71 @@
1
+ require 'logger'
2
+
3
+ module Philotic
4
+ class Config
5
+ module Defaults
6
+
7
+ DISABLE_PUBLISH = false
8
+ INITIALIZE_NAMED_QUEUES = false
9
+ DELETE_EXISTING_QUEUES = false
10
+ LOG_LEVEL = Logger::DEBUG
11
+ RABBIT_SCHEME = 'amqp'
12
+ RABBIT_HOST = 'localhost'
13
+ RABBIT_PORT = 5672
14
+ RABBIT_USER = 'guest'
15
+ RABBIT_PASSWORD = 'guest'
16
+ RABBIT_VHOST = '%2f' # '/'
17
+ RABBIT_URL = "#{RABBIT_SCHEME}://#{RABBIT_USER}:#{RABBIT_PASSWORD}@#{RABBIT_HOST}:#{RABBIT_PORT}/#{RABBIT_VHOST}"
18
+ EXCHANGE_NAME = 'philotic.headers'
19
+ ROUTING_KEY = nil
20
+ PERSISTENT = false
21
+ IMMEDIATE = false
22
+ MANDATORY = false
23
+ SERIALIZATIONS = '["json"]' # serializations is expected to be a JSON ray of strings
24
+ CONTENT_TYPE = 'application/json'
25
+ CONTENT_ENCODING = nil
26
+ PRIORITY = nil
27
+ MESSAGE_ID = nil
28
+ CORRELATION_ID = nil
29
+ REPLY_TO = nil
30
+ TYPE = nil
31
+ USER_ID = nil
32
+ APP_ID = nil
33
+ TIMESTAMP = nil
34
+ EXPIRATION = nil
35
+ CONNECTION_ATTEMPTS = 3
36
+ PREFETCH_COUNT = 0
37
+ AUTOMATICALLY_RECOVER = true
38
+ NETWORK_RECOVERY_INTERVAL = 5 # seconds
39
+ CONTINUATION_TIMEOUT = 4000 # ms
40
+ RAISE_ERROR_ON_PUBLISH = false
41
+ ENCRYPTION_KEY = nil
42
+
43
+
44
+ def defaults
45
+ @defaults ||= Hash[Philotic::Config::Defaults.constants.map do |c|
46
+ key = c.downcase.to_sym
47
+
48
+ env_key = "#{ENV_PREFIX}_#{key}".upcase
49
+
50
+ [key, ENV[env_key] || Philotic::Config::Defaults.const_get(c)]
51
+ end
52
+ ]
53
+ end
54
+
55
+ def self.included(base)
56
+ Philotic::Config::Defaults.constants.each do |c|
57
+ attr_symbol = c.downcase.to_sym
58
+ base.send(:attr_writer, attr_symbol)
59
+ base.class_eval %Q{
60
+ def #{attr_symbol}
61
+ unless defined? @#{attr_symbol}
62
+ @#{attr_symbol} = defaults[:#{attr_symbol}]
63
+ end
64
+ @#{attr_symbol}
65
+ end
66
+ }
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -82,9 +82,9 @@ module Philotic
82
82
 
83
83
  def connection_settings
84
84
  {
85
- timeout: config.timeout.to_i,
86
- automatic_recovery: true,
87
- on_tcp_connection_failure: config.connection_failed_handler,
85
+ automatically_recover: config.automatically_recover,
86
+ network_recovery_interval: config.network_recovery_interval,
87
+ continuation_timeout: config.continuation_timeout,
88
88
  }
89
89
  end
90
90
 
@@ -1,47 +1,39 @@
1
1
  module Philotic
2
2
 
3
- CONNECTION_OPTIONS = [
4
- :rabbit_host,
5
- :connection_failed_handler,
6
- :connection_loss_handler,
7
- :timeout,
8
- ]
9
- EXCHANGE_OPTIONS = [
10
- :exchange_name,
11
- :message_return_handler,
12
- ]
13
- MESSAGE_OPTIONS = [
14
- :routing_key,
15
- :persistent,
16
- :immediate,
17
- :mandatory,
18
- :content_type,
19
- :content_encoding,
20
- :priority,
21
- :message_id,
22
- :correlation_id,
23
- :reply_to,
24
- :type,
25
- :user_id,
26
- :app_id,
27
- :timestamp,
28
- :expiration,
3
+ MESSAGE_OPTIONS = [
4
+ :routing_key,
5
+ :persistent,
6
+ :immediate,
7
+ :mandatory,
8
+ :content_type,
9
+ :content_encoding,
10
+ :priority,
11
+ :message_id,
12
+ :correlation_id,
13
+ :reply_to,
14
+ :type,
15
+ :user_id,
16
+ :app_id,
17
+ :timestamp,
18
+ :expiration,
29
19
  ]
30
20
 
31
21
  PHILOTIC_HEADERS = [
32
- :philotic_firehose,
33
- :philotic_product,
34
- :philotic_component,
35
- :philotic_message_type,
22
+ :philotic_firehose,
23
+ :philotic_product,
24
+ :philotic_component,
25
+ :philotic_message_type,
26
+ :philotic_serializations,
27
+
36
28
  ]
37
29
 
38
30
  DEFAULT_NAMED_QUEUE_OPTIONS = {
39
- auto_delete: false,
40
- durable: true
31
+ auto_delete: false,
32
+ durable: true
41
33
  }
42
34
  DEFAULT_ANONYMOUS_QUEUE_OPTIONS = {
43
- auto_delete: true,
44
- durable: false
35
+ auto_delete: true,
36
+ durable: false
45
37
  }
46
38
 
47
39
  DEFAULT_SUBSCRIBE_OPTIONS = {}
@@ -1,5 +1,6 @@
1
1
  require 'philotic/constants'
2
2
  require 'philotic/singleton'
3
+ require 'active_support/inflections'
3
4
 
4
5
  module Philotic
5
6
  class Message
@@ -30,9 +31,10 @@ module Philotic
30
31
 
31
32
  def initialize(routables={}, payloads={}, connection=nil)
32
33
  raise NotInstantiableError if self.class == Philotic::Message
33
- self.timestamp = Time.now.to_i
34
- self.philotic_firehose = true
35
- self.connection = connection
34
+ self.timestamp = Time.now.to_i
35
+ self.philotic_firehose = true
36
+ self.connection = connection
37
+ self.philotic_serializations = self.connection.config.serializations
36
38
 
37
39
  # dynamically insert any passed in routables into both attr_routable
38
40
  # and attr_payload
@@ -1,4 +1,5 @@
1
1
  require 'philotic/constants'
2
+ require 'philotic/serialization/serializer'
2
3
 
3
4
  module Philotic
4
5
  class Publisher
@@ -26,6 +27,7 @@ module Philotic
26
27
  rescue => e
27
28
  message.publish_error = e
28
29
  logger.error e.message
30
+ raise e if config.raise_error_on_publish
29
31
  end
30
32
  message
31
33
  end
@@ -55,7 +57,7 @@ module Philotic
55
57
 
56
58
  payload = normalize_payload_times(payload)
57
59
 
58
- connection.exchange.publish(payload.to_json, metadata)
60
+ connection.exchange.publish(Philotic::Serialization::Serializer.dump(payload, metadata), metadata)
59
61
  log_message_published(:debug, metadata, payload, 'published message')
60
62
  true
61
63
  end
@@ -0,0 +1,8 @@
1
+ require 'philotic/serialization/serializer'
2
+ require 'philotic/serialization/encryptor'
3
+ require 'philotic/serialization/json'
4
+
5
+ module Philotic
6
+ module Serialization
7
+ end
8
+ end
@@ -0,0 +1,56 @@
1
+ require 'encryptor'
2
+ require 'philotic/serialization/serializer'
3
+ require 'base64'
4
+
5
+ module Philotic
6
+ module Serialization
7
+ module Encryptor
8
+ extend self
9
+
10
+ def content_type
11
+ 'application/json'
12
+ end
13
+
14
+ def serialization
15
+ :encrypted
16
+ end
17
+
18
+ def default_encryption_key
19
+ Philotic.config.encryption_key
20
+ end
21
+
22
+ def random_salt
23
+ Base64.encode64 SecureRandom.random_bytes(256)
24
+ end
25
+
26
+ def default_algorithm
27
+ 'aes-256-cbc'
28
+ end
29
+
30
+ def random_iv(algorithm = default_algorithm)
31
+ OpenSSL::Cipher::Cipher.new(algorithm).random_iv
32
+ end
33
+
34
+ def key
35
+ @key ||= default_encryption_key
36
+ end
37
+
38
+ def dump(payload, metadata)
39
+ metadata[:headers][:encryption] ||= {}
40
+ algorithm = (metadata[:headers][:encryption][:algorithm] ||= default_algorithm)
41
+ iv = Base64.decode64(metadata[:headers][:encryption][:iv] ||= Base64.encode64(random_iv(algorithm)))
42
+ salt = Base64.decode64(metadata[:headers][:encryption][:salt] ||= Base64.encode64(random_salt))
43
+ Base64.encode64 ::Encryptor.encrypt(payload, key: key, iv: iv, salt: salt)
44
+ end
45
+
46
+ def load(payload, metadata)
47
+ headers = metadata[:headers].deep_dup.deep_symbolize_keys
48
+
49
+ iv = Base64.decode64 headers[:encryption][:iv]
50
+ salt = Base64.decode64 headers[:encryption][:salt]
51
+ ::Encryptor.decrypt(Base64.decode64(payload), key: key, iv: iv, salt: salt)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ Philotic::Serialization::Serializer.register Philotic::Serialization::Encryptor
@@ -0,0 +1,29 @@
1
+ require 'multi_json'
2
+ require 'oj'
3
+
4
+ require 'philotic/serialization/serializer'
5
+
6
+ module Philotic
7
+ module Serialization
8
+ module Json
9
+ extend self
10
+
11
+ def content_type
12
+ 'application/json'
13
+ end
14
+
15
+ def serialization
16
+ :json
17
+ end
18
+
19
+ def dump(payload, metadata)
20
+ MultiJson.dump payload
21
+ end
22
+
23
+ def load(payload, metadata)
24
+ MultiJson.load payload
25
+ end
26
+ end
27
+ end
28
+ end
29
+ Philotic::Serialization::Serializer.register Philotic::Serialization::Json
@@ -0,0 +1,44 @@
1
+ module Philotic
2
+ module Serialization
3
+ module Serializer
4
+ extend self
5
+
6
+ def serializers
7
+ @serializers ||= {}
8
+ end
9
+
10
+ def factory(serialization)
11
+ serialization = serialization.to_s.downcase.to_sym
12
+ @serializers[serialization]
13
+ end
14
+
15
+ def register(serializer)
16
+ serializers[serializer.serialization] = serializer
17
+ end
18
+
19
+ # return the fully deserialized payload
20
+ def load(payload, metadata)
21
+ _transform(:load, payload, metadata)
22
+ end
23
+
24
+ def dump(payload, metadata)
25
+ _transform(:dump, payload, metadata)
26
+ end
27
+
28
+ private
29
+ def _transform(dump_or_load, payload, metadata)
30
+ headers = metadata[:headers].deep_dup.deep_symbolize_keys
31
+
32
+ serializations = headers[:philotic_serializations]
33
+
34
+ serializations.reverse! if(dump_or_load == :load)
35
+
36
+ serializations.reduce(payload.dup) do |transformed, serialization|
37
+ serializer = factory serialization
38
+ (serializer &&
39
+ serializer.public_send(dump_or_load, transformed, metadata)) || transformed
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,5 +1,6 @@
1
1
  require 'philotic/constants'
2
2
  require 'philotic/message'
3
+ require 'philotic/serialization/serializer'
3
4
 
4
5
  module Philotic
5
6
  class Subscriber
@@ -20,7 +21,7 @@ module Philotic
20
21
 
21
22
  def subscription_callback(&block)
22
23
  lambda do |delivery_info, metadata, payload|
23
- hash_payload = JSON.parse payload
24
+ hash_payload = Philotic::Serialization::Serializer.load(payload, metadata)
24
25
 
25
26
  message = Class.new(Philotic::Message).new(metadata[:headers], hash_payload)
26
27
  message.delivery_info = delivery_info
@@ -1,3 +1,3 @@
1
1
  module Philotic
2
- VERSION = '1.1.1'
2
+ VERSION = '1.2.0'
3
3
  end
@@ -17,16 +17,18 @@ Gem::Specification.new do |gem|
17
17
  gem.licenses = ['MIT']
18
18
 
19
19
  gem.add_development_dependency 'awesome_print', '~> 1.6'
20
- gem.add_development_dependency 'codeclimate-test-reporter', '~> 0.4'
21
20
  gem.add_development_dependency 'bundler', '~> 1.10'
21
+ gem.add_development_dependency 'codeclimate-test-reporter', '~> 0.4'
22
22
  gem.add_development_dependency 'pry', '~> 0.10'
23
23
  gem.add_development_dependency 'rake', '~> 10.4'
24
24
  gem.add_development_dependency 'rspec', '~> 3.3'
25
25
  gem.add_development_dependency 'rspec-its', '~> 1.2'
26
- gem.add_development_dependency 'timecop', '~> 0.8'
27
26
  gem.add_development_dependency 'simplecov', '~> 0.10'
27
+ gem.add_development_dependency 'timecop', '~> 0.8'
28
28
 
29
29
  gem.add_dependency 'activesupport', '>= 3.2'
30
+ gem.add_dependency 'encryptor', '~> 1.3'
30
31
  gem.add_dependency 'bunny', '~> 2.2'
31
- gem.add_dependency 'json', '>= 1.8'
32
- end
32
+ gem.add_dependency 'multi_json', '~> 1.11'
33
+ gem.add_dependency 'oj', '~> 2.12'
34
+ end
@@ -1,9 +1,6 @@
1
1
  defaults: &defaults
2
2
  #connection settings
3
3
  rabbit_host: localhost
4
- # connection_failed_handler: method/proc
5
- # connection_loss_handler: method/proc
6
- timeout: 2
7
4
 
8
5
  #exchange settings
9
6
  exchange_name: philotic.headers
@@ -14,7 +11,6 @@ defaults: &defaults
14
11
  persistent: false
15
12
  immediate: false
16
13
  mandatory: false
17
- content_type: ~
18
14
  content_encoding: ~
19
15
  priority: ~
20
16
  message_id: ~
@@ -4,13 +4,37 @@ require 'philotic/connection'
4
4
 
5
5
  describe Philotic::Config do
6
6
 
7
- describe '#defaults' do
8
- end
7
+ describe '#load_file' do
8
+ let(:config_file_path) { './philotic.yml.example' }
9
+ let(:config) { YAML.load_file(config_file_path)['test'] }
10
+
11
+ subject { described_class.new(instance_double Philotic::Connection) }
9
12
 
10
- describe '#load' do
13
+ it 'properly loads config' do
14
+ subject.load_file config_file_path, 'test'
15
+ expect(config.keys).to_not be :empty?
16
+ config.keys.each do |key|
17
+ expect(subject.send(key)).to eq config[key]
18
+ end
19
+ end
11
20
  end
12
21
 
13
- describe '#load_file' do
22
+
23
+ describe '#message_return_handler' do
24
+ let(:logger) { instance_double(Logger) }
25
+ let(:basic_return) { instance_double(Bunny::ReturnInfo) }
26
+ let(:metadata) { instance_double(Bunny::Session) }
27
+ let(:payload) { {foo: 'bar'}.to_json }
28
+ let(:connection) { instance_double(Philotic::Connection, logger: logger) }
29
+
30
+ subject { described_class.new(connection) }
31
+
32
+ it 'logs a warning do' do
33
+
34
+ expect(logger).to receive(:warn)
35
+ subject.message_return_handler.call basic_return, metadata, payload
36
+ end
37
+
14
38
  end
15
39
 
16
40
  describe '#parse_rabbit_uri' do
@@ -24,20 +48,20 @@ describe Philotic::Config do
24
48
  it do
25
49
  should change {
26
50
  [
27
- config.rabbit_user,
28
- config.rabbit_password,
29
- config.rabbit_host,
30
- config.rabbit_port,
31
- config.rabbit_vhost,
51
+ config.rabbit_user,
52
+ config.rabbit_password,
53
+ config.rabbit_host,
54
+ config.rabbit_port,
55
+ config.rabbit_vhost,
32
56
  ]
33
57
  }
34
- .to [
35
- 'user',
36
- 'pass',
37
- 'host',
38
- 12345,
39
- 'vhost',
40
- ]
58
+ .to [
59
+ 'user',
60
+ 'pass',
61
+ 'host',
62
+ 12345,
63
+ 'vhost',
64
+ ]
41
65
  end
42
66
  end
43
67
  end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ module Philotic
5
+ module Serialization
6
+ describe Encryptor do
7
+ let(:encryption_key) { 'super_secret_key' }
8
+
9
+ describe '.content_type' do
10
+ specify { expect(subject.content_type).to eq 'application/json' }
11
+ end
12
+
13
+ describe '.serialization' do
14
+ specify { expect(subject.serialization).to eq :encrypted }
15
+ end
16
+
17
+ describe '.default_encryption_key' do
18
+ it 'pulls the key from Philotic.config' do
19
+ expect(Philotic.config).to receive(:encryption_key) { encryption_key }
20
+ expect(subject.default_encryption_key).to eq encryption_key
21
+ end
22
+
23
+ describe 'encryption' do
24
+ let(:metadata) { {headers: {}} }
25
+ let(:payload) {'payload'}
26
+
27
+ it 'encrypts and decrypts the payload' do
28
+ expect(Philotic.config).to receive(:encryption_key) { encryption_key }
29
+
30
+ expect(subject.load(subject.dump(payload, metadata), metadata)).to eq payload
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -204,7 +204,9 @@ describe Philotic::Message do
204
204
  end
205
205
 
206
206
  describe '.publish' do
207
- let (:connection) { double }
207
+ let (:connection) { instance_double Philotic::Connection }
208
+ let (:config) { instance_double Philotic::Config }
209
+ let (:serializations) { ['json'].to_json }
208
210
  let(:headers) do
209
211
  {
210
212
  header1: 'h1',
@@ -222,7 +224,10 @@ describe Philotic::Message do
222
224
  end
223
225
  subject { Philotic::Message }
224
226
  specify do
225
- expect_any_instance_of(Philotic::Message).to receive(:connection).and_return(connection)
227
+ expect_any_instance_of(Philotic::Message).to receive(:connection).twice.and_return(connection)
228
+ expect(connection).to receive(:config).and_return(config)
229
+ expect(config).to receive(:serializations).and_return(serializations)
230
+
226
231
  expect(connection).to receive(:publish) do |message|
227
232
  expect(message.headers).to include(headers)
228
233
  expect(message.payload).to eq payloads
@@ -22,21 +22,22 @@ describe Philotic::Publisher do
22
22
  it 'should call _publish with the right values' do
23
23
  Timecop.freeze
24
24
  expect(subject).to receive(:_publish).with(
25
- {
26
- subject: 'Hello',
27
- message: 'How are you?'
25
+ {
26
+ subject: 'Hello',
27
+ message: 'How are you?'
28
+ },
29
+ {
30
+ headers: {
31
+ philotic_firehose: true,
32
+ philotic_product: nil,
33
+ philotic_component: nil,
34
+ philotic_message_type: nil,
35
+ philotic_serializations: Philotic.config.serializations,
36
+ hue: :M,
37
+ available: true,
28
38
  },
29
- {
30
- headers: {
31
- philotic_firehose: true,
32
- philotic_product: nil,
33
- philotic_component: nil,
34
- philotic_message_type: nil,
35
- hue: :M,
36
- available: true,
37
- },
38
- timestamp: Time.now.to_i
39
- }
39
+ timestamp: Time.now.to_i
40
+ }
40
41
  )
41
42
  expect(message).to_not be_published
42
43
  subject.publish(message)
@@ -80,38 +81,39 @@ describe Philotic::Publisher do
80
81
  expect(subject.connection).to receive(:connect!)
81
82
  expect(subject.connection).to receive(:connected?).and_return(true)
82
83
  metadata = {
83
- routing_key: nil,
84
- persistent: false,
85
- immediate: false,
86
- mandatory: false,
87
- content_type: 'application/json',
88
- content_encoding: nil,
89
- priority: nil,
90
- message_id: nil,
91
- correlation_id: nil,
92
- reply_to: nil,
93
- type: nil,
94
- user_id: nil,
95
- app_id: nil,
96
- expiration: nil,
97
- headers: {
98
- philotic_firehose: true,
99
- philotic_product: nil,
100
- philotic_component: nil,
101
- philotic_message_type: nil,
102
- hue: :M,
103
- available: true,
104
- },
105
- timestamp: Time.now.to_i
84
+ routing_key: nil,
85
+ persistent: false,
86
+ immediate: false,
87
+ mandatory: false,
88
+ content_type: 'application/json',
89
+ content_encoding: nil,
90
+ priority: nil,
91
+ message_id: nil,
92
+ correlation_id: nil,
93
+ reply_to: nil,
94
+ type: nil,
95
+ user_id: nil,
96
+ app_id: nil,
97
+ expiration: nil,
98
+ headers: {
99
+ philotic_firehose: true,
100
+ philotic_product: nil,
101
+ philotic_component: nil,
102
+ philotic_message_type: nil,
103
+ philotic_serializations: Philotic.config.serializations,
104
+ hue: :M,
105
+ available: true,
106
+ },
107
+ timestamp: Time.now.to_i
106
108
  }
107
109
 
108
110
 
109
111
  expect(exchange).to receive(:publish).with(
110
- {
111
- subject: 'Hello',
112
- message: 'How are you?'
113
- }.to_json,
114
- metadata
112
+ {
113
+ subject: 'Hello',
114
+ message: 'How are you?'
115
+ }.to_json,
116
+ metadata
115
117
  )
116
118
  expect(message).to_not be_published
117
119
  subject.publish(message)
@@ -7,6 +7,23 @@ require 'philotic/subscriber'
7
7
 
8
8
  describe Philotic::Subscriber do
9
9
 
10
+ describe '#logger' do
11
+ let(:logger) { instance_double(Logger) }
12
+ let(:connection) { instance_double(Philotic::Connection, logger: logger) }
13
+ subject { described_class.new connection }
14
+ it 'is the connection logger' do
15
+ expect(subject.logger).to be subject.connection.logger
16
+ end
17
+ end
18
+
19
+ describe '#config' do
20
+ let(:config) { instance_double(Philotic::Config) }
21
+ let(:connection) { instance_double(Philotic::Connection, config: config) }
22
+ subject { described_class.new connection }
23
+ it 'is the connection logger' do
24
+ expect(subject.config).to be subject.connection.config
25
+ end
26
+ end
10
27
 
11
28
  describe '#subscription_callback' do
12
29
 
@@ -18,7 +35,7 @@ describe Philotic::Subscriber do
18
35
  end
19
36
 
20
37
  let(:delivery_info) { double }
21
- let(:metadata) { {headers: {header_1: 'foo'}} }
38
+ let(:metadata) { {headers: {header_1: 'foo', philotic_serializations: Philotic.config.serializations}} }
22
39
  let(:payload) { {message: 'body'} }
23
40
 
24
41
  it 'hydrates received messages' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: philotic
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Keyes
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-12 00:00:00.000000000 Z
11
+ date: 2015-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: awesome_print
@@ -25,33 +25,33 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.6'
27
27
  - !ruby/object:Gem::Dependency
28
- name: codeclimate-test-reporter
28
+ name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.4'
33
+ version: '1.10'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.4'
40
+ version: '1.10'
41
41
  - !ruby/object:Gem::Dependency
42
- name: bundler
42
+ name: codeclimate-test-reporter
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.10'
47
+ version: '0.4'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.10'
54
+ version: '0.4'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: pry
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -109,33 +109,33 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '1.2'
111
111
  - !ruby/object:Gem::Dependency
112
- name: timecop
112
+ name: simplecov
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0.8'
117
+ version: '0.10'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '0.8'
124
+ version: '0.10'
125
125
  - !ruby/object:Gem::Dependency
126
- name: simplecov
126
+ name: timecop
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '0.10'
131
+ version: '0.8'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '0.10'
138
+ version: '0.8'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: activesupport
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +150,20 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '3.2'
153
+ - !ruby/object:Gem::Dependency
154
+ name: encryptor
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '1.3'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '1.3'
153
167
  - !ruby/object:Gem::Dependency
154
168
  name: bunny
155
169
  requirement: !ruby/object:Gem::Requirement
@@ -165,19 +179,33 @@ dependencies:
165
179
  - !ruby/object:Gem::Version
166
180
  version: '2.2'
167
181
  - !ruby/object:Gem::Dependency
168
- name: json
182
+ name: multi_json
169
183
  requirement: !ruby/object:Gem::Requirement
170
184
  requirements:
171
- - - ">="
185
+ - - "~>"
172
186
  - !ruby/object:Gem::Version
173
- version: '1.8'
187
+ version: '1.11'
174
188
  type: :runtime
175
189
  prerelease: false
176
190
  version_requirements: !ruby/object:Gem::Requirement
177
191
  requirements:
178
- - - ">="
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '1.11'
195
+ - !ruby/object:Gem::Dependency
196
+ name: oj
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: '2.12'
202
+ type: :runtime
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
179
207
  - !ruby/object:Gem::Version
180
- version: '1.8'
208
+ version: '2.12'
181
209
  description: Lightweight, opinionated wrapper for using RabbitMQ headers exchanges
182
210
  email:
183
211
  - nkeyes@gmail.com
@@ -204,6 +232,7 @@ files:
204
232
  - examples/subscribing/named_queue.rb
205
233
  - lib/philotic.rb
206
234
  - lib/philotic/config.rb
235
+ - lib/philotic/config/defaults.rb
207
236
  - lib/philotic/connection.rb
208
237
  - lib/philotic/constants.rb
209
238
  - lib/philotic/consumer.rb
@@ -213,6 +242,10 @@ files:
213
242
  - lib/philotic/logging/message.rb
214
243
  - lib/philotic/message.rb
215
244
  - lib/philotic/publisher.rb
245
+ - lib/philotic/serialization.rb
246
+ - lib/philotic/serialization/encryptor.rb
247
+ - lib/philotic/serialization/json.rb
248
+ - lib/philotic/serialization/serializer.rb
216
249
  - lib/philotic/singleton.rb
217
250
  - lib/philotic/subscriber.rb
218
251
  - lib/philotic/tasks.rb
@@ -226,6 +259,7 @@ files:
226
259
  - spec/philotic/connection_spec.rb
227
260
  - spec/philotic/consumer_spec.rb
228
261
  - spec/philotic/logging/logger_spec.rb
262
+ - spec/philotic/logging/serialization/encryptor_spec.rb
229
263
  - spec/philotic/message_spec.rb
230
264
  - spec/philotic/publisher_spec.rb
231
265
  - spec/philotic/subscriber_spec.rb
@@ -261,6 +295,7 @@ test_files:
261
295
  - spec/philotic/connection_spec.rb
262
296
  - spec/philotic/consumer_spec.rb
263
297
  - spec/philotic/logging/logger_spec.rb
298
+ - spec/philotic/logging/serialization/encryptor_spec.rb
264
299
  - spec/philotic/message_spec.rb
265
300
  - spec/philotic/publisher_spec.rb
266
301
  - spec/philotic/subscriber_spec.rb