bundler 4.0.23 → 4.1.0.beta1

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.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/{lib/bundler/vendor/connection_pool/LICENSE → MIT.txt} +8 -6
  3. data/bundler.gemspec +23 -6
  4. data/lib/bundler/build_metadata.rb +2 -2
  5. data/lib/bundler/checksum.rb +40 -25
  6. data/lib/bundler/ci_detector.rb +1 -1
  7. data/lib/bundler/cli/add.rb +3 -4
  8. data/lib/bundler/cli/cache.rb +4 -0
  9. data/lib/bundler/cli/clean.rb +5 -0
  10. data/lib/bundler/cli/common.rb +37 -1
  11. data/lib/bundler/cli/config.rb +4 -2
  12. data/lib/bundler/cli/gem.rb +0 -17
  13. data/lib/bundler/cli/install.rb +4 -5
  14. data/lib/bundler/cli/lock.rb +4 -16
  15. data/lib/bundler/cli/outdated.rb +8 -3
  16. data/lib/bundler/cli/platform.rb +1 -15
  17. data/lib/bundler/cli/pristine.rb +2 -1
  18. data/lib/bundler/cli/update.rb +21 -12
  19. data/lib/bundler/cli.rb +19 -28
  20. data/lib/bundler/definition.rb +61 -24
  21. data/lib/bundler/dependency.rb +4 -0
  22. data/lib/bundler/dsl.rb +77 -11
  23. data/lib/bundler/endpoint_specification.rb +51 -14
  24. data/lib/bundler/env.rb +7 -24
  25. data/lib/bundler/errors.rb +34 -5
  26. data/lib/bundler/fetcher/compact_index.rb +14 -5
  27. data/lib/bundler/fetcher/connection_pools.rb +150 -0
  28. data/lib/bundler/fetcher/downloader.rb +33 -24
  29. data/lib/bundler/fetcher.rb +8 -47
  30. data/lib/bundler/injector.rb +3 -3
  31. data/lib/bundler/inline.rb +44 -4
  32. data/lib/bundler/installer/parallel_installer.rb +25 -30
  33. data/lib/bundler/installer.rb +20 -10
  34. data/lib/bundler/lazy_specification.rb +44 -17
  35. data/lib/bundler/lockfile_generator.rb +24 -2
  36. data/lib/bundler/lockfile_parser.rb +43 -5
  37. data/lib/bundler/man/bundle-add.1 +7 -4
  38. data/lib/bundler/man/bundle-add.1.ronn +8 -4
  39. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  40. data/lib/bundler/man/bundle-cache.1 +2 -2
  41. data/lib/bundler/man/bundle-cache.1.ronn +2 -2
  42. data/lib/bundler/man/bundle-check.1 +1 -1
  43. data/lib/bundler/man/bundle-clean.1 +1 -1
  44. data/lib/bundler/man/bundle-config.1 +38 -6
  45. data/lib/bundler/man/bundle-config.1.ronn +143 -10
  46. data/lib/bundler/man/bundle-console.1 +1 -1
  47. data/lib/bundler/man/bundle-doctor.1 +1 -1
  48. data/lib/bundler/man/bundle-env.1 +1 -1
  49. data/lib/bundler/man/bundle-exec.1 +1 -1
  50. data/lib/bundler/man/bundle-fund.1 +1 -1
  51. data/lib/bundler/man/bundle-gem.1 +1 -1
  52. data/lib/bundler/man/bundle-help.1 +1 -1
  53. data/lib/bundler/man/bundle-info.1 +1 -1
  54. data/lib/bundler/man/bundle-init.1 +1 -1
  55. data/lib/bundler/man/bundle-install.1 +2 -2
  56. data/lib/bundler/man/bundle-install.1.ronn +4 -4
  57. data/lib/bundler/man/bundle-issue.1 +1 -1
  58. data/lib/bundler/man/bundle-licenses.1 +1 -1
  59. data/lib/bundler/man/bundle-list.1 +1 -1
  60. data/lib/bundler/man/bundle-lock.1 +4 -4
  61. data/lib/bundler/man/bundle-lock.1.ronn +6 -6
  62. data/lib/bundler/man/bundle-open.1 +1 -1
  63. data/lib/bundler/man/bundle-outdated.1 +2 -2
  64. data/lib/bundler/man/bundle-outdated.1.ronn +1 -1
  65. data/lib/bundler/man/bundle-platform.1 +1 -1
  66. data/lib/bundler/man/bundle-plugin.1 +1 -1
  67. data/lib/bundler/man/bundle-pristine.1 +1 -1
  68. data/lib/bundler/man/bundle-remove.1 +1 -1
  69. data/lib/bundler/man/bundle-show.1 +1 -1
  70. data/lib/bundler/man/bundle-update.1 +5 -5
  71. data/lib/bundler/man/bundle-update.1.ronn +5 -7
  72. data/lib/bundler/man/bundle-version.1 +1 -1
  73. data/lib/bundler/man/bundle.1 +1 -1
  74. data/lib/bundler/man/gemfile.5 +45 -1
  75. data/lib/bundler/man/gemfile.5.ronn +53 -0
  76. data/lib/bundler/match_metadata.rb +20 -0
  77. data/lib/bundler/match_platform.rb +25 -2
  78. data/lib/bundler/match_remote_metadata.rb +21 -6
  79. data/lib/bundler/materialization.rb +2 -1
  80. data/lib/bundler/override.rb +69 -0
  81. data/lib/bundler/plugin/dsl.rb +3 -5
  82. data/lib/bundler/plugin/events.rb +55 -13
  83. data/lib/bundler/plugin/index.rb +87 -11
  84. data/lib/bundler/plugin/installer/path.rb +1 -1
  85. data/lib/bundler/plugin/installer.rb +13 -5
  86. data/lib/bundler/plugin.rb +58 -30
  87. data/lib/bundler/remote_specification.rb +6 -3
  88. data/lib/bundler/resolver/base.rb +2 -1
  89. data/lib/bundler/resolver/incompatibility.rb +1 -1
  90. data/lib/bundler/resolver.rb +73 -23
  91. data/lib/bundler/ruby_version.rb +0 -2
  92. data/lib/bundler/rubygems_ext.rb +71 -1
  93. data/lib/bundler/rubygems_gem_installer.rb +41 -2
  94. data/lib/bundler/rubygems_integration.rb +7 -2
  95. data/lib/bundler/runtime.rb +69 -2
  96. data/lib/bundler/self_manager.rb +9 -15
  97. data/lib/bundler/settings.rb +373 -30
  98. data/lib/bundler/shared_helpers.rb +2 -1
  99. data/lib/bundler/source/git/git_proxy.rb +2 -10
  100. data/lib/bundler/source/git.rb +15 -6
  101. data/lib/bundler/source/path/installer.rb +1 -1
  102. data/lib/bundler/source/rubygems/remote.rb +10 -5
  103. data/lib/bundler/source/rubygems.rb +48 -12
  104. data/lib/bundler/spec_set.rb +16 -4
  105. data/lib/bundler/stub_specification.rb +2 -1
  106. data/lib/bundler/templates/newgem/Gemfile.tt +4 -4
  107. data/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt +1 -1
  108. data/lib/bundler/templates/newgem/newgem.gemspec.tt +3 -3
  109. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +1 -1
  110. data/lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt +1 -1
  111. data/lib/bundler/ui/shell.rb +0 -4
  112. data/lib/bundler/ui/silent.rb +0 -4
  113. data/lib/bundler/vendor/fileutils/lib/fileutils.rb +29 -54
  114. data/lib/bundler/vendored_pub_grub.rb +5 -2
  115. data/lib/bundler/vendored_securerandom.rb +11 -8
  116. data/lib/bundler/vendored_uri.rb +14 -14
  117. data/lib/bundler/version.rb +1 -1
  118. data/lib/bundler/worker.rb +3 -2
  119. data/lib/bundler.rb +4 -2
  120. data/lib/rubygems/compact_index_client/cache.rb +122 -0
  121. data/lib/rubygems/compact_index_client/cache_file.rb +147 -0
  122. data/lib/rubygems/compact_index_client/http_fetcher.rb +88 -0
  123. data/lib/rubygems/compact_index_client/parser.rb +90 -0
  124. data/lib/rubygems/compact_index_client/updater.rb +113 -0
  125. data/lib/rubygems/compact_index_client.rb +111 -0
  126. data/lib/rubygems/cooldown_settings.rb +57 -0
  127. data/lib/rubygems/credential_store/native/linux.rb +97 -0
  128. data/lib/rubygems/credential_store/native/macos.rb +88 -0
  129. data/lib/rubygems/credential_store/native/windows.rb +130 -0
  130. data/lib/rubygems/credential_store.rb +332 -0
  131. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/assignment.rb +1 -1
  132. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +7 -7
  133. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/failure_writer.rb +1 -1
  134. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/incompatibility.rb +4 -4
  135. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/package.rb +1 -1
  136. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/partial_solution.rb +1 -1
  137. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/rubygems.rb +3 -3
  138. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/solve_failure.rb +1 -1
  139. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/static_package_source.rb +3 -3
  140. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/strategy.rb +2 -2
  141. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/term.rb +1 -1
  142. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version.rb +1 -1
  143. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_constraint.rb +3 -3
  144. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_range.rb +1 -1
  145. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_solver.rb +2 -2
  146. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_union.rb +1 -1
  147. data/lib/rubygems/vendor/pub_grub/lib/pub_grub.rb +57 -0
  148. data/lib/{bundler → rubygems}/vendor/securerandom/lib/securerandom.rb +10 -6
  149. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/common.rb +120 -120
  150. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/file.rb +13 -13
  151. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ftp.rb +24 -24
  152. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/generic.rb +135 -147
  153. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/http.rb +18 -18
  154. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/https.rb +4 -4
  155. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ldap.rb +14 -14
  156. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ldaps.rb +4 -4
  157. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/mailto.rb +21 -21
  158. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/rfc2396_parser.rb +39 -39
  159. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/rfc3986_parser.rb +14 -14
  160. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/version.rb +2 -2
  161. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ws.rb +12 -12
  162. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/wss.rb +4 -4
  163. data/lib/{bundler → rubygems}/vendor/uri/lib/uri.rb +35 -31
  164. data/lib/rubygems/yaml_serializer.rb +880 -0
  165. metadata +77 -68
  166. data/CHANGELOG.md +0 -5812
  167. data/LICENSE.md +0 -22
  168. data/README.md +0 -58
  169. data/lib/bundler/compact_index_client/cache.rb +0 -107
  170. data/lib/bundler/compact_index_client/cache_file.rb +0 -148
  171. data/lib/bundler/compact_index_client/parser.rb +0 -87
  172. data/lib/bundler/compact_index_client/updater.rb +0 -105
  173. data/lib/bundler/compact_index_client.rb +0 -92
  174. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +0 -237
  175. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +0 -3
  176. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +0 -56
  177. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +0 -233
  178. data/lib/bundler/vendor/net-http-persistent/README.rdoc +0 -82
  179. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb +0 -41
  180. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb +0 -65
  181. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb +0 -89
  182. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +0 -1159
  183. data/lib/bundler/vendor/pub_grub/lib/pub_grub.rb +0 -31
  184. data/lib/bundler/vendored_persistent.rb +0 -11
  185. data/lib/bundler/yaml_serializer.rb +0 -98
  186. /data/lib/{bundler → rubygems}/vendor/pub_grub/LICENSE.txt +0 -0
  187. /data/lib/{bundler → rubygems}/vendor/securerandom/COPYING +0 -0
  188. /data/lib/{bundler → rubygems}/vendor/uri/COPYING +0 -0
@@ -1,237 +0,0 @@
1
- ##
2
- # The TimedStack manages a pool of homogeneous connections (or any resource
3
- # you wish to manage). Connections are created lazily up to a given maximum
4
- # number.
5
- #
6
- # Examples:
7
- #
8
- # ts = TimedStack.new(1) { MyConnection.new }
9
- #
10
- # # fetch a connection
11
- # conn = ts.pop
12
- #
13
- # # return a connection
14
- # ts.push conn
15
- #
16
- # conn = ts.pop
17
- # ts.pop timeout: 5
18
- # #=> raises Bundler::ConnectionPool::TimeoutError after 5 seconds
19
- class Bundler::ConnectionPool::TimedStack
20
- attr_reader :max
21
-
22
- ##
23
- # Creates a new pool with +size+ connections that are created from the given
24
- # +block+.
25
- def initialize(size = 0, &block)
26
- @create_block = block
27
- @created = 0
28
- @que = []
29
- @max = size
30
- @mutex = Thread::Mutex.new
31
- @resource = Thread::ConditionVariable.new
32
- @shutdown_block = nil
33
- end
34
-
35
- ##
36
- # Returns +obj+ to the stack. +options+ is ignored in TimedStack but may be
37
- # used by subclasses that extend TimedStack.
38
- def push(obj, options = {})
39
- @mutex.synchronize do
40
- if @shutdown_block
41
- @created -= 1 unless @created == 0
42
- @shutdown_block.call(obj)
43
- else
44
- store_connection obj, options
45
- end
46
-
47
- @resource.broadcast
48
- end
49
- end
50
- alias_method :<<, :push
51
-
52
- ##
53
- # Retrieves a connection from the stack. If a connection is available it is
54
- # immediately returned. If no connection is available within the given
55
- # timeout a Bundler::ConnectionPool::TimeoutError is raised.
56
- #
57
- # @option options [Float] :timeout (0.5) Wait this many seconds for an available entry
58
- # @option options [Class] :exception (Bundler::ConnectionPool::TimeoutError) Exception class to raise
59
- # if an entry was not available within the timeout period. Use `exception: false` to return nil.
60
- #
61
- # The +timeout+ argument will be removed in 3.0.
62
- # Other options may be used by subclasses that extend TimedStack.
63
- def pop(timeout = 0.5, options = {})
64
- options, timeout = timeout, 0.5 if Hash === timeout
65
- timeout = options.fetch :timeout, timeout
66
-
67
- deadline = current_time + timeout
68
- @mutex.synchronize do
69
- loop do
70
- raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block
71
- if (conn = try_fetch_connection(options))
72
- return conn
73
- end
74
-
75
- connection = try_create(options)
76
- return connection if connection
77
-
78
- to_wait = deadline - current_time
79
- if to_wait <= 0
80
- exc = options.fetch(:exception, Bundler::ConnectionPool::TimeoutError)
81
- if exc
82
- raise Bundler::ConnectionPool::TimeoutError, "Waited #{timeout} sec, #{length}/#{@max} available"
83
- else
84
- return nil
85
- end
86
- end
87
- @resource.wait(@mutex, to_wait)
88
- end
89
- end
90
- end
91
-
92
- ##
93
- # Shuts down the TimedStack by passing each connection to +block+ and then
94
- # removing it from the pool. Attempting to checkout a connection after
95
- # shutdown will raise +Bundler::ConnectionPool::PoolShuttingDownError+ unless
96
- # +:reload+ is +true+.
97
- def shutdown(reload: false, &block)
98
- raise ArgumentError, "shutdown must receive a block" unless block
99
-
100
- @mutex.synchronize do
101
- @shutdown_block = block
102
- @resource.broadcast
103
-
104
- shutdown_connections
105
- @shutdown_block = nil if reload
106
- end
107
- end
108
-
109
- ##
110
- # Reaps connections that were checked in more than +idle_seconds+ ago.
111
- def reap(idle_seconds, &block)
112
- raise ArgumentError, "reap must receive a block" unless block
113
- raise ArgumentError, "idle_seconds must be a number" unless idle_seconds.is_a?(Numeric)
114
- raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block
115
-
116
- idle.times do
117
- conn =
118
- @mutex.synchronize do
119
- raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block
120
-
121
- reserve_idle_connection(idle_seconds)
122
- end
123
- break unless conn
124
-
125
- block.call(conn)
126
- end
127
- end
128
-
129
- ##
130
- # Returns +true+ if there are no available connections.
131
- def empty?
132
- (@created - @que.length) >= @max
133
- end
134
-
135
- ##
136
- # The number of connections available on the stack.
137
- def length
138
- @max - @created + @que.length
139
- end
140
-
141
- ##
142
- # The number of connections created and available on the stack.
143
- def idle
144
- @que.length
145
- end
146
-
147
- ##
148
- # Reduce the created count
149
- def decrement_created
150
- @created -= 1 unless @created == 0
151
- end
152
-
153
- private
154
-
155
- def current_time
156
- Process.clock_gettime(Process::CLOCK_MONOTONIC)
157
- end
158
-
159
- ##
160
- # This is an extension point for TimedStack and is called with a mutex.
161
- #
162
- # This method must returns a connection from the stack if one exists. Allows
163
- # subclasses with expensive match/search algorithms to avoid double-handling
164
- # their stack.
165
- def try_fetch_connection(options = nil)
166
- connection_stored?(options) && fetch_connection(options)
167
- end
168
-
169
- ##
170
- # This is an extension point for TimedStack and is called with a mutex.
171
- #
172
- # This method must returns true if a connection is available on the stack.
173
- def connection_stored?(options = nil)
174
- !@que.empty?
175
- end
176
-
177
- ##
178
- # This is an extension point for TimedStack and is called with a mutex.
179
- #
180
- # This method must return a connection from the stack.
181
- def fetch_connection(options = nil)
182
- @que.pop&.first
183
- end
184
-
185
- ##
186
- # This is an extension point for TimedStack and is called with a mutex.
187
- #
188
- # This method must shut down all connections on the stack.
189
- def shutdown_connections(options = nil)
190
- while (conn = try_fetch_connection(options))
191
- @created -= 1 unless @created == 0
192
- @shutdown_block.call(conn)
193
- end
194
- end
195
-
196
- ##
197
- # This is an extension point for TimedStack and is called with a mutex.
198
- #
199
- # This method returns the oldest idle connection if it has been idle for more than idle_seconds.
200
- # This requires that the stack is kept in order of checked in time (oldest first).
201
- def reserve_idle_connection(idle_seconds)
202
- return unless idle_connections?(idle_seconds)
203
-
204
- @created -= 1 unless @created == 0
205
-
206
- @que.shift.first
207
- end
208
-
209
- ##
210
- # This is an extension point for TimedStack and is called with a mutex.
211
- #
212
- # Returns true if the first connection in the stack has been idle for more than idle_seconds
213
- def idle_connections?(idle_seconds)
214
- connection_stored? && (current_time - @que.first.last > idle_seconds)
215
- end
216
-
217
- ##
218
- # This is an extension point for TimedStack and is called with a mutex.
219
- #
220
- # This method must return +obj+ to the stack.
221
- def store_connection(obj, options = nil)
222
- @que.push [obj, current_time]
223
- end
224
-
225
- ##
226
- # This is an extension point for TimedStack and is called with a mutex.
227
- #
228
- # This method must create a connection if and only if the total number of
229
- # connections allowed has not been met.
230
- def try_create(options = nil)
231
- unless @created == @max
232
- object = @create_block.call
233
- @created += 1
234
- object
235
- end
236
- end
237
- end
@@ -1,3 +0,0 @@
1
- class Bundler::ConnectionPool
2
- VERSION = "2.5.5"
3
- end
@@ -1,56 +0,0 @@
1
- class Bundler::ConnectionPool
2
- class Wrapper < ::BasicObject
3
- METHODS = [:with, :pool_shutdown, :wrapped_pool]
4
-
5
- def initialize(options = {}, &block)
6
- @pool = options.fetch(:pool) { ::Bundler::ConnectionPool.new(options, &block) }
7
- end
8
-
9
- def wrapped_pool
10
- @pool
11
- end
12
-
13
- def with(&block)
14
- @pool.with(&block)
15
- end
16
-
17
- def pool_shutdown(&block)
18
- @pool.shutdown(&block)
19
- end
20
-
21
- def pool_size
22
- @pool.size
23
- end
24
-
25
- def pool_available
26
- @pool.available
27
- end
28
-
29
- def respond_to?(id, *args)
30
- METHODS.include?(id) || with { |c| c.respond_to?(id, *args) }
31
- end
32
-
33
- # rubocop:disable Style/MissingRespondToMissing
34
- if ::RUBY_VERSION >= "3.0.0"
35
- def method_missing(name, *args, **kwargs, &block)
36
- with do |connection|
37
- connection.send(name, *args, **kwargs, &block)
38
- end
39
- end
40
- elsif ::RUBY_VERSION >= "2.7.0"
41
- ruby2_keywords def method_missing(name, *args, &block)
42
- with do |connection|
43
- connection.send(name, *args, &block)
44
- end
45
- end
46
- else
47
- def method_missing(name, *args, &block)
48
- with do |connection|
49
- connection.send(name, *args, &block)
50
- end
51
- end
52
- end
53
- # rubocop:enable Style/MethodMissingSuper
54
- # rubocop:enable Style/MissingRespondToMissing
55
- end
56
- end
@@ -1,233 +0,0 @@
1
- require_relative "../../../vendored_timeout"
2
- require_relative "connection_pool/version"
3
-
4
- class Bundler::ConnectionPool
5
- class Error < ::RuntimeError; end
6
-
7
- class PoolShuttingDownError < ::Bundler::ConnectionPool::Error; end
8
-
9
- class TimeoutError < ::Gem::Timeout::Error; end
10
- end
11
-
12
- # Generic connection pool class for sharing a limited number of objects or network connections
13
- # among many threads. Note: pool elements are lazily created.
14
- #
15
- # Example usage with block (faster):
16
- #
17
- # @pool = Bundler::ConnectionPool.new { Redis.new }
18
- # @pool.with do |redis|
19
- # redis.lpop('my-list') if redis.llen('my-list') > 0
20
- # end
21
- #
22
- # Using optional timeout override (for that single invocation)
23
- #
24
- # @pool.with(timeout: 2.0) do |redis|
25
- # redis.lpop('my-list') if redis.llen('my-list') > 0
26
- # end
27
- #
28
- # Example usage replacing an existing connection (slower):
29
- #
30
- # $redis = Bundler::ConnectionPool.wrap { Redis.new }
31
- #
32
- # def do_work
33
- # $redis.lpop('my-list') if $redis.llen('my-list') > 0
34
- # end
35
- #
36
- # Accepts the following options:
37
- # - :size - number of connections to pool, defaults to 5
38
- # - :timeout - amount of time to wait for a connection if none currently available, defaults to 5 seconds
39
- # - :auto_reload_after_fork - automatically drop all connections after fork, defaults to true
40
- #
41
- class Bundler::ConnectionPool
42
- DEFAULTS = {size: 5, timeout: 5, auto_reload_after_fork: true}.freeze
43
-
44
- def self.wrap(options, &block)
45
- Wrapper.new(options, &block)
46
- end
47
-
48
- if Process.respond_to?(:fork)
49
- INSTANCES = ObjectSpace::WeakMap.new
50
- private_constant :INSTANCES
51
-
52
- def self.after_fork
53
- INSTANCES.values.each do |pool|
54
- next unless pool.auto_reload_after_fork
55
-
56
- # We're on after fork, so we know all other threads are dead.
57
- # All we need to do is to ensure the main thread doesn't have a
58
- # checked out connection
59
- pool.checkin(force: true)
60
- pool.reload do |connection|
61
- # Unfortunately we don't know what method to call to close the connection,
62
- # so we try the most common one.
63
- connection.close if connection.respond_to?(:close)
64
- end
65
- end
66
- nil
67
- end
68
-
69
- if ::Process.respond_to?(:_fork) # MRI 3.1+
70
- module ForkTracker
71
- def _fork
72
- pid = super
73
- if pid == 0
74
- Bundler::ConnectionPool.after_fork
75
- end
76
- pid
77
- end
78
- end
79
- Process.singleton_class.prepend(ForkTracker)
80
- end
81
- else
82
- INSTANCES = nil
83
- private_constant :INSTANCES
84
-
85
- def self.after_fork
86
- # noop
87
- end
88
- end
89
-
90
- def initialize(options = {}, &block)
91
- raise ArgumentError, "Connection pool requires a block" unless block
92
-
93
- options = DEFAULTS.merge(options)
94
-
95
- @size = Integer(options.fetch(:size))
96
- @timeout = options.fetch(:timeout)
97
- @auto_reload_after_fork = options.fetch(:auto_reload_after_fork)
98
-
99
- @available = TimedStack.new(@size, &block)
100
- @key = :"pool-#{@available.object_id}"
101
- @key_count = :"pool-#{@available.object_id}-count"
102
- @discard_key = :"pool-#{@available.object_id}-discard"
103
- INSTANCES[self] = self if @auto_reload_after_fork && INSTANCES
104
- end
105
-
106
- def with(options = {})
107
- # We need to manage exception handling manually here in order
108
- # to work correctly with `Gem::Timeout.timeout` and `Thread#raise`.
109
- # Otherwise an interrupted Thread can leak connections.
110
- Thread.handle_interrupt(Exception => :never) do
111
- conn = checkout(options)
112
- begin
113
- Thread.handle_interrupt(Exception => :immediate) do
114
- yield conn
115
- end
116
- ensure
117
- checkin
118
- end
119
- end
120
- end
121
- alias_method :then, :with
122
-
123
- ##
124
- # Marks the current thread's checked-out connection for discard.
125
- #
126
- # When a connection is marked for discard, it will not be returned to the pool
127
- # when checked in. Instead, the connection will be discarded.
128
- # This is useful when a connection has become invalid or corrupted
129
- # and should not be reused.
130
- #
131
- # Takes an optional block that will be called with the connection to be discarded.
132
- # The block should perform any necessary clean-up on the connection.
133
- #
134
- # @yield [conn]
135
- # @yieldparam conn [Object] The connection to be discarded.
136
- # @yieldreturn [void]
137
- #
138
- #
139
- # Note: This only affects the connection currently checked out by the calling thread.
140
- # The connection will be discarded when +checkin+ is called.
141
- #
142
- # @return [void]
143
- #
144
- # @example
145
- # pool.with do |conn|
146
- # begin
147
- # conn.execute("SELECT 1")
148
- # rescue SomeConnectionError
149
- # pool.discard_current_connection # Mark connection as bad
150
- # raise
151
- # end
152
- # end
153
- def discard_current_connection(&block)
154
- ::Thread.current[@discard_key] = block || proc { |conn| conn }
155
- end
156
-
157
- def checkout(options = {})
158
- if ::Thread.current[@key]
159
- ::Thread.current[@key_count] += 1
160
- ::Thread.current[@key]
161
- else
162
- ::Thread.current[@key_count] = 1
163
- ::Thread.current[@key] = @available.pop(options[:timeout] || @timeout, options)
164
- end
165
- end
166
-
167
- def checkin(force: false)
168
- if ::Thread.current[@key]
169
- if ::Thread.current[@key_count] == 1 || force
170
- if ::Thread.current[@discard_key]
171
- begin
172
- @available.decrement_created
173
- ::Thread.current[@discard_key].call(::Thread.current[@key])
174
- rescue
175
- nil
176
- ensure
177
- ::Thread.current[@discard_key] = nil
178
- end
179
- else
180
- @available.push(::Thread.current[@key])
181
- end
182
- ::Thread.current[@key] = nil
183
- ::Thread.current[@key_count] = nil
184
- else
185
- ::Thread.current[@key_count] -= 1
186
- end
187
- elsif !force
188
- raise Bundler::ConnectionPool::Error, "no connections are checked out"
189
- end
190
-
191
- nil
192
- end
193
-
194
- ##
195
- # Shuts down the Bundler::ConnectionPool by passing each connection to +block+ and
196
- # then removing it from the pool. Attempting to checkout a connection after
197
- # shutdown will raise +Bundler::ConnectionPool::PoolShuttingDownError+.
198
- def shutdown(&block)
199
- @available.shutdown(&block)
200
- end
201
-
202
- ##
203
- # Reloads the Bundler::ConnectionPool by passing each connection to +block+ and then
204
- # removing it the pool. Subsequent checkouts will create new connections as
205
- # needed.
206
- def reload(&block)
207
- @available.shutdown(reload: true, &block)
208
- end
209
-
210
- ## Reaps idle connections that have been idle for over +idle_seconds+.
211
- # +idle_seconds+ defaults to 60.
212
- def reap(idle_seconds = 60, &block)
213
- @available.reap(idle_seconds, &block)
214
- end
215
-
216
- # Size of this connection pool
217
- attr_reader :size
218
- # Automatically drop all connections after fork
219
- attr_reader :auto_reload_after_fork
220
-
221
- # Number of pool entries available for checkout at this instant.
222
- def available
223
- @available.length
224
- end
225
-
226
- # Number of pool entries created and idle in the pool.
227
- def idle
228
- @available.idle
229
- end
230
- end
231
-
232
- require_relative "connection_pool/timed_stack"
233
- require_relative "connection_pool/wrapper"
@@ -1,82 +0,0 @@
1
- = net-http-persistent
2
-
3
- home :: https://github.com/drbrain/net-http-persistent
4
- rdoc :: https://rubydoc.info/gems/net-http-persistent
5
-
6
- == DESCRIPTION:
7
-
8
- Manages persistent connections using Net::HTTP including a thread pool for
9
- connecting to multiple hosts.
10
-
11
- Using persistent HTTP connections can dramatically increase the speed of HTTP.
12
- Creating a new HTTP connection for every request involves an extra TCP
13
- round-trip and causes TCP congestion avoidance negotiation to start over.
14
-
15
- Net::HTTP supports persistent connections with some API methods but does not
16
- make setting up a single persistent connection or managing multiple
17
- connections easy. Net::HTTP::Persistent wraps Net::HTTP and allows you to
18
- focus on how to make HTTP requests.
19
-
20
- == FEATURES/PROBLEMS:
21
-
22
- * Supports TLS with secure defaults
23
- * Thread-safe
24
- * Pure ruby
25
-
26
- == SYNOPSIS
27
-
28
- The following example will make two requests to the same server. The
29
- connection is kept alive between requests:
30
-
31
- require 'net/http/persistent'
32
-
33
- uri = URI 'http://example.com/awesome/web/service'
34
-
35
- http = Net::HTTP::Persistent.new name: 'my_app_name'
36
-
37
- # perform a GET
38
- response = http.request uri
39
-
40
- # create a POST
41
- post_uri = uri + 'create'
42
- post = Net::HTTP::Post.new post_uri.path
43
- post.set_form_data 'some' => 'cool data'
44
-
45
- # perform the POST, the URI is always required
46
- response = http.request post_uri, post
47
-
48
- # if you are done making http requests, or won't make requests for several
49
- # minutes
50
- http.shutdown
51
-
52
- Please see the documentation on Net::HTTP::Persistent for more information,
53
- including SSL connection verification, header handling and tunable options.
54
-
55
- == INSTALL:
56
-
57
- gem install net-http-persistent
58
-
59
- == LICENSE:
60
-
61
- (The MIT License)
62
-
63
- Copyright (c) Eric Hodel, Aaron Patterson
64
-
65
- Permission is hereby granted, free of charge, to any person obtaining
66
- a copy of this software and associated documentation files (the
67
- 'Software'), to deal in the Software without restriction, including
68
- without limitation the rights to use, copy, modify, merge, publish,
69
- distribute, sublicense, and/or sell copies of the Software, and to
70
- permit persons to whom the Software is furnished to do so, subject to
71
- the following conditions:
72
-
73
- The above copyright notice and this permission notice shall be
74
- included in all copies or substantial portions of the Software.
75
-
76
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
77
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
78
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
79
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
80
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
81
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
82
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,41 +0,0 @@
1
- ##
2
- # A Gem::Net::HTTP connection wrapper that holds extra information for managing the
3
- # connection's lifetime.
4
-
5
- class Gem::Net::HTTP::Persistent::Connection # :nodoc:
6
-
7
- attr_accessor :http
8
-
9
- attr_accessor :last_use
10
-
11
- attr_accessor :requests
12
-
13
- attr_accessor :ssl_generation
14
-
15
- def initialize http_class, http_args, ssl_generation
16
- @http = http_class.new(*http_args)
17
- @ssl_generation = ssl_generation
18
-
19
- reset
20
- end
21
-
22
- def finish
23
- @http.finish
24
- rescue IOError
25
- ensure
26
- reset
27
- end
28
- alias_method :close, :finish
29
-
30
- def reset
31
- @last_use = Gem::Net::HTTP::Persistent::EPOCH
32
- @requests = 0
33
- end
34
-
35
- def ressl ssl_generation
36
- @ssl_generation = ssl_generation
37
-
38
- finish
39
- end
40
-
41
- end