dalli-elasticache-with-timeout 0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ee4bcc3e0b25e6151f1250f43fb854558fb73e2b
4
+ data.tar.gz: 07358013afde109fa151bb56d5264bdcac2f8147
5
+ SHA512:
6
+ metadata.gz: 4005310aaa6f86fd121201b26996aeafb273768d71c00e34a4f9472f2b7edab8f6b399605152b7a3acadc02f75010589fc4f1f26a8aead7775b77e892fd5e935
7
+ data.tar.gz: efb8bd9bf2d6ee50ca1a04af09df8269687016ffc07f4d26b001fdacd7ba664d80a6add1720ab1227edc558d295c41b9885969f41a19769865f44191d8457231
data/README.md ADDED
@@ -0,0 +1,80 @@
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)
2
+ =================
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.
5
+
6
+ Installation
7
+ ------------
8
+
9
+ Install the [rubygem](https://rubygems.org/gems/dalli-elasticache):
10
+
11
+ ```ruby
12
+ # in your Gemfile
13
+ gem 'dalli-elasticache'
14
+ ```
15
+
16
+ Setup for Rails 3.x and Newer
17
+ -----------------------------
18
+
19
+ Configure your environment-specific application settings:
20
+
21
+ ```ruby
22
+ # in config/environments/production.rb
23
+ endpoint = "my-cluster-name.abc123.cfg.use1.cache.amazonaws.com:11211"
24
+ elasticache = Dalli::ElastiCache.new(endpoint)
25
+
26
+ config.cache_store = :dalli_store, elasticache.servers, {:expires_in => 1.day, :compress => true}
27
+ ```
28
+
29
+ Note that the ElastiCache server list will be refreshed each time an app server process starts.
30
+
31
+ Client Usage
32
+ ------------
33
+
34
+ Create an ElastiCache instance:
35
+
36
+ ```ruby
37
+ config_endpoint = "aaron-scratch.vfdnac.cfg.use1.cache.amazonaws.com:11211"
38
+
39
+ # Options for configuring the Dalli::Client
40
+ dalli_options = {
41
+ :expires_in => 24 * 60 * 60,
42
+ :namespace => "my_app",
43
+ :compress => true
44
+ }
45
+
46
+ elasticache = Dalli::ElastiCache.new(config_endpoint, dalli_options)
47
+ ```
48
+
49
+ Fetch information about the Memcached nodes:
50
+
51
+ ```ruby
52
+ # Dalli::Client with configuration from the AutoDiscovery endpoint
53
+ elasticache.client
54
+ # => #<Dalli::Client ... @servers=["aaron-scratch.vfdnac.0001.use1.cache.amazonaws.com:11211", ...]>
55
+
56
+ # Node addresses
57
+ elasticache.servers
58
+ # => ["aaron-scratch.vfdnac.0001.use1.cache.amazonaws.com:11211", "aaron-scratch.vfdnac.0002.use1.cache.amazonaws.com:11211"]
59
+
60
+ # Number of times the cluster configuration has changed
61
+ elasticache.version
62
+ # => 12
63
+
64
+ # Memcached version of the cluster
65
+ elasticache.engine_version
66
+ # => "1.4.14"
67
+
68
+ # Refresh data from the endpoint
69
+ elasticache.refresh
70
+
71
+ # Refresh and get client with new configuration
72
+ elasticache.refresh.client
73
+ ```
74
+
75
+ License
76
+ -------
77
+
78
+ Copyright 2013 Aaron Suggs
79
+
80
+ Released under an [MIT License](http://opensource.org/licenses/MIT)
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:test)
7
+
8
+ task :default => :test
@@ -0,0 +1,2 @@
1
+ # Support default bundler require path
2
+ require 'dalli/elasticache'
@@ -0,0 +1,49 @@
1
+ require 'dalli'
2
+ 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'
7
+
8
+ module Dalli
9
+ class ElastiCache
10
+ attr_reader :endpoint, :options
11
+
12
+ def initialize(config_endpoint, options={})
13
+ cluster_timeout = (options || {}).delete(:cluster_timeout) || (options || {}).delete('cluster_timeout')
14
+ @endpoint = Dalli::Elasticache::AutoDiscovery::Endpoint.new(config_endpoint, cluster_timeout)
15
+ @options = options
16
+ end
17
+
18
+ # Dalli::Client configured to connect to the cluster's nodes
19
+ def client
20
+ Dalli::Client.new(servers, options)
21
+ end
22
+
23
+ # The number of times the cluster configuration has been changed
24
+ #
25
+ # Returns an integer
26
+ def version
27
+ endpoint.config.version
28
+ end
29
+
30
+ # The cache engine version of the cluster
31
+ def engine_version
32
+ endpoint.engine_version
33
+ end
34
+
35
+ # List of cluster server nodes with ip addresses and ports
36
+ # Always use host name instead of private elasticache IPs as internal IPs can change after a node is rebooted
37
+ def servers
38
+ endpoint.config.nodes.map{ |h| "#{h[:host]}:#{h[:port]}" }
39
+ end
40
+
41
+ # Clear all cached data from the cluster endpoint
42
+ def refresh
43
+ config_endpoint = "#{endpoint.host}:#{endpoint.port}"
44
+ @endpoint = Dalli::Elasticache::AutoDiscovery::Endpoint.new(config_endpoint, endpoint.timeout)
45
+
46
+ self
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,49 @@
1
+ module Dalli
2
+ module Elasticache
3
+ 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.
7
+ #
8
+ # http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/AutoDiscovery.AddingToYourClientLibrary.html
9
+
10
+ class ConfigResponse
11
+
12
+ # The raw response text
13
+ attr_reader :text
14
+
15
+ # Matches the version line of the response
16
+ VERSION_REGEX = /^(\d+)$/
17
+
18
+ # Matches strings like "my-cluster.001.cache.aws.com|10.154.182.29|11211"
19
+ NODE_REGEX = /(([-.a-zA-Z0-9]+)\|(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b)\|(\d+))/
20
+ NODE_LIST_REGEX = /^(#{NODE_REGEX}\s*)+$/
21
+
22
+ def initialize(response_text)
23
+ @text = response_text.to_s
24
+ end
25
+
26
+ # The number of times the configuration has been changed
27
+ #
28
+ # Returns an integer
29
+ def version
30
+ VERSION_REGEX.match(@text)[1].to_i
31
+ end
32
+
33
+ # Node hosts, ip addresses, and ports
34
+ #
35
+ # Returns an Array of Hashes with values for :host, :ip and :port
36
+ def nodes
37
+ 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
+ }
43
+ end
44
+ end
45
+
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,128 @@
1
+ module Dalli
2
+ module Elasticache
3
+ module AutoDiscovery
4
+ class Endpoint
5
+ class Timeout < StandardError; end;
6
+
7
+ # Endpoint configuration
8
+ attr_reader :host
9
+ attr_reader :port
10
+ attr_reader :timeout
11
+
12
+ # Matches Strings like "my-host.cache.aws.com:11211"
13
+ ENDPOINT_REGEX = /([-.a-zA-Z0-9]+):(\d+)/
14
+
15
+ STATS_COMMAND = "stats\r\n"
16
+ CONFIG_COMMAND = "config get cluster\r\n"
17
+ # Legacy command for version < 1.4.14
18
+ OLD_CONFIG_COMMAND = "get AmazonElastiCache:cluster\r\n"
19
+
20
+ def initialize(endpoint, timeout)
21
+ ENDPOINT_REGEX.match(endpoint) do |m|
22
+ @host = m[1]
23
+ @port = m[2].to_i
24
+ end
25
+ @timeout = timeout
26
+ end
27
+
28
+ # A cached ElastiCache::StatsResponse
29
+ def stats
30
+ @stats ||= get_stats_from_remote
31
+ end
32
+
33
+ # A cached ElastiCache::ConfigResponse
34
+ def config
35
+ @config ||= get_config_from_remote
36
+ end
37
+
38
+ # The memcached engine version
39
+ def engine_version
40
+ stats.version
41
+ end
42
+
43
+ protected
44
+
45
+ def with_socket(&block)
46
+ TCPSocket.new(config_host, config_port)
47
+ end
48
+
49
+ def get_stats_from_remote
50
+ data = remote_command(STATS_COMMAND)
51
+ StatsResponse.new(data)
52
+ end
53
+
54
+ def get_config_from_remote
55
+ if engine_version < Gem::Version.new("1.4.14")
56
+ data = remote_command(OLD_CONFIG_COMMAND)
57
+ else
58
+ data = remote_command(CONFIG_COMMAND)
59
+ end
60
+ ConfigResponse.new(data)
61
+ end
62
+
63
+ # Send an ASCII command to the endpoint
64
+ #
65
+ # Returns the raw response as a String
66
+ def remote_command(command)
67
+ socket = tcp_socket(@host, @port, @timeout)
68
+ socket.puts command
69
+
70
+ data = ""
71
+ until (line = socket.readline) =~ /END/
72
+ data << line
73
+ end
74
+
75
+ socket.close
76
+ data
77
+ end
78
+
79
+ # Creates and connects a tcp socket with an optional timeout
80
+ #
81
+ # Returns a Socket or TCPSocket instance
82
+ def tcp_socket(host, port, timeout)
83
+ if timeout.nil?
84
+ TCPSocket.new(host, port)
85
+ else
86
+ # Convert the passed host into structures the non-blocking calls
87
+ # can deal with
88
+ addr = Socket.getaddrinfo(host, nil)
89
+ sockaddr = Socket.pack_sockaddr_in(port, addr[0][3])
90
+
91
+ Socket.new(Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0).tap do |socket|
92
+ socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
93
+
94
+ begin
95
+ # Initiate the socket connection in the background. If it doesn't fail
96
+ # immediatelyit will raise an IO::WaitWritable (Errno::EINPROGRESS)
97
+ # indicating the connection is in progress.
98
+ socket.connect_nonblock(sockaddr)
99
+
100
+ rescue IO::WaitWritable
101
+ # IO.select will block until the socket is writable or the timeout
102
+ # is exceeded - whichever comes first.
103
+ if IO.select(nil, [socket], nil, timeout)
104
+ begin
105
+ # Verify there is now a good connection
106
+ socket.connect_nonblock(sockaddr)
107
+ rescue Errno::EISCONN
108
+ return socket
109
+ # Good news everybody, the socket is connected!
110
+ rescue
111
+ # An unexpected exception was raised - the connection is no good.
112
+ socket.close
113
+ raise
114
+ end
115
+ else
116
+ # IO.select returns nil when the socket is not ready before timeout
117
+ # seconds have elapsed
118
+ socket.close
119
+ raise Timeout, "Connection attempt took longer than timeout of #{timeout} seconds"
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,31 @@
1
+ module Dalli
2
+ module Elasticache
3
+ 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.
7
+ #
8
+ # http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/AutoDiscovery.AddingToYourClientLibrary.html
9
+
10
+ class StatsResponse
11
+
12
+ # The raw response text
13
+ attr_reader :text
14
+
15
+ # Matches the version line of the response
16
+ VERSION_REGEX = /^STAT version ([0-9.]+)\s*$/
17
+
18
+ def initialize(response_text)
19
+ @text = response_text.to_s
20
+ end
21
+
22
+ # Extract the engine version stat
23
+ #
24
+ # Returns a Gem::Version
25
+ def version
26
+ Gem::Version.new(VERSION_REGEX.match(@text)[1])
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,5 @@
1
+ module Dalli
2
+ class ElastiCache
3
+ VERSION = "0.2.0"
4
+ end
5
+ end
@@ -0,0 +1,32 @@
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
@@ -0,0 +1,64 @@
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
+ :cluster_timeout => 5
10
+ }
11
+ Dalli::ElastiCache.new("my-cluster.cfg.use1.cache.amazonaws.com:11211", options)
12
+ end
13
+
14
+ 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" }
15
+ let(:response) { Dalli::Elasticache::AutoDiscovery::ConfigResponse.new(config_text) }
16
+
17
+ describe '.new' do
18
+ it 'builds endpoint' do
19
+ cache.endpoint.host.should == "my-cluster.cfg.use1.cache.amazonaws.com"
20
+ cache.endpoint.port.should == 11211
21
+ cache.endpoint.timeout.should == 5
22
+ end
23
+
24
+ it 'stores Dalli options' do
25
+ cache.options[:expires_in].should == 24*60*60
26
+ cache.options[:namespace].should == "my_app"
27
+ cache.options[:compress].should == true
28
+ end
29
+ end
30
+
31
+ describe '#client' do
32
+ it 'builds with node list'
33
+ it 'builds with options'
34
+ end
35
+
36
+ describe '#servers' do
37
+ before { Dalli::Elasticache::AutoDiscovery::Endpoint.any_instance.should_receive(:get_config_from_remote).and_return(response) }
38
+
39
+ it 'lists addresses and ports' do
40
+ cache.servers.should == ["mycluster.0001.cache.amazonaws.com:11211", "mycluster.0002.cache.amazonaws.com:11211", "mycluster.0003.cache.amazonaws.com:11211"]
41
+ end
42
+ end
43
+
44
+ describe '#version' do
45
+ end
46
+
47
+ describe '#engine_version' do
48
+ end
49
+
50
+ describe '#refresh' do
51
+ it 'clears endpoint configuration' do
52
+ stale_endpoint = cache.endpoint
53
+ cache.refresh.endpoint.should_not === stale_endpoint
54
+ end
55
+
56
+ it 'builds endpoint with same configuration' do
57
+ stale_endpoint = cache.endpoint
58
+ cache.refresh
59
+ cache.endpoint.host.should == stale_endpoint.host
60
+ cache.endpoint.port.should == stale_endpoint.port
61
+ end
62
+ end
63
+
64
+ end
@@ -0,0 +1,16 @@
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", nil)
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
@@ -0,0 +1,12 @@
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
@@ -0,0 +1,14 @@
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
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dalli-elasticache-with-timeout
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Aaron Suggs
8
+ - Zach Millman
9
+ - Misha Conway
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2017-02-21 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rake
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: rspec
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: dalli
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 1.0.0
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 1.0.0
57
+ description: |2
58
+ This gem provides an interface for fetching cluster information from an AWS
59
+ ElastiCache AutoDiscovery server and configuring a Dalli client to connect
60
+ to all nodes in the cache cluster.
61
+ email:
62
+ - aaron@ktheory.com
63
+ - zach@magoosh.com
64
+ - mishaAconway@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - README.md
70
+ - Rakefile
71
+ - lib/dalli-elasticache.rb
72
+ - lib/dalli/elasticache.rb
73
+ - lib/dalli/elasticache/auto_discovery/config_response.rb
74
+ - lib/dalli/elasticache/auto_discovery/endpoint.rb
75
+ - lib/dalli/elasticache/auto_discovery/stats_response.rb
76
+ - lib/dalli/elasticache/version.rb
77
+ - spec/config_response_spec.rb
78
+ - spec/elasticache_spec.rb
79
+ - spec/endpoint_spec.rb
80
+ - spec/spec_helper.rb
81
+ - spec/stats_response_spec.rb
82
+ homepage: https://github.com/MishaConway/dalli-elasticache
83
+ licenses:
84
+ - MIT
85
+ metadata: {}
86
+ post_install_message:
87
+ rdoc_options:
88
+ - "--charset=UTF-8"
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: 1.9.2
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: 1.3.5
101
+ requirements: []
102
+ rubyforge_project:
103
+ rubygems_version: 2.6.7
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: Configure Dalli clients with ElastiCache's AutoDiscovery
107
+ test_files:
108
+ - spec/config_response_spec.rb
109
+ - spec/elasticache_spec.rb
110
+ - spec/endpoint_spec.rb
111
+ - spec/spec_helper.rb
112
+ - spec/stats_response_spec.rb