dalli 2.7.11 → 3.0.0

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,95 @@
1
1
  # frozen_string_literal: true
2
- require 'rbconfig'
3
2
 
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
-
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
3
+ require 'openssl'
72
4
 
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
93
-
94
- puts "Using standard socket IO (#{RUBY_DESCRIPTION})" if defined?($TESTING) && $TESTING
95
- module Dalli::Server::KSocket
5
+ module Dalli
6
+ module Socket
96
7
  module InstanceMethods
8
+
97
9
  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
10
+ value = +""
11
+ loop do
12
+ result = read_nonblock(count - value.bytesize, exception: false)
13
+ if result == :wait_readable
14
+ raise Timeout::Error, "IO timeout: #{safe_options.inspect}" unless IO.select([self], nil, nil, options[:socket_timeout])
15
+ elsif result == :wait_writable
16
+ raise Timeout::Error, "IO timeout: #{safe_options.inspect}" unless IO.select(nil, [self], nil, options[:socket_timeout])
17
+ elsif result
18
+ value << result
107
19
  else
108
- safe_options = options.reject{|k,v| [:username, :password].include? k}
109
- raise Timeout::Error, "IO timeout: #{safe_options.inspect}"
20
+ raise Errno::ECONNRESET, "Connection reset: #{safe_options.inspect}"
110
21
  end
22
+ break if value.bytesize == count
111
23
  end
112
24
  value
113
25
  end
114
26
 
115
27
  def read_available
116
- value = String.new('')
117
- while true
118
- begin
119
- value << read_nonblock(8196)
120
- rescue Errno::EAGAIN, Errno::EWOULDBLOCK
28
+ value = +""
29
+ loop do
30
+ result = read_nonblock(8196, exception: false)
31
+ if result == :wait_readable
32
+ break
33
+ elsif result == :wait_writable
121
34
  break
35
+ elsif result
36
+ value << result
37
+ else
38
+ raise Errno::ECONNRESET, "Connection reset: #{safe_options.inspect}"
122
39
  end
123
40
  end
124
41
  value
125
42
  end
126
- end
127
43
 
128
- def self.included(receiver)
129
- receiver.send(:attr_accessor, :options, :server)
130
- receiver.send(:include, InstanceMethods)
44
+ def safe_options
45
+ options.reject { |k, v| [:username, :password].include? k }
46
+ end
131
47
  end
132
- end
133
-
134
- class Dalli::Server::KSocket::TCP < TCPSocket
135
- extend Dalli::Server::TCPSocketOptions
136
- include Dalli::Server::KSocket
137
48
 
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
49
+ class SSLSocket < ::OpenSSL::SSL::SSLSocket
50
+ include Dalli::Socket::InstanceMethods
51
+ def options
52
+ io.options
145
53
  end
146
54
  end
147
- end
148
55
 
149
- if RbConfig::CONFIG['host_os'] =~ /mingw|mswin/
150
- class Dalli::Server::KSocket::UNIX
151
- def initialize(*args)
152
- raise Dalli::DalliError, "Unix sockets are not supported on Windows platform."
56
+ class TCP < TCPSocket
57
+ include Dalli::Socket::InstanceMethods
58
+ attr_accessor :options, :server
59
+
60
+ def self.open(host, port, server, options = {})
61
+ Timeout.timeout(options[:socket_timeout]) do
62
+ sock = new(host, port)
63
+ sock.options = {host: host, port: port}.merge(options)
64
+ sock.server = server
65
+ sock.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, true)
66
+ sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true) if options[:keepalive]
67
+ sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_RCVBUF, options[:rcvbuf]) if options[:rcvbuf]
68
+ sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_SNDBUF, options[:sndbuf]) if options[:sndbuf]
69
+
70
+ return sock unless options[:ssl_context]
71
+
72
+ ssl_socket = Dalli::Socket::SSLSocket.new(sock, options[:ssl_context])
73
+ ssl_socket.hostname = host
74
+ ssl_socket.sync_close = true
75
+ ssl_socket.connect
76
+ ssl_socket
77
+ end
153
78
  end
154
79
  end
155
- else
156
- class Dalli::Server::KSocket::UNIX < UNIXSocket
157
- include Dalli::Server::KSocket
80
+
81
+ class UNIX < UNIXSocket
82
+ include Dalli::Socket::InstanceMethods
83
+ attr_accessor :options, :server
158
84
 
159
85
  def self.open(path, server, options = {})
160
86
  Timeout.timeout(options[:socket_timeout]) do
161
87
  sock = new(path)
162
- sock.options = {:path => path}.merge(options)
88
+ sock.options = {path: path}.merge(options)
163
89
  sock.server = server
164
90
  sock
165
91
  end
166
92
  end
167
93
  end
168
-
169
94
  end
170
95
  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.0"
4
5
  end
data/lib/dalli.rb CHANGED
@@ -1,14 +1,17 @@
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/socket"
9
+ require "dalli/version"
10
+ require "dalli/options"
10
11
 
11
12
  module Dalli
13
+ autoload :Server, "dalli/server"
14
+
12
15
  # generic error
13
16
  class DalliError < RuntimeError; end
14
17
  # socket/server communication error
@@ -28,12 +31,12 @@ module Dalli
28
31
 
29
32
  def self.rails_logger
30
33
  (defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger) ||
31
- (defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER.respond_to?(:debug) && RAILS_DEFAULT_LOGGER)
34
+ (defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER.respond_to?(:debug) && RAILS_DEFAULT_LOGGER)
32
35
  end
33
36
 
34
37
  def self.default_logger
35
- require 'logger'
36
- l = Logger.new(STDOUT)
38
+ require "logger"
39
+ l = Logger.new($stdout)
37
40
  l.level = Logger::INFO
38
41
  l
39
42
  end
@@ -41,9 +44,4 @@ module Dalli
41
44
  def self.logger=(logger)
42
45
  @logger = logger
43
46
  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
47
  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.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter M. Goldstein
@@ -9,8 +9,50 @@ 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-13 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'
42
+ - !ruby/object:Gem::Dependency
43
+ name: openssl-extensions
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
14
56
  description: High performance memcached client for Ruby
15
57
  email:
16
58
  - peter.m.goldstein@gmail.com
@@ -23,14 +65,13 @@ files:
23
65
  - History.md
24
66
  - LICENSE
25
67
  - README.md
26
- - lib/action_dispatch/middleware/session/dalli_store.rb
27
- - lib/active_support/cache/dalli_store.rb
28
68
  - lib/dalli.rb
29
69
  - lib/dalli/cas/client.rb
30
70
  - lib/dalli/client.rb
31
71
  - lib/dalli/compressor.rb
32
72
  - lib/dalli/options.rb
33
- - lib/dalli/railtie.rb
73
+ - lib/dalli/protocol.rb
74
+ - lib/dalli/protocol/binary.rb
34
75
  - lib/dalli/ring.rb
35
76
  - lib/dalli/server.rb
36
77
  - lib/dalli/socket.rb
@@ -55,8 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
55
96
  - !ruby/object:Gem::Version
56
97
  version: '0'
57
98
  requirements: []
58
- rubyforge_project:
59
- rubygems_version: 2.7.6.2
99
+ rubygems_version: 3.2.29
60
100
  signing_key:
61
101
  specification_version: 4
62
102
  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