sensu-redis 1.6.1 → 2.0.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: c2ae81e88a971e4f2a7e4dd8a4fb8fa5d293d0d9
4
- data.tar.gz: 469995301c9de2f01dbafd4865ba342b6337499d
3
+ metadata.gz: 5bfbf215d8c3a1975203dc6f5c08d65e54ff3167
4
+ data.tar.gz: 9ba122e38b68809b037ddf97a338729a6d8104fc
5
5
  SHA512:
6
- metadata.gz: 3c5493adc40c41ae6e7fc38da259d239bc807e0a56dc835b6c4e4dfaa22b0c034246b057bddc95e4760be6889782f244af99ee1d8cb444695834ee68c691f9ba
7
- data.tar.gz: 0cddcba167fc57f6b6e61f9513034716790a51125d6f957721f9fcda60586fc7937943c67fdd3647c89531b03e3b3e0e1eb7cff3b91e322da2b30627a413fe80
6
+ metadata.gz: 0416a9108788879d8cb8a6f688142a85b87f9c5d5a324c0e8301f823557f3d8994b5e2413719e178ed785579fd7e452de6d3ac3c03e7251f6199eef600081b7f
7
+ data.tar.gz: 84569b024c3cae5f170ddc0e3c5fa39ebff6b838ed7c6952190c54e236534743f159e7b61c753153ded0d6137b835a991166887dd248fad9f6330d314e98866c
data/README.md CHANGED
@@ -2,9 +2,6 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/sensu/sensu-redis.svg?branch=master)](https://travis-ci.org/sensu/sensu-redis)
4
4
 
5
- [![Code Climate](https://codeclimate.com/github/sensu/sensu-redis.png)](https://codeclimate.com/github/sensu/sensu-redis)
6
- [![Code Climate Coverage](https://codeclimate.com/github/sensu/sensu-redis/coverage.png)](https://codeclimate.com/github/sensu/sensu-redis)
7
-
8
5
  ## Installation
9
6
 
10
7
  Add this line to your application's Gemfile:
data/lib/sensu/redis.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "rubygems"
2
+ require "sensu/redis/utilities"
2
3
  require "sensu/redis/client"
3
4
  require "sensu/redis/sentinel"
4
5
  require "eventmachine"
@@ -7,6 +8,15 @@ require "uri"
7
8
  module Sensu
8
9
  module Redis
9
10
  class << self
11
+ include Utilities
12
+
13
+ # Set the Redis logger.
14
+ #
15
+ # @param logger [Object] Redis logger.
16
+ def logger=(logger)
17
+ @logger = logger
18
+ end
19
+
10
20
  # Parse a Redis URL. An argument error exception is thrown if
11
21
  # this method is unable to parse the provided URL string.
12
22
  #
@@ -34,18 +44,35 @@ module Sensu
34
44
  sentinel = Sentinel.new(options)
35
45
  sentinel.resolve do |host, port|
36
46
  redis = EM.connect(host, port, Client, options)
47
+ redis.logger = @logger
37
48
  redis.sentinel = sentinel
38
49
  block.call(redis)
39
50
  end
40
51
  end
41
52
 
42
53
  # Connect to the current Redis master directly, using the
43
- # provided connection options.
54
+ # provided connection options. This method uses `resolve_host()`
55
+ # to first resolve the provided host, if it's not already an IP
56
+ # address. Resolving the hostname upfront guards against lookup
57
+ # failures that would cause the Sensu process to crash. Upfront
58
+ # hostname resolution also allows this Redis library to work
59
+ # with Amazon AWS ElastiCache & where DNS is used as a failover
60
+ # mechanism.
44
61
  #
45
62
  # @param options [Hash]
46
63
  # @yield callback to be called with the redis connection object.
47
64
  def connect_direct(options, &block)
48
- block.call(EM.connect(options[:host], options[:port], Client, options))
65
+ resolve_host(options[:host]) do |ip_address|
66
+ if ip_address.nil?
67
+ EM::Timer.new(1) do
68
+ connect_direct(options, &block)
69
+ end
70
+ else
71
+ redis = EM.connect(ip_address, options[:port], Client, options)
72
+ redis.logger = @logger
73
+ block.call(redis)
74
+ end
75
+ end
49
76
  end
50
77
 
51
78
  # Connect to Redis using the provided connection options.
@@ -1,13 +1,15 @@
1
1
  require "sensu/redis/client/constants"
2
2
  require "sensu/redis/client/errors"
3
+ require "sensu/redis/utilities"
3
4
  require "eventmachine"
4
5
 
5
6
  module Sensu
6
7
  module Redis
7
8
  class Client < EM::Connection
8
9
  include EM::Deferrable
10
+ include Utilities
9
11
 
10
- attr_accessor :sentinel, :auto_reconnect, :reconnect_on_error
12
+ attr_accessor :logger, :sentinel, :auto_reconnect, :reconnect_on_error
11
13
 
12
14
  # Initialize the connection, creating the Redis command methods,
13
15
  # and setting the default connection options and callbacks.
@@ -81,13 +83,28 @@ module Sensu
81
83
 
82
84
  # Reconnect to Redis. The before reconnect callback is first
83
85
  # called if not already reconnecting. This method uses a 1
84
- # second delay before attempting a reconnect.
86
+ # second delay before attempting a reconnect. The method
87
+ # `determine_address()` is used to determine the correct host
88
+ # and port to reconnect to, either via Sentinel (new master) or
89
+ # the previous host and port. This method uses `resolve_host()`
90
+ # to first resolve the determined host, if it's not already an
91
+ # IP address. Resolving the hostname upfront guards against
92
+ # lookup failures that would cause the Sensu process to crash.
93
+ # Upfront hostname resolution also allows this Redis library to
94
+ # work with Amazon AWS ElastiCache & where DNS is used as a
95
+ # failover mechanism.
85
96
  def reconnect!
86
97
  @reconnect_callbacks[:before].call unless @reconnecting
87
98
  @reconnecting = true
88
99
  EM.add_timer(1) do
89
100
  determine_address do |host, port|
90
- reconnect(host, port)
101
+ resolve_host(host) do |ip_address|
102
+ if ip_address.nil?
103
+ reconnect!
104
+ else
105
+ reconnect(ip_address, port)
106
+ end
107
+ end
91
108
  end
92
109
  end
93
110
  end
@@ -55,7 +55,6 @@ module Sensu
55
55
  end
56
56
  end
57
57
 
58
-
59
58
  # Create a Sentinel master resolve timeout, causing the previous
60
59
  # attempt to fail/cancel, while beginning another attempt.
61
60
  #
@@ -0,0 +1,68 @@
1
+ require "ipaddr"
2
+ require "socket"
3
+
4
+ module Sensu
5
+ module Redis
6
+ module Utilities
7
+ # Determine if a host is an IP address (or DNS hostname).
8
+ #
9
+ # @param host [String]
10
+ # @return [TrueClass, FalseClass]
11
+ def ip_address?(host)
12
+ begin
13
+ ip_address = IPAddr.new(host)
14
+ ip_address.ipv4? || ip_address.ipv6?
15
+ rescue IPAddr::InvalidAddressError
16
+ false
17
+ end
18
+ end
19
+
20
+ # Resolve a hostname to an IP address for a host. This method
21
+ # will return `nil` to the provided block when the hostname
22
+ # cannot be resolved to an IP address.
23
+ #
24
+ # @param host [String]
25
+ # @param block [Proc] called with the result of the DNS
26
+ # query (IP address).
27
+ def resolve_hostname(host, &block)
28
+ resolve = Proc.new do
29
+ begin
30
+ info = case RUBY_PLATFORM
31
+ when /linux/
32
+ flags = Socket::AI_NUMERICSERV | Socket::AI_ADDRCONFIG
33
+ Socket.getaddrinfo(host, nil, Socket::AF_UNSPEC, nil, nil, flags)
34
+ else
35
+ Socket.getaddrinfo(host, nil)
36
+ end
37
+ info.first.nil? ? nil : info.first[2]
38
+ rescue => error
39
+ @logger.error("redis connection error", {
40
+ :reason => "unable to resolve hostname",
41
+ :host => host,
42
+ :error => error.to_s
43
+ }) if @logger
44
+ nil
45
+ end
46
+ end
47
+ EM.defer(resolve, block)
48
+ end
49
+
50
+ # Resolve a hostname to an IP address for a host. This method
51
+ # will return the provided host to the provided block if it
52
+ # is already an IP address. This method will return `nil` to the
53
+ # provided block when the hostname cannot be resolved to an
54
+ # IP address.
55
+ #
56
+ # @param host [String]
57
+ # @param block [Proc] called with the result of the DNS
58
+ # query (IP address).
59
+ def resolve_host(host, &block)
60
+ if ip_address?(host)
61
+ yield host
62
+ else
63
+ resolve_hostname(host, &block)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
data/sensu-redis.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "sensu-redis"
5
- spec.version = "1.6.1"
5
+ spec.version = "2.0.0"
6
6
  spec.authors = ["Sean Porter"]
7
7
  spec.email = ["portertech@gmail.com"]
8
8
  spec.summary = "The Sensu Redis client library"
@@ -20,5 +20,4 @@ Gem::Specification.new do |spec|
20
20
  spec.add_development_dependency "bundler", "~> 1.6"
21
21
  spec.add_development_dependency "rake", "10.5.0"
22
22
  spec.add_development_dependency "rspec"
23
- spec.add_development_dependency "codeclimate-test-reporter" unless RUBY_VERSION < "1.9"
24
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sensu-redis
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Porter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-12 00:00:00.000000000 Z
11
+ date: 2016-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: eventmachine
@@ -66,20 +66,6 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: codeclimate-test-reporter
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
69
  description: The Sensu Redis client library
84
70
  email:
85
71
  - portertech@gmail.com
@@ -94,6 +80,7 @@ files:
94
80
  - lib/sensu/redis/client/constants.rb
95
81
  - lib/sensu/redis/client/errors.rb
96
82
  - lib/sensu/redis/sentinel.rb
83
+ - lib/sensu/redis/utilities.rb
97
84
  - sensu-redis.gemspec
98
85
  homepage: https://github.com/sensu/sensu-redis
99
86
  licenses: