dalli-elasticache 0.2.0 → 2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3223c4e9eb1fd636a8841a415905203022f03276
4
- data.tar.gz: b853a9d5674e3d4335cd8b6046f3dfa3eba5ef0f
2
+ SHA256:
3
+ metadata.gz: 1da71566964e9f17cacf29d2c670d15d7adb80e4b4cc86f8371ea98eb2b80928
4
+ data.tar.gz: 7b58a9dc5efb77773c0da4de9b1891bbdc5c98d8d4012e13fd432a7906ea6e16
5
5
  SHA512:
6
- metadata.gz: aa250e3c5c9aa4e55434c7d05b76deaea939735414dafac2cd5b2a3dbf42b46042c7931420f872e837a79384394f15a1f1e48f32d9d44eca529f4896e6fc9063
7
- data.tar.gz: 627f5c1718932bcbfd7cd661a8c03b55e1ccbb714478598ffffcb28e247f07b503a2e3208f3c90b3778a2a62bbf9496f5ae884f5e470a702f9cd6451d22ddefb
6
+ metadata.gz: 04cf01bc3a0ff7c14c3173b05be796038bbe3ad45292bffdacb95834900bd8c40ecd224c206f676f3bdfde2e256beb3812d73b156723235daeabace027de704d
7
+ data.tar.gz: 13668d4ead1f6e6fd5e2288d5124a1cb47751d7f97dd4a2f50f288c3db123a7c2228d88b4264ea499091e9ebe0fd1db4167b71cd0b8ba8224793847f6dc4f94a
data/README.md CHANGED
@@ -1,46 +1,63 @@
1
- Dalli ElastiCache [![Gem Version](https://badge.fury.io/rb/dalli-elasticache.svg)](http://badge.fury.io/rb/dalli-elasticache) [![Build Status](https://travis-ci.org/ktheory/dalli-elasticache.svg)](https://travis-ci.org/ktheory/dalli-elasticache) [![Code Climate](https://codeclimate.com/github/ktheory/dalli-elasticache.png)](https://codeclimate.com/github/ktheory/dalli-elasticache)
1
+ Dalli ElastiCache [![Gem Version](https://badge.fury.io/rb/dalli-elasticache.svg)](http://badge.fury.io/rb/dalli-elasticache) [![Build Status](https://github.com/ktheory/dalli-elasticache/actions/workflows/tests.yml/badge.svg)](https://github.com/ktheory/dalli-elasticache/actions/workflows/tests.yml) [![Code Climate](https://codeclimate.com/github/ktheory/dalli-elasticache.png)](https://codeclimate.com/github/ktheory/dalli-elasticache)
2
2
  =================
3
3
 
4
- Use [AWS ElastiCache AutoDiscovery](http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/AutoDiscovery.html) to automatically configure your [Dalli memcached client](https://github.com/mperham/dalli) with all the nodes in your cluster.
4
+ Use [AWS ElastiCache AutoDiscovery](https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/AutoDiscovery.html) or [Google Cloud MemoryStore Auto Discovery](https://cloud.google.com/memorystore/docs/memcached/using-auto-discovery) to automatically configure your [Dalli memcached client](https://github.com/petergoldstein/dalli) with all the nodes in your cluster.
5
5
 
6
6
  Installation
7
7
  ------------
8
8
 
9
- Install the [rubygem](https://rubygems.org/gems/dalli-elasticache):
9
+ Install the [gem](https://rubygems.org/gems/dalli-elasticache):
10
10
 
11
11
  ```ruby
12
12
  # in your Gemfile
13
13
  gem 'dalli-elasticache'
14
14
  ```
15
15
 
16
- Setup for Rails 3.x and Newer
17
- -----------------------------
16
+ Using Dalli Elasticache in Rails
17
+ ---------------------------------
18
18
 
19
- Configure your environment-specific application settings:
19
+ Note that the list of memcached servers used by Rails will be refreshed each time an app server process starts. If the list of nodes in your cluster changes, this configuration will not be reflected in the Rails configuraiton without such a server process restart.
20
+
21
+ ### Configuring a Cache Store
22
+
23
+ The most common use of Dalli in Rails is to support a cache store. To set up your cache store with a cluster, you'll need to generate the list of servers with Dalli ElastiCache and pass them to the `cache_store` configuration. This needs to be done in your `config/environments/RAILS_ENV.rb` file for each Rails environment where you want to use a cluster.
20
24
 
21
25
  ```ruby
22
26
  # in config/environments/production.rb
23
27
  endpoint = "my-cluster-name.abc123.cfg.use1.cache.amazonaws.com:11211"
24
28
  elasticache = Dalli::ElastiCache.new(endpoint)
25
29
 
26
- config.cache_store = :dalli_store, elasticache.servers, {:expires_in => 1.day, :compress => true}
30
+ config.cache_store = :mem_cache_store, elasticache.servers, { expires_in: 1.day }
27
31
  ```
32
+ ### Configuring a Session Store
33
+
34
+ Another use of Dalli in Rails is to support a Rails session store. Dalli ElastiCache can also be used in this case. The usage is very similar - first use Dalli ElastiCache to generate the list of servers, and then pass that result to the Rails configuration. In `config/application.rb` you would write:
28
35
 
29
- Note that the ElastiCache server list will be refreshed each time an app server process starts.
36
+ ```ruby
37
+ # in config/environments/production.rb
38
+ endpoint = "my-cluster-name.abc123.cfg.use1.cache.amazonaws.com:11211"
39
+ elasticache = Dalli::ElastiCache.new(endpoint)
40
+
41
+ config.session_store = :mem_cache_store, memcache_server: elasticache.servers, pool_size: 10, pool_timeout: 5, expire_after: 1.day
42
+ ```
30
43
 
31
- Client Usage
44
+ ### Dalli Considerations
45
+
46
+ Please see [here](https://github.com/petergoldstein/dalli/wiki/Using-Dalli-with-Rails) for more information on configuring Dalli and Rails.
47
+
48
+
49
+ Using Dalli ElastiCache with a Dalli Client
32
50
  ------------
33
51
 
34
- Create an ElastiCache instance:
52
+ To initialize a Dalli Client for all the nodes of a cluster, one simply needs to pass the configuration endpoint and any options for the Dalli Client into the `Dalli::ElastiCache` initializer. Then one can use the methods on the `Dalli::ElastiCache` object to generate an appropriately configured `Dalli::Client`or to get information about the cluster.
35
53
 
36
54
  ```ruby
37
55
  config_endpoint = "aaron-scratch.vfdnac.cfg.use1.cache.amazonaws.com:11211"
38
56
 
39
57
  # Options for configuring the Dalli::Client
40
58
  dalli_options = {
41
- :expires_in => 24 * 60 * 60,
42
- :namespace => "my_app",
43
- :compress => true
59
+ expires_in: 24 * 60 * 60,
60
+ namespace: "my_app"
44
61
  }
45
62
 
46
63
  elasticache = Dalli::ElastiCache.new(config_endpoint, dalli_options)
@@ -72,9 +89,58 @@ elasticache.refresh
72
89
  elasticache.refresh.client
73
90
  ```
74
91
 
92
+ ### TLS
93
+
94
+ Pass an `OpenSSL::SSL::SSLContext` via `ssl_context:` to enable TLS for the auto-discovery connection. This uses the same interface as Dalli's own TLS support.
95
+
96
+ ```ruby
97
+ ssl_context = OpenSSL::SSL::SSLContext.new
98
+ ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
99
+
100
+ elasticache = Dalli::ElastiCache.new(
101
+ "my-cluster.abc123.cfg.use1.cache.amazonaws.com:11211",
102
+ { expires_in: 1.day },
103
+ ssl_context: ssl_context
104
+ )
105
+ ```
106
+
107
+ Note that `ssl_context:` controls TLS for the auto-discovery endpoint only. To also encrypt traffic to the cache nodes themselves, pass `ssl_context:` in the Dalli options as well:
108
+
109
+ ```ruby
110
+ elasticache = Dalli::ElastiCache.new(endpoint, { ssl_context: ssl_context }, ssl_context: ssl_context)
111
+ ```
112
+
113
+ ### Refreshing the Node List
114
+
115
+ The node list is fetched once and cached. Call `#refresh` to re-query the endpoint, which creates a new `Dalli::Client` with the current node list.
116
+
117
+ Two common patterns for keeping the node list up to date:
118
+
119
+ **On failure** — rescue `Dalli::RingError` (raised when no nodes are reachable) and refresh before retrying:
120
+
121
+ ```ruby
122
+ begin
123
+ cache.get("key")
124
+ rescue Dalli::RingError
125
+ elasticache.refresh
126
+ retry
127
+ end
128
+ ```
129
+
130
+ **On a schedule** — refresh periodically in a background thread or job. AWS does not publish exact timing for node replacement, but the process typically takes a few minutes, so refreshing every 60 seconds is a reasonable default:
131
+
132
+ ```ruby
133
+ Thread.new do
134
+ loop do
135
+ sleep 60
136
+ elasticache.refresh
137
+ end
138
+ end
139
+ ```
140
+
141
+ A combination of both approaches is reasonable for production use.
142
+
75
143
  License
76
144
  -------
77
145
 
78
- Copyright 2013 Aaron Suggs
79
-
80
- Released under an [MIT License](http://opensource.org/licenses/MIT)
146
+ Copyright (2017-2022) Aaron Suggs, Peter M. Goldstein. See LICENSE for details.
data/Rakefile CHANGED
@@ -1,8 +1,10 @@
1
- require "rubygems"
2
- require "bundler/setup"
3
- require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+ require 'bundler/gem_tasks'
6
+ require 'rspec/core/rake_task'
5
7
 
6
8
  RSpec::Core::RakeTask.new(:test)
7
9
 
8
- task :default => :test
10
+ task default: :test
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openssl'
4
+
5
+ module Dalli
6
+ module Elasticache
7
+ module AutoDiscovery
8
+ ##
9
+ # Base command class for configuration endpoint
10
+ # command. Contains the network logic.
11
+ ##
12
+ class BaseCommand
13
+ attr_reader :host, :port, :timeout, :ssl_context
14
+
15
+ def initialize(host, port, timeout = nil, ssl_context: nil)
16
+ @host = host
17
+ @port = port
18
+ @timeout = timeout
19
+ @ssl_context = ssl_context
20
+ end
21
+
22
+ # Send an ASCII command to the endpoint
23
+ #
24
+ # Returns the raw response as a String
25
+ def send_command
26
+ tcp_socket = ::Socket.tcp(@host, @port, connect_timeout: timeout)
27
+ begin
28
+ socket = ssl_context ? wrap_with_ssl(tcp_socket) : tcp_socket
29
+ socket.puts command
30
+ response_from_socket(socket)
31
+ ensure
32
+ (socket || tcp_socket).close
33
+ end
34
+ end
35
+
36
+ def response_from_socket(socket)
37
+ data = +''
38
+ loop do
39
+ wait_for_data(socket)
40
+ line = socket.readline
41
+ break if line.include?('END')
42
+
43
+ data << line
44
+ end
45
+
46
+ data
47
+ end
48
+
49
+ private
50
+
51
+ def wrap_with_ssl(tcp_socket)
52
+ ssl_socket = OpenSSL::SSL::SSLSocket.new(tcp_socket, ssl_context)
53
+ ssl_socket.hostname = @host
54
+ ssl_socket.sync_close = true
55
+ ssl_socket.connect
56
+ ssl_socket
57
+ end
58
+
59
+ def wait_for_data(socket)
60
+ return unless timeout
61
+
62
+ raise Timeout::Error, "Auto discovery read timed out after #{timeout}s" unless socket.wait_readable(timeout)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dalli
4
+ module Elasticache
5
+ module AutoDiscovery
6
+ ##
7
+ # Encapsulates execution of the 'config' command, which is used to
8
+ # extract the list of nodes and determine if that list of nodes has changed.
9
+ ##
10
+ class ConfigCommand < BaseCommand
11
+ CONFIG_COMMAND = "config get cluster\r\n"
12
+
13
+ def response
14
+ ConfigResponse.new(send_command)
15
+ end
16
+
17
+ def command
18
+ CONFIG_COMMAND
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,48 +1,45 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dalli
2
4
  module Elasticache
3
5
  module AutoDiscovery
4
-
5
6
  # This class wraps the raw ASCII response from an Auto Discovery endpoint
6
7
  # and provides methods for extracting data from that response.
7
8
  #
8
9
  # http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/AutoDiscovery.AddingToYourClientLibrary.html
9
-
10
10
  class ConfigResponse
11
-
12
11
  # The raw response text
13
12
  attr_reader :text
14
-
13
+
15
14
  # Matches the version line of the response
16
- VERSION_REGEX = /^(\d+)$/
17
-
15
+ VERSION_REGEX = /^(\d+)\r?\n/
16
+
18
17
  # Matches strings like "my-cluster.001.cache.aws.com|10.154.182.29|11211"
19
18
  NODE_REGEX = /(([-.a-zA-Z0-9]+)\|(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b)\|(\d+))/
20
19
  NODE_LIST_REGEX = /^(#{NODE_REGEX}\s*)+$/
21
-
20
+
22
21
  def initialize(response_text)
23
22
  @text = response_text.to_s
24
23
  end
25
-
24
+
26
25
  # The number of times the configuration has been changed
27
26
  #
28
27
  # Returns an integer
29
28
  def version
30
- VERSION_REGEX.match(@text)[1].to_i
29
+ m = VERSION_REGEX.match(@text)
30
+ return -1 unless m
31
+
32
+ m[1].to_i
31
33
  end
32
-
34
+
33
35
  # Node hosts, ip addresses, and ports
34
36
  #
35
37
  # Returns an Array of Hashes with values for :host, :ip and :port
36
38
  def nodes
37
39
  NODE_LIST_REGEX.match(@text).to_s.scan(NODE_REGEX).map do |match|
38
- {
39
- :host => match[1],
40
- :ip => match[2],
41
- :port => match[3].to_i
42
- }
40
+ Node.new(match[1], match[2], match[3].to_i)
43
41
  end
44
42
  end
45
-
46
43
  end
47
44
  end
48
45
  end
@@ -1,76 +1,47 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dalli
2
4
  module Elasticache
3
5
  module AutoDiscovery
6
+ ##
7
+ # This is a representation of the configuration endpoint for
8
+ # a memcached cluster. It encapsulates information returned from
9
+ # that endpoint.
10
+ ##
4
11
  class Endpoint
5
-
6
12
  # Endpoint configuration
7
- attr_reader :host
8
- attr_reader :port
9
-
10
- # Matches Strings like "my-host.cache.aws.com:11211"
11
- ENDPOINT_REGEX = /([-.a-zA-Z0-9]+):(\d+)/
12
-
13
- STATS_COMMAND = "stats\r\n"
14
- CONFIG_COMMAND = "config get cluster\r\n"
15
- # Legacy command for version < 1.4.14
16
- OLD_CONFIG_COMMAND = "get AmazonElastiCache:cluster\r\n"
17
-
18
- def initialize(endpoint)
19
- ENDPOINT_REGEX.match(endpoint) do |m|
20
- @host = m[1]
21
- @port = m[2].to_i
22
- end
23
- end
24
-
13
+ attr_reader :host, :port
14
+
15
+ # Matches DNS/IPv4 like "my-host.cache.aws.com:11211" or bracketed IPv6 like "[::1]:11211"
16
+ ENDPOINT_REGEX = /^([-_.a-zA-Z0-9]+|\[[a-fA-F0-9:]+\])(?::(\d+))?$/
17
+
18
+ def initialize(addr, timeout: nil, ssl_context: nil)
19
+ @host, @port = parse_endpoint_address(addr)
20
+ @timeout = timeout
21
+ @ssl_context = ssl_context
22
+ end
23
+
24
+ DEFAULT_PORT = 11_211
25
+ def parse_endpoint_address(addr)
26
+ m = ENDPOINT_REGEX.match(addr)
27
+ raise ArgumentError, "Unable to parse configuration endpoint address - #{addr}" unless m
28
+
29
+ [m[1], (m[2] || DEFAULT_PORT).to_i]
30
+ end
31
+
25
32
  # A cached ElastiCache::StatsResponse
26
33
  def stats
27
- @stats ||= get_stats_from_remote
34
+ @stats ||= StatsCommand.new(@host, @port, @timeout, ssl_context: @ssl_context).response
28
35
  end
29
-
36
+
30
37
  # A cached ElastiCache::ConfigResponse
31
38
  def config
32
- @config ||= get_config_from_remote
39
+ @config ||= ConfigCommand.new(@host, @port, @timeout, ssl_context: @ssl_context).response
33
40
  end
34
-
41
+
35
42
  # The memcached engine version
36
43
  def engine_version
37
- stats.version
38
- end
39
-
40
- protected
41
-
42
- def with_socket(&block)
43
- TCPSocket.new(config_host, config_port)
44
- end
45
-
46
- def get_stats_from_remote
47
- data = remote_command(STATS_COMMAND)
48
- StatsResponse.new(data)
49
- end
50
-
51
- def get_config_from_remote
52
- if engine_version < Gem::Version.new("1.4.14")
53
- data = remote_command(OLD_CONFIG_COMMAND)
54
- else
55
- data = remote_command(CONFIG_COMMAND)
56
- end
57
- ConfigResponse.new(data)
58
- end
59
-
60
- # Send an ASCII command to the endpoint
61
- #
62
- # Returns the raw response as a String
63
- def remote_command(command)
64
- socket = TCPSocket.new(@host, @port)
65
- socket.puts command
66
-
67
- data = ""
68
- until (line = socket.readline) =~ /END/
69
- data << line
70
- end
71
-
72
- socket.close
73
- data
44
+ stats.engine_version
74
45
  end
75
46
  end
76
47
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dalli
4
+ module Elasticache
5
+ module AutoDiscovery
6
+ ##
7
+ # Represents a single memcached node in the
8
+ # cluster.
9
+ ##
10
+ class Node
11
+ attr_reader :host, :ip, :port
12
+
13
+ def initialize(host, ip, port)
14
+ @host = host
15
+ @ip = ip
16
+ @port = port
17
+ end
18
+
19
+ def ==(other)
20
+ host == other.host &&
21
+ ip == other.ip &&
22
+ port == other.port
23
+ end
24
+
25
+ def eql?(other)
26
+ self == other
27
+ end
28
+
29
+ def hash
30
+ [host, ip, port].hash
31
+ end
32
+
33
+ def to_s
34
+ "#{@host}:#{@port}"
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dalli
4
+ module Elasticache
5
+ module AutoDiscovery
6
+ ##
7
+ # Encapsulates execution of the 'stats' command, which is used to
8
+ # extract the engine_version
9
+ ##
10
+ class StatsCommand < BaseCommand
11
+ STATS_COMMAND = "stats\r\n"
12
+
13
+ def response
14
+ StatsResponse.new(send_command)
15
+ end
16
+
17
+ def command
18
+ STATS_COMMAND
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,29 +1,32 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dalli
2
4
  module Elasticache
3
5
  module AutoDiscovery
4
-
5
- # This class wraps the raw ASCII response from an Auto Discovery endpoint
6
- # and provides methods for extracting data from that response.
6
+ # This class wraps the raw ASCII response from a stats call to an
7
+ # Auto Discovery endpoint and provides methods for extracting data
8
+ # from that response.
7
9
  #
8
10
  # http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/AutoDiscovery.AddingToYourClientLibrary.html
9
-
10
11
  class StatsResponse
11
-
12
12
  # The raw response text
13
13
  attr_reader :text
14
-
14
+
15
15
  # Matches the version line of the response
16
- VERSION_REGEX = /^STAT version ([0-9.]+)\s*$/
17
-
16
+ VERSION_REGEX = /^STAT version ([0-9.]+|unknown)\s*/i
17
+
18
18
  def initialize(response_text)
19
19
  @text = response_text.to_s
20
20
  end
21
-
21
+
22
22
  # Extract the engine version stat
23
23
  #
24
- # Returns a Gem::Version
25
- def version
26
- Gem::Version.new(VERSION_REGEX.match(@text)[1])
24
+ # Returns a string
25
+ def engine_version
26
+ m = VERSION_REGEX.match(@text)
27
+ return '' unless m && m[1]
28
+
29
+ m[1]
27
30
  end
28
31
  end
29
32
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dalli
2
4
  class ElastiCache
3
- VERSION = "0.2.0"
5
+ VERSION = '2.0.1'
4
6
  end
5
7
  end
@@ -1,47 +1,80 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'dalli'
2
4
  require 'socket'
3
- require 'dalli/elasticache/version'
4
- require 'dalli/elasticache/auto_discovery/endpoint'
5
- require 'dalli/elasticache/auto_discovery/config_response'
6
- require 'dalli/elasticache/auto_discovery/stats_response'
5
+ require 'timeout'
6
+ require_relative 'elasticache/version'
7
+ require_relative 'elasticache/auto_discovery/endpoint'
8
+ require_relative 'elasticache/auto_discovery/base_command'
9
+ require_relative 'elasticache/auto_discovery/node'
10
+ require_relative 'elasticache/auto_discovery/config_response'
11
+ require_relative 'elasticache/auto_discovery/config_command'
12
+ require_relative 'elasticache/auto_discovery/stats_response'
13
+ require_relative 'elasticache/auto_discovery/stats_command'
7
14
 
8
15
  module Dalli
16
+ ##
17
+ # Dalli::Elasticache provides an interface for providing a configuration
18
+ # endpoint for a memcached cluster on ElasticCache and retrieving the
19
+ # list of addresses (hostname and port) for the individual nodes of that cluster.
20
+ #
21
+ # This allows the caller to pass that server list to Dalli, which then
22
+ # distributes cached items consistently over the nodes.
23
+ ##
9
24
  class ElastiCache
25
+ DEFAULT_TIMEOUT = 5
26
+
10
27
  attr_reader :endpoint, :options
11
-
12
- def initialize(config_endpoint, options={})
13
- @endpoint = Dalli::Elasticache::AutoDiscovery::Endpoint.new(config_endpoint)
14
- @options = options
28
+
29
+ ##
30
+ # Creates a new Dalli::ElasticCache instance.
31
+ #
32
+ # config_endpoint - a String containing the host and (optionally) port of the
33
+ # configuration endpoint for the cluster. If not specified the port will
34
+ # default to 11211. The host must be either a DNS name, an IPv4 address, or
35
+ # a bracketed IPv6 address.
36
+ # dalli_options - a set of options passed to the Dalli::Client that is returned
37
+ # by the client method. Otherwise unused.
38
+ # timeout: - connect and read timeout in seconds for auto-discovery TCP calls.
39
+ # Defaults to 5 seconds.
40
+ ##
41
+ def initialize(config_endpoint, dalli_options = {}, timeout: DEFAULT_TIMEOUT, ssl_context: nil)
42
+ @timeout = timeout
43
+ @ssl_context = ssl_context
44
+ @endpoint = Dalli::Elasticache::AutoDiscovery::Endpoint.new(config_endpoint, timeout:, ssl_context:)
45
+ @options = dalli_options
15
46
  end
16
-
47
+
17
48
  # Dalli::Client configured to connect to the cluster's nodes
18
49
  def client
19
50
  Dalli::Client.new(servers, options)
20
51
  end
21
-
52
+
22
53
  # The number of times the cluster configuration has been changed
23
54
  #
24
55
  # Returns an integer
25
56
  def version
26
57
  endpoint.config.version
27
58
  end
28
-
59
+
29
60
  # The cache engine version of the cluster
61
+ #
62
+ # Returns a string
30
63
  def engine_version
31
64
  endpoint.engine_version
32
65
  end
33
-
66
+
34
67
  # List of cluster server nodes with ip addresses and ports
35
68
  # Always use host name instead of private elasticache IPs as internal IPs can change after a node is rebooted
36
69
  def servers
37
- endpoint.config.nodes.map{ |h| "#{h[:host]}:#{h[:port]}" }
70
+ endpoint.config.nodes.map(&:to_s)
38
71
  end
39
-
72
+
40
73
  # Clear all cached data from the cluster endpoint
41
74
  def refresh
42
75
  config_endpoint = "#{endpoint.host}:#{endpoint.port}"
43
- @endpoint = Dalli::Elasticache::AutoDiscovery::Endpoint.new(config_endpoint)
44
-
76
+ @endpoint = Dalli::Elasticache::AutoDiscovery::Endpoint.new(config_endpoint, timeout: @timeout,
77
+ ssl_context: @ssl_context)
45
78
  self
46
79
  end
47
80
  end
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Support default bundler require path
2
- require 'dalli/elasticache'
4
+ require_relative 'dalli/elasticache'
metadata CHANGED
@@ -1,58 +1,30 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dalli-elasticache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Suggs
8
8
  - Zach Millman
9
- autorequire:
9
+ - Peter M. Goldstein
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-02-24 00:00:00.000000000 Z
12
+ date: 1980-01-02 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: rake
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - ">="
19
- - !ruby/object:Gem::Version
20
- version: '0'
21
- type: :development
22
- prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- version: '0'
28
- - !ruby/object:Gem::Dependency
29
- name: rspec
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - ">="
33
- - !ruby/object:Gem::Version
34
- version: '0'
35
- type: :development
36
- prerelease: false
37
- version_requirements: !ruby/object:Gem::Requirement
38
- requirements:
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- version: '0'
42
14
  - !ruby/object:Gem::Dependency
43
15
  name: dalli
44
16
  requirement: !ruby/object:Gem::Requirement
45
17
  requirements:
46
18
  - - ">="
47
19
  - !ruby/object:Gem::Version
48
- version: 1.0.0
20
+ version: 5.0.0
49
21
  type: :runtime
50
22
  prerelease: false
51
23
  version_requirements: !ruby/object:Gem::Requirement
52
24
  requirements:
53
25
  - - ">="
54
26
  - !ruby/object:Gem::Version
55
- version: 1.0.0
27
+ version: 5.0.0
56
28
  description: |2
57
29
  This gem provides an interface for fetching cluster information from an AWS
58
30
  ElastiCache AutoDiscovery server and configuring a Dalli client to connect
@@ -60,6 +32,7 @@ description: |2
60
32
  email:
61
33
  - aaron@ktheory.com
62
34
  - zach@magoosh.com
35
+ - peter.m.goldstein@gmail.com
63
36
  executables: []
64
37
  extensions: []
65
38
  extra_rdoc_files: []
@@ -68,20 +41,19 @@ files:
68
41
  - Rakefile
69
42
  - lib/dalli-elasticache.rb
70
43
  - lib/dalli/elasticache.rb
44
+ - lib/dalli/elasticache/auto_discovery/base_command.rb
45
+ - lib/dalli/elasticache/auto_discovery/config_command.rb
71
46
  - lib/dalli/elasticache/auto_discovery/config_response.rb
72
47
  - lib/dalli/elasticache/auto_discovery/endpoint.rb
48
+ - lib/dalli/elasticache/auto_discovery/node.rb
49
+ - lib/dalli/elasticache/auto_discovery/stats_command.rb
73
50
  - lib/dalli/elasticache/auto_discovery/stats_response.rb
74
51
  - lib/dalli/elasticache/version.rb
75
- - spec/config_response_spec.rb
76
- - spec/elasticache_spec.rb
77
- - spec/endpoint_spec.rb
78
- - spec/spec_helper.rb
79
- - spec/stats_response_spec.rb
80
52
  homepage: http://github.com/ktheory/dalli-elasticache
81
53
  licenses:
82
54
  - MIT
83
- metadata: {}
84
- post_install_message:
55
+ metadata:
56
+ rubygems_mfa_required: 'true'
85
57
  rdoc_options:
86
58
  - "--charset=UTF-8"
87
59
  require_paths:
@@ -90,21 +62,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
90
62
  requirements:
91
63
  - - ">="
92
64
  - !ruby/object:Gem::Version
93
- version: 1.9.2
65
+ version: 3.3.0
94
66
  required_rubygems_version: !ruby/object:Gem::Requirement
95
67
  requirements:
96
68
  - - ">="
97
69
  - !ruby/object:Gem::Version
98
70
  version: 1.3.5
99
71
  requirements: []
100
- rubyforge_project:
101
- rubygems_version: 2.5.2
102
- signing_key:
72
+ rubygems_version: 4.0.14
103
73
  specification_version: 4
104
74
  summary: Configure Dalli clients with ElastiCache's AutoDiscovery
105
- test_files:
106
- - spec/config_response_spec.rb
107
- - spec/elasticache_spec.rb
108
- - spec/endpoint_spec.rb
109
- - spec/spec_helper.rb
110
- - spec/stats_response_spec.rb
75
+ test_files: []
@@ -1,32 +0,0 @@
1
- require_relative 'spec_helper'
2
-
3
- describe 'Dalli::Elasticache::AutoDiscovery::ConfigResponse' do
4
- let :response do
5
- text = "CONFIG cluster 0 141\r\n12\nmycluster.0001.cache.amazonaws.com|10.112.21.1|11211 mycluster.0002.cache.amazonaws.com|10.112.21.2|11211 mycluster.0003.cache.amazonaws.com|10.112.21.3|11211\n\r\n"
6
- Dalli::Elasticache::AutoDiscovery::ConfigResponse.new(text)
7
- end
8
-
9
- describe '#version' do
10
- it 'parses version' do
11
- response.version.should == 12
12
- end
13
- end
14
-
15
- describe '#nodes' do
16
- it 'parses hosts' do
17
- response.nodes.map{|s| s[:host]}.should == [
18
- "mycluster.0001.cache.amazonaws.com",
19
- "mycluster.0002.cache.amazonaws.com",
20
- "mycluster.0003.cache.amazonaws.com"
21
- ]
22
- end
23
-
24
- it 'parses ip addresses' do
25
- response.nodes.map{|s| s[:ip]}.should == ["10.112.21.1", "10.112.21.2", "10.112.21.3"]
26
- end
27
-
28
- it 'parses ports' do
29
- response.nodes.map{|s| s[:port]}.should == [11211, 11211, 11211]
30
- end
31
- end
32
- end
@@ -1,62 +0,0 @@
1
- require_relative 'spec_helper'
2
-
3
- describe 'Dalli::ElastiCache::Endpoint' do
4
- let(:cache) do
5
- options = {
6
- :expires_in => 24*60*60,
7
- :namespace => "my_app",
8
- :compress => true
9
- }
10
- Dalli::ElastiCache.new("my-cluster.cfg.use1.cache.amazonaws.com:11211", options)
11
- end
12
-
13
- let(:config_text) { "CONFIG cluster 0 141\r\n12\nmycluster.0001.cache.amazonaws.com|10.112.21.1|11211 mycluster.0002.cache.amazonaws.com|10.112.21.2|11211 mycluster.0003.cache.amazonaws.com|10.112.21.3|11211\n\r\n" }
14
- let(:response) { Dalli::Elasticache::AutoDiscovery::ConfigResponse.new(config_text) }
15
-
16
- describe '.new' do
17
- it 'builds endpoint' do
18
- cache.endpoint.host.should == "my-cluster.cfg.use1.cache.amazonaws.com"
19
- cache.endpoint.port.should == 11211
20
- end
21
-
22
- it 'stores Dalli options' do
23
- cache.options[:expires_in].should == 24*60*60
24
- cache.options[:namespace].should == "my_app"
25
- cache.options[:compress].should == true
26
- end
27
- end
28
-
29
- describe '#client' do
30
- it 'builds with node list'
31
- it 'builds with options'
32
- end
33
-
34
- describe '#servers' do
35
- before { Dalli::Elasticache::AutoDiscovery::Endpoint.any_instance.should_receive(:get_config_from_remote).and_return(response) }
36
-
37
- it 'lists addresses and ports' do
38
- cache.servers.should == ["mycluster.0001.cache.amazonaws.com:11211", "mycluster.0002.cache.amazonaws.com:11211", "mycluster.0003.cache.amazonaws.com:11211"]
39
- end
40
- end
41
-
42
- describe '#version' do
43
- end
44
-
45
- describe '#engine_version' do
46
- end
47
-
48
- describe '#refresh' do
49
- it 'clears endpoint configuration' do
50
- stale_endpoint = cache.endpoint
51
- cache.refresh.endpoint.should_not === stale_endpoint
52
- end
53
-
54
- it 'builds endpoint with same configuration' do
55
- stale_endpoint = cache.endpoint
56
- cache.refresh
57
- cache.endpoint.host.should == stale_endpoint.host
58
- cache.endpoint.port.should == stale_endpoint.port
59
- end
60
- end
61
-
62
- end
@@ -1,16 +0,0 @@
1
- require_relative 'spec_helper'
2
-
3
- describe 'Dalli::Elasticache::AutoDiscovery::Endpoint' do
4
- let(:endpoint) do
5
- Dalli::Elasticache::AutoDiscovery::Endpoint.new("my-cluster.cfg.use1.cache.amazonaws.com:11211")
6
- end
7
-
8
- describe '.new' do
9
- it 'parses host' do
10
- endpoint.host.should == "my-cluster.cfg.use1.cache.amazonaws.com"
11
- end
12
- it 'parses port' do
13
- endpoint.port.should == 11211
14
- end
15
- end
16
- end
data/spec/spec_helper.rb DELETED
@@ -1,12 +0,0 @@
1
- require "bundler/setup"
2
-
3
- require "dalli/elasticache"
4
-
5
- RSpec.configure do |config|
6
- config.expect_with :rspec do |c|
7
- c.syntax = :should
8
- end
9
- config.mock_with :rspec do |c|
10
- c.syntax = :should
11
- end
12
- end
@@ -1,14 +0,0 @@
1
- require_relative 'spec_helper'
2
-
3
- describe 'Dalli::Elasticache::AutoDiscovery::StatsResponse' do
4
- let :response do
5
- text = "STAT pid 1\r\nSTAT uptime 68717\r\nSTAT time 1398885375\r\nSTAT version 1.4.14\r\nSTAT libevent 1.4.13-stable\r\nSTAT pointer_size 64\r\nSTAT rusage_user 0.136008\r\nSTAT rusage_system 0.424026\r\nSTAT curr_connections 5\r\nSTAT total_connections 1159\r\nSTAT connection_structures 6\r\nSTAT reserved_fds 5\r\nSTAT cmd_get 0\r\nSTAT cmd_set 0\r\nSTAT cmd_flush 0\r\nSTAT cmd_touch 0\r\nSTAT cmd_config_get 4582\r\nSTAT cmd_config_set 2\r\nSTAT get_hits 0\r\nSTAT get_misses 0\r\nSTAT delete_misses 0\r\nSTAT delete_hits 0\r\nSTAT incr_misses 0\r\nSTAT incr_hits 0\r\nSTAT decr_misses 0\r\nSTAT decr_hits 0\r\nSTAT cas_misses 0\r\nSTAT cas_hits 0\r\nSTAT cas_badval 0\r\nSTAT touch_hits 0\r\nSTAT touch_misses 0\r\nSTAT auth_cmds 0\r\nSTAT auth_errors 0\r\nSTAT bytes_read 189356\r\nSTAT bytes_written 2906615\r\nSTAT limit_maxbytes 209715200\r\nSTAT accepting_conns 1\r\nSTAT listen_disabled_num 0\r\nSTAT threads 1\r\nSTAT conn_yields 0\r\nSTAT curr_config 1\r\nSTAT hash_power_level 16\r\nSTAT hash_bytes 524288\r\nSTAT hash_is_expanding 0\r\nSTAT expired_unfetched 0\r\nSTAT evicted_unfetched 0\r\nSTAT bytes 0\r\nSTAT curr_items 0\r\nSTAT total_items 0\r\nSTAT evictions 0\r\nSTAT reclaimed 0\r\n"
6
- Dalli::Elasticache::AutoDiscovery::StatsResponse.new(text)
7
- end
8
-
9
- describe '#version' do
10
- it 'parses version' do
11
- response.version.should == Gem::Version.new("1.4.14")
12
- end
13
- end
14
- end