dalli 2.7.11 → 3.0.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of dalli might be problematic. Click here for more details.

data/lib/dalli/socket.rb CHANGED
@@ -1,170 +1,104 @@
1
1
  # frozen_string_literal: true
2
- require 'rbconfig'
3
-
4
- module Dalli::Server::TCPSocketOptions
5
- def setsockopts(sock, options)
6
- sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, true)
7
- sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true) if options[:keepalive]
8
- sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVBUF, options[:rcvbuf]) if options[:rcvbuf]
9
- sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, options[:sndbuf]) if options[:sndbuf]
10
- end
11
- end
12
-
13
- begin
14
- require 'kgio'
15
- puts "Using kgio socket IO" if defined?($TESTING) && $TESTING
16
-
17
- class Dalli::Server::KSocket < Kgio::Socket
18
- attr_accessor :options, :server
19
-
20
- def kgio_wait_readable
21
- IO.select([self], nil, nil, options[:socket_timeout]) || raise(Timeout::Error, "IO timeout")
22
- end
23
-
24
- def kgio_wait_writable
25
- IO.select(nil, [self], nil, options[:socket_timeout]) || raise(Timeout::Error, "IO timeout")
26
- end
27
-
28
- alias :write :kgio_write
29
2
 
30
- def readfull(count)
31
- value = String.new('')
32
- while true
33
- value << kgio_read!(count - value.bytesize)
34
- break if value.bytesize == count
35
- end
36
- value
37
- end
38
-
39
- def read_available
40
- value = String.new('')
41
- while true
42
- ret = kgio_tryread(8196)
43
- case ret
44
- when nil
45
- raise EOFError, 'end of stream'
46
- when :wait_readable
47
- break
48
- else
49
- value << ret
50
- end
51
- end
52
- value
53
- end
54
- end
55
-
56
- class Dalli::Server::KSocket::TCP < Dalli::Server::KSocket
57
- extend Dalli::Server::TCPSocketOptions
58
-
59
- def self.open(host, port, server, options = {})
60
- addr = Socket.pack_sockaddr_in(port, host)
61
- sock = start(addr)
62
- setsockopts(sock, options)
63
- sock.options = options
64
- sock.server = server
65
- sock.kgio_wait_writable
66
- sock
67
- rescue Timeout::Error
68
- sock.close if sock
69
- raise
70
- end
71
- end
72
-
73
- class Dalli::Server::KSocket::UNIX < Dalli::Server::KSocket
74
- def self.open(path, server, options = {})
75
- addr = Socket.pack_sockaddr_un(path)
76
- sock = start(addr)
77
- sock.options = options
78
- sock.server = server
79
- sock.kgio_wait_writable
80
- sock
81
- rescue Timeout::Error
82
- sock.close if sock
83
- raise
84
- end
85
- end
86
-
87
- if ::Kgio.respond_to?(:wait_readable=)
88
- ::Kgio.wait_readable = :kgio_wait_readable
89
- ::Kgio.wait_writable = :kgio_wait_writable
90
- end
91
-
92
- rescue LoadError
3
+ require 'openssl'
4
+ require 'rbconfig'
93
5
 
94
- puts "Using standard socket IO (#{RUBY_DESCRIPTION})" if defined?($TESTING) && $TESTING
95
- module Dalli::Server::KSocket
6
+ module Dalli
7
+ module Socket
96
8
  module InstanceMethods
9
+
97
10
  def readfull(count)
98
- value = String.new('')
99
- begin
100
- while true
101
- value << read_nonblock(count - value.bytesize)
102
- break if value.bytesize == count
103
- end
104
- rescue Errno::EAGAIN, Errno::EWOULDBLOCK
105
- if IO.select([self], nil, nil, options[:socket_timeout])
106
- retry
11
+ value = +""
12
+ loop do
13
+ result = read_nonblock(count - value.bytesize, exception: false)
14
+ if result == :wait_readable
15
+ raise Timeout::Error, "IO timeout: #{safe_options.inspect}" unless IO.select([self], nil, nil, options[:socket_timeout])
16
+ elsif result == :wait_writable
17
+ raise Timeout::Error, "IO timeout: #{safe_options.inspect}" unless IO.select(nil, [self], nil, options[:socket_timeout])
18
+ elsif result
19
+ value << result
107
20
  else
108
- safe_options = options.reject{|k,v| [:username, :password].include? k}
109
- raise Timeout::Error, "IO timeout: #{safe_options.inspect}"
21
+ raise Errno::ECONNRESET, "Connection reset: #{safe_options.inspect}"
110
22
  end
23
+ break if value.bytesize == count
111
24
  end
112
25
  value
113
26
  end
114
27
 
115
28
  def read_available
116
- value = String.new('')
117
- while true
118
- begin
119
- value << read_nonblock(8196)
120
- rescue Errno::EAGAIN, Errno::EWOULDBLOCK
29
+ value = +""
30
+ loop do
31
+ result = read_nonblock(8196, exception: false)
32
+ if result == :wait_readable
121
33
  break
34
+ elsif result == :wait_writable
35
+ break
36
+ elsif result
37
+ value << result
38
+ else
39
+ raise Errno::ECONNRESET, "Connection reset: #{safe_options.inspect}"
122
40
  end
123
41
  end
124
42
  value
125
43
  end
44
+
45
+ def safe_options
46
+ options.reject { |k, v| [:username, :password].include? k }
47
+ end
126
48
  end
127
49
 
128
- def self.included(receiver)
129
- receiver.send(:attr_accessor, :options, :server)
130
- receiver.send(:include, InstanceMethods)
50
+ class SSLSocket < ::OpenSSL::SSL::SSLSocket
51
+ include Dalli::Socket::InstanceMethods
52
+ def options
53
+ io.options
54
+ end
131
55
  end
132
- end
133
56
 
134
- class Dalli::Server::KSocket::TCP < TCPSocket
135
- extend Dalli::Server::TCPSocketOptions
136
- include Dalli::Server::KSocket
57
+ class TCP < TCPSocket
58
+ include Dalli::Socket::InstanceMethods
59
+ attr_accessor :options, :server
137
60
 
138
- def self.open(host, port, server, options = {})
139
- Timeout.timeout(options[:socket_timeout]) do
140
- sock = new(host, port)
141
- setsockopts(sock, options)
142
- sock.options = {:host => host, :port => port}.merge(options)
143
- sock.server = server
144
- sock
61
+ def self.open(host, port, server, options = {})
62
+ Timeout.timeout(options[:socket_timeout]) do
63
+ sock = new(host, port)
64
+ sock.options = {host: host, port: port}.merge(options)
65
+ sock.server = server
66
+ sock.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, true)
67
+ sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true) if options[:keepalive]
68
+ sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_RCVBUF, options[:rcvbuf]) if options[:rcvbuf]
69
+ sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_SNDBUF, options[:sndbuf]) if options[:sndbuf]
70
+
71
+ return sock unless options[:ssl_context]
72
+
73
+ ssl_socket = Dalli::Socket::SSLSocket.new(sock, options[:ssl_context])
74
+ ssl_socket.hostname = host
75
+ ssl_socket.sync_close = true
76
+ ssl_socket.connect
77
+ ssl_socket
78
+ end
145
79
  end
146
80
  end
147
81
  end
148
82
 
149
83
  if RbConfig::CONFIG['host_os'] =~ /mingw|mswin/
150
- class Dalli::Server::KSocket::UNIX
84
+ class Dalli::Socket::UNIX
151
85
  def initialize(*args)
152
- raise Dalli::DalliError, "Unix sockets are not supported on Windows platform."
86
+ raise Dalli::DalliError, 'Unix sockets are not supported on Windows platform.'
153
87
  end
154
88
  end
155
89
  else
156
- class Dalli::Server::KSocket::UNIX < UNIXSocket
157
- include Dalli::Server::KSocket
90
+ class Dalli::Socket::UNIX < UNIXSocket
91
+ include Dalli::Socket::InstanceMethods
92
+ attr_accessor :options, :server
158
93
 
159
94
  def self.open(path, server, options = {})
160
95
  Timeout.timeout(options[:socket_timeout]) do
161
96
  sock = new(path)
162
- sock.options = {:path => path}.merge(options)
97
+ sock.options = {path: path}.merge(options)
163
98
  sock.server = server
164
99
  sock
165
100
  end
166
101
  end
167
102
  end
168
-
169
103
  end
170
104
  end
data/lib/dalli/version.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Dalli
3
- VERSION = '2.7.11'
4
+ VERSION = "3.0.4"
4
5
  end
data/lib/dalli.rb CHANGED
@@ -1,14 +1,20 @@
1
1
  # frozen_string_literal: true
2
- require 'dalli/compressor'
3
- require 'dalli/client'
4
- require 'dalli/ring'
5
- require 'dalli/server'
6
- require 'dalli/socket'
7
- require 'dalli/version'
8
- require 'dalli/options'
9
- require 'dalli/railtie' if defined?(::Rails::Railtie)
2
+
3
+ require "dalli/compressor"
4
+ require "dalli/client"
5
+ require "dalli/ring"
6
+ require "dalli/protocol"
7
+ require "dalli/protocol/binary"
8
+ require "dalli/protocol/server_config_parser"
9
+ require "dalli/protocol/ttl_sanitizer"
10
+ require 'dalli/protocol/value_compressor'
11
+ require "dalli/socket"
12
+ require "dalli/version"
13
+ require "dalli/options"
10
14
 
11
15
  module Dalli
16
+ autoload :Server, "dalli/server"
17
+
12
18
  # generic error
13
19
  class DalliError < RuntimeError; end
14
20
  # socket/server communication error
@@ -28,12 +34,12 @@ module Dalli
28
34
 
29
35
  def self.rails_logger
30
36
  (defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger) ||
31
- (defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER.respond_to?(:debug) && RAILS_DEFAULT_LOGGER)
37
+ (defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER.respond_to?(:debug) && RAILS_DEFAULT_LOGGER)
32
38
  end
33
39
 
34
40
  def self.default_logger
35
- require 'logger'
36
- l = Logger.new(STDOUT)
41
+ require "logger"
42
+ l = Logger.new($stdout)
37
43
  l.level = Logger::INFO
38
44
  l
39
45
  end
@@ -41,9 +47,4 @@ module Dalli
41
47
  def self.logger=(logger)
42
48
  @logger = logger
43
49
  end
44
-
45
- end
46
-
47
- if defined?(RAILS_VERSION) && RAILS_VERSION < '3'
48
- raise Dalli::DalliError, "Dalli #{Dalli::VERSION} does not support Rails version < 3.0"
49
50
  end
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
  require 'rack/session/abstract/id'
3
3
  require 'dalli'
4
+ require 'connection_pool'
4
5
 
5
6
  module Rack
6
7
  module Session
7
- class Dalli < defined?(Abstract::Persisted) ? Abstract::Persisted : Abstract::ID
8
- attr_reader :pool, :mutex
8
+ class Dalli < Abstract::Persisted
9
+ attr_reader :pool
9
10
 
10
11
  DEFAULT_DALLI_OPTIONS = {
11
12
  :namespace => 'rack:session',
@@ -74,26 +75,13 @@ module Rack
74
75
  @default_ttl = ttl @default_options[:expire_after]
75
76
 
76
77
  # Normalize and validate passed options
77
- cache, mserv, mopts, popts = extract_dalli_options options
78
-
79
- @pool =
80
- if cache # caller passed a Dalli::Client or ConnectionPool instance
81
- cache
82
- elsif popts # caller passed ConnectionPool options
83
- ConnectionPool.new(popts) { ::Dalli::Client.new(mserv, mopts) }
84
- else
85
- ::Dalli::Client.new(mserv, mopts)
86
- end
87
-
88
- if @pool.respond_to?(:alive!) # is a Dalli::Client
89
- @mutex = Mutex.new
78
+ mserv, mopts, popts = extract_dalli_options(options)
90
79
 
91
- @pool.alive!
92
- end
80
+ @pool = ConnectionPool.new(popts || {}) { ::Dalli::Client.new(mserv, mopts) }
93
81
  end
94
82
 
95
83
  def get_session(env, sid)
96
- with_block(env, [nil, {}]) do |dc|
84
+ with_block([nil, {}]) do |dc|
97
85
  unless sid and !sid.empty? and session = dc.get(sid)
98
86
  old_sid, sid, session = sid, generate_sid_with(dc), {}
99
87
  unless dc.add(sid, session, @default_ttl)
@@ -108,53 +96,49 @@ module Rack
108
96
  def set_session(env, session_id, new_session, options)
109
97
  return false unless session_id
110
98
 
111
- with_block(env, false) do |dc|
99
+ with_block(false) do |dc|
112
100
  dc.set(session_id, new_session, ttl(options[:expire_after]))
113
101
  session_id
114
102
  end
115
103
  end
116
104
 
117
105
  def destroy_session(env, session_id, options)
118
- with_block(env) do |dc|
106
+ with_block do |dc|
119
107
  dc.delete(session_id)
120
108
  generate_sid_with(dc) unless options[:drop]
121
109
  end
122
110
  end
123
111
 
124
- if defined?(Abstract::Persisted)
125
- def find_session(req, sid)
126
- get_session req.env, sid
127
- end
112
+ def find_session(req, sid)
113
+ get_session req.env, sid
114
+ end
128
115
 
129
- def write_session(req, sid, session, options)
130
- set_session req.env, sid, session, options
131
- end
116
+ def write_session(req, sid, session, options)
117
+ set_session req.env, sid, session, options
118
+ end
132
119
 
133
- def delete_session(req, sid, options)
134
- destroy_session req.env, sid, options
135
- end
120
+ def delete_session(req, sid, options)
121
+ destroy_session req.env, sid, options
136
122
  end
137
123
 
138
124
  private
139
125
 
140
126
  def extract_dalli_options(options)
141
- return [options[:cache]] if options[:cache]
127
+ raise "Rack::Session::Dalli no longer supports the :cache option." if options[:cache]
142
128
 
129
+ popts = {}
143
130
  # Filter out Rack::Session-specific options and apply our defaults
144
131
  mopts = DEFAULT_DALLI_OPTIONS.merge \
145
132
  options.reject {|k, _| DEFAULT_OPTIONS.key? k }
146
133
  mserv = mopts.delete :memcache_server
147
134
 
148
135
  if mopts[:pool_size] || mopts[:pool_timeout]
149
- popts = {}
150
136
  popts[:size] = mopts.delete :pool_size if mopts[:pool_size]
151
137
  popts[:timeout] = mopts.delete :pool_timeout if mopts[:pool_timeout]
152
-
153
- # For a connection pool, locking is handled at the pool level
154
- mopts[:threadsafe] = false unless mopts.key? :threadsafe
138
+ mopts[:threadsafe] = true
155
139
  end
156
140
 
157
- [nil, mserv, mopts, popts]
141
+ [mserv, mopts, popts]
158
142
  end
159
143
 
160
144
  def generate_sid_with(dc)
@@ -164,8 +148,7 @@ module Rack
164
148
  end
165
149
  end
166
150
 
167
- def with_block(env, default=nil, &block)
168
- @mutex.lock if @mutex and env['rack.multithread']
151
+ def with_block(default=nil, &block)
169
152
  @pool.with(&block)
170
153
  rescue ::Dalli::DalliError, Errno::ECONNREFUSED
171
154
  raise if $!.message =~ /undefined class/
@@ -174,8 +157,6 @@ module Rack
174
157
  warn $!.inspect
175
158
  end
176
159
  default
177
- ensure
178
- @mutex.unlock if @mutex and @mutex.locked?
179
160
  end
180
161
 
181
162
  def ttl(expire_after)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dalli
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.7.11
4
+ version: 3.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter M. Goldstein
@@ -9,8 +9,36 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-09-26 00:00:00.000000000 Z
13
- dependencies: []
12
+ date: 2021-10-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rack
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: connection_pool
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'
14
42
  description: High performance memcached client for Ruby
15
43
  email:
16
44
  - peter.m.goldstein@gmail.com
@@ -23,14 +51,16 @@ files:
23
51
  - History.md
24
52
  - LICENSE
25
53
  - README.md
26
- - lib/action_dispatch/middleware/session/dalli_store.rb
27
- - lib/active_support/cache/dalli_store.rb
28
54
  - lib/dalli.rb
29
55
  - lib/dalli/cas/client.rb
30
56
  - lib/dalli/client.rb
31
57
  - lib/dalli/compressor.rb
32
58
  - lib/dalli/options.rb
33
- - lib/dalli/railtie.rb
59
+ - lib/dalli/protocol.rb
60
+ - lib/dalli/protocol/binary.rb
61
+ - lib/dalli/protocol/server_config_parser.rb
62
+ - lib/dalli/protocol/ttl_sanitizer.rb
63
+ - lib/dalli/protocol/value_compressor.rb
34
64
  - lib/dalli/ring.rb
35
65
  - lib/dalli/server.rb
36
66
  - lib/dalli/socket.rb
@@ -55,8 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
55
85
  - !ruby/object:Gem::Version
56
86
  version: '0'
57
87
  requirements: []
58
- rubyforge_project:
59
- rubygems_version: 2.7.6.2
88
+ rubygems_version: 3.2.30
60
89
  signing_key:
61
90
  specification_version: 4
62
91
  summary: High performance memcached client for Ruby
@@ -1,82 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'active_support/cache'
3
- require 'action_dispatch/middleware/session/abstract_store'
4
- require 'dalli'
5
-
6
- # Dalli-based session store for Rails 3.0.
7
- module ActionDispatch
8
- module Session
9
- class DalliStore < AbstractStore
10
- def initialize(app, options = {})
11
- # Support old :expires option
12
- options[:expire_after] ||= options[:expires]
13
-
14
- super
15
-
16
- @default_options = { :namespace => 'rack:session' }.merge(@default_options)
17
-
18
- @pool = options[:cache] || begin
19
- Dalli::Client.new(
20
- @default_options[:memcache_server], @default_options)
21
- end
22
- @namespace = @default_options[:namespace]
23
-
24
- @raise_errors = !!@default_options[:raise_errors]
25
-
26
- super
27
- end
28
-
29
- def reset
30
- @pool.reset
31
- end
32
-
33
- private
34
-
35
- def get_session(env, sid)
36
- sid = generate_sid unless sid and !sid.empty?
37
- begin
38
- session = @pool.get(sid) || {}
39
- rescue Dalli::DalliError => ex
40
- # re-raise ArgumentError so Rails' session abstract_store.rb can autoload any missing models
41
- raise ArgumentError, ex.message if ex.message =~ /unmarshal/
42
- Rails.logger.warn("Session::DalliStore#get: #{ex.message}")
43
- session = {}
44
- end
45
- [sid, session]
46
- end
47
-
48
- def set_session(env, sid, session_data, options = nil)
49
- options ||= env[ENV_SESSION_OPTIONS_KEY]
50
- expiry = options[:expire_after]
51
- @pool.set(sid, session_data, expiry)
52
- sid
53
- rescue Dalli::DalliError
54
- Rails.logger.warn("Session::DalliStore#set: #{$!.message}")
55
- raise if @raise_errors
56
- false
57
- end
58
-
59
- def destroy_session(env, session_id, options)
60
- begin
61
- @pool.delete(session_id)
62
- rescue Dalli::DalliError
63
- Rails.logger.warn("Session::DalliStore#destroy_session: #{$!.message}")
64
- raise if @raise_errors
65
- end
66
- return nil if options[:drop]
67
- generate_sid
68
- end
69
-
70
- def destroy(env)
71
- if sid = current_session_id(env)
72
- @pool.delete(sid)
73
- end
74
- rescue Dalli::DalliError
75
- Rails.logger.warn("Session::DalliStore#destroy: #{$!.message}")
76
- raise if @raise_errors
77
- false
78
- end
79
-
80
- end
81
- end
82
- end