dalli-elasticache 2.0.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
2
  SHA256:
3
- metadata.gz: 66afce9165ca020c9c46d25f12901919968d33ec9de15be287a9f589497a042e
4
- data.tar.gz: e67a94f65b45ecaf034ba6bfd67c574c3275100d43b8f893d52181606dfdeb1e
3
+ metadata.gz: 1da71566964e9f17cacf29d2c670d15d7adb80e4b4cc86f8371ea98eb2b80928
4
+ data.tar.gz: 7b58a9dc5efb77773c0da4de9b1891bbdc5c98d8d4012e13fd432a7906ea6e16
5
5
  SHA512:
6
- metadata.gz: 92399afd4065a1bdb8f387eb6e04d47152c3e4e2e25fe8449713258409d84986014c2c71ad67a0aa90d8a2bd8a3df9721aca6862ac456c908d1fee4901b4465f
7
- data.tar.gz: 379dce4897d563f6811133aaef02c724da76a0bc6f31973b324241d913c5dae2bb53aa15f0536518de6f7e42d1526ff3f3efbfc83f13fc7d3610cff5277d44b0
6
+ metadata.gz: 04cf01bc3a0ff7c14c3173b05be796038bbe3ad45292bffdacb95834900bd8c40ecd224c206f676f3bdfde2e256beb3812d73b156723235daeabace027de704d
7
+ data.tar.gz: 13668d4ead1f6e6fd5e2288d5124a1cb47751d7f97dd4a2f50f288c3db123a7c2228d88b4264ea499091e9ebe0fd1db4167b71cd0b8ba8224793847f6dc4f94a
data/README.md CHANGED
@@ -89,6 +89,57 @@ elasticache.refresh
89
89
  elasticache.refresh.client
90
90
  ```
91
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
+
92
143
  License
93
144
  -------
94
145
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'openssl'
4
+
3
5
  module Dalli
4
6
  module Elasticache
5
7
  module AutoDiscovery
@@ -8,24 +10,26 @@ module Dalli
8
10
  # command. Contains the network logic.
9
11
  ##
10
12
  class BaseCommand
11
- attr_reader :host, :port, :timeout
13
+ attr_reader :host, :port, :timeout, :ssl_context
12
14
 
13
- def initialize(host, port, timeout = nil)
15
+ def initialize(host, port, timeout = nil, ssl_context: nil)
14
16
  @host = host
15
17
  @port = port
16
18
  @timeout = timeout
19
+ @ssl_context = ssl_context
17
20
  end
18
21
 
19
22
  # Send an ASCII command to the endpoint
20
23
  #
21
24
  # Returns the raw response as a String
22
25
  def send_command
23
- socket = ::Socket.tcp(@host, @port, connect_timeout: timeout)
26
+ tcp_socket = ::Socket.tcp(@host, @port, connect_timeout: timeout)
24
27
  begin
28
+ socket = ssl_context ? wrap_with_ssl(tcp_socket) : tcp_socket
25
29
  socket.puts command
26
30
  response_from_socket(socket)
27
31
  ensure
28
- socket.close
32
+ (socket || tcp_socket).close
29
33
  end
30
34
  end
31
35
 
@@ -44,6 +48,14 @@ module Dalli
44
48
 
45
49
  private
46
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
+
47
59
  def wait_for_data(socket)
48
60
  return unless timeout
49
61
 
@@ -15,9 +15,10 @@ module Dalli
15
15
  # Matches DNS/IPv4 like "my-host.cache.aws.com:11211" or bracketed IPv6 like "[::1]:11211"
16
16
  ENDPOINT_REGEX = /^([-_.a-zA-Z0-9]+|\[[a-fA-F0-9:]+\])(?::(\d+))?$/
17
17
 
18
- def initialize(addr, timeout: nil)
18
+ def initialize(addr, timeout: nil, ssl_context: nil)
19
19
  @host, @port = parse_endpoint_address(addr)
20
20
  @timeout = timeout
21
+ @ssl_context = ssl_context
21
22
  end
22
23
 
23
24
  DEFAULT_PORT = 11_211
@@ -30,12 +31,12 @@ module Dalli
30
31
 
31
32
  # A cached ElastiCache::StatsResponse
32
33
  def stats
33
- @stats ||= StatsCommand.new(@host, @port, @timeout).response
34
+ @stats ||= StatsCommand.new(@host, @port, @timeout, ssl_context: @ssl_context).response
34
35
  end
35
36
 
36
37
  # A cached ElastiCache::ConfigResponse
37
38
  def config
38
- @config ||= ConfigCommand.new(@host, @port, @timeout).response
39
+ @config ||= ConfigCommand.new(@host, @port, @timeout, ssl_context: @ssl_context).response
39
40
  end
40
41
 
41
42
  # The memcached engine version
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Dalli
4
4
  class ElastiCache
5
- VERSION = '2.0.0'
5
+ VERSION = '2.0.1'
6
6
  end
7
7
  end
@@ -38,9 +38,10 @@ module Dalli
38
38
  # timeout: - connect and read timeout in seconds for auto-discovery TCP calls.
39
39
  # Defaults to 5 seconds.
40
40
  ##
41
- def initialize(config_endpoint, dalli_options = {}, timeout: DEFAULT_TIMEOUT)
41
+ def initialize(config_endpoint, dalli_options = {}, timeout: DEFAULT_TIMEOUT, ssl_context: nil)
42
42
  @timeout = timeout
43
- @endpoint = Dalli::Elasticache::AutoDiscovery::Endpoint.new(config_endpoint, timeout:)
43
+ @ssl_context = ssl_context
44
+ @endpoint = Dalli::Elasticache::AutoDiscovery::Endpoint.new(config_endpoint, timeout:, ssl_context:)
44
45
  @options = dalli_options
45
46
  end
46
47
 
@@ -72,8 +73,8 @@ module Dalli
72
73
  # Clear all cached data from the cluster endpoint
73
74
  def refresh
74
75
  config_endpoint = "#{endpoint.host}:#{endpoint.port}"
75
- @endpoint = Dalli::Elasticache::AutoDiscovery::Endpoint.new(config_endpoint, timeout: @timeout)
76
-
76
+ @endpoint = Dalli::Elasticache::AutoDiscovery::Endpoint.new(config_endpoint, timeout: @timeout,
77
+ ssl_context: @ssl_context)
77
78
  self
78
79
  end
79
80
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dalli-elasticache
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Suggs
@@ -69,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
69
  - !ruby/object:Gem::Version
70
70
  version: 1.3.5
71
71
  requirements: []
72
- rubygems_version: 4.0.6
72
+ rubygems_version: 4.0.14
73
73
  specification_version: 4
74
74
  summary: Configure Dalli clients with ElastiCache's AutoDiscovery
75
75
  test_files: []