bundler 4.0.21 → 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 (190) 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 +1 -2
  15. data/lib/bundler/cli/outdated.rb +8 -3
  16. data/lib/bundler/cli/pristine.rb +2 -1
  17. data/lib/bundler/cli/update.rb +21 -12
  18. data/lib/bundler/cli.rb +14 -11
  19. data/lib/bundler/definition.rb +61 -24
  20. data/lib/bundler/dependency.rb +4 -0
  21. data/lib/bundler/dsl.rb +77 -11
  22. data/lib/bundler/endpoint_specification.rb +51 -14
  23. data/lib/bundler/env.rb +7 -24
  24. data/lib/bundler/errors.rb +34 -5
  25. data/lib/bundler/fetcher/compact_index.rb +14 -5
  26. data/lib/bundler/fetcher/connection_pools.rb +150 -0
  27. data/lib/bundler/fetcher/downloader.rb +31 -16
  28. data/lib/bundler/fetcher.rb +8 -47
  29. data/lib/bundler/injector.rb +3 -3
  30. data/lib/bundler/inline.rb +44 -4
  31. data/lib/bundler/installer/parallel_installer.rb +25 -30
  32. data/lib/bundler/installer.rb +20 -6
  33. data/lib/bundler/lazy_specification.rb +44 -17
  34. data/lib/bundler/lockfile_generator.rb +24 -2
  35. data/lib/bundler/lockfile_parser.rb +43 -5
  36. data/lib/bundler/man/bundle-add.1 +7 -4
  37. data/lib/bundler/man/bundle-add.1.ronn +8 -4
  38. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  39. data/lib/bundler/man/bundle-cache.1 +2 -2
  40. data/lib/bundler/man/bundle-cache.1.ronn +2 -2
  41. data/lib/bundler/man/bundle-check.1 +1 -1
  42. data/lib/bundler/man/bundle-clean.1 +1 -1
  43. data/lib/bundler/man/bundle-config.1 +38 -6
  44. data/lib/bundler/man/bundle-config.1.ronn +143 -10
  45. data/lib/bundler/man/bundle-console.1 +1 -1
  46. data/lib/bundler/man/bundle-doctor.1 +1 -1
  47. data/lib/bundler/man/bundle-env.1 +1 -1
  48. data/lib/bundler/man/bundle-exec.1 +1 -1
  49. data/lib/bundler/man/bundle-fund.1 +1 -1
  50. data/lib/bundler/man/bundle-gem.1 +1 -1
  51. data/lib/bundler/man/bundle-help.1 +1 -1
  52. data/lib/bundler/man/bundle-info.1 +1 -1
  53. data/lib/bundler/man/bundle-init.1 +1 -1
  54. data/lib/bundler/man/bundle-install.1 +2 -2
  55. data/lib/bundler/man/bundle-install.1.ronn +4 -4
  56. data/lib/bundler/man/bundle-issue.1 +1 -1
  57. data/lib/bundler/man/bundle-licenses.1 +1 -1
  58. data/lib/bundler/man/bundle-list.1 +1 -1
  59. data/lib/bundler/man/bundle-lock.1 +3 -3
  60. data/lib/bundler/man/bundle-lock.1.ronn +5 -5
  61. data/lib/bundler/man/bundle-open.1 +1 -1
  62. data/lib/bundler/man/bundle-outdated.1 +1 -1
  63. data/lib/bundler/man/bundle-platform.1 +1 -1
  64. data/lib/bundler/man/bundle-plugin.1 +1 -1
  65. data/lib/bundler/man/bundle-pristine.1 +1 -1
  66. data/lib/bundler/man/bundle-remove.1 +1 -1
  67. data/lib/bundler/man/bundle-show.1 +1 -1
  68. data/lib/bundler/man/bundle-update.1 +3 -3
  69. data/lib/bundler/man/bundle-update.1.ronn +3 -5
  70. data/lib/bundler/man/bundle-version.1 +1 -1
  71. data/lib/bundler/man/bundle.1 +1 -1
  72. data/lib/bundler/man/gemfile.5 +45 -1
  73. data/lib/bundler/man/gemfile.5.ronn +53 -0
  74. data/lib/bundler/match_metadata.rb +20 -0
  75. data/lib/bundler/match_platform.rb +25 -2
  76. data/lib/bundler/match_remote_metadata.rb +21 -6
  77. data/lib/bundler/materialization.rb +2 -1
  78. data/lib/bundler/override.rb +69 -0
  79. data/lib/bundler/plugin/dsl.rb +3 -5
  80. data/lib/bundler/plugin/events.rb +55 -13
  81. data/lib/bundler/plugin/index.rb +87 -11
  82. data/lib/bundler/plugin/installer/path.rb +1 -1
  83. data/lib/bundler/plugin/installer.rb +13 -5
  84. data/lib/bundler/plugin.rb +58 -30
  85. data/lib/bundler/remote_specification.rb +6 -3
  86. data/lib/bundler/resolver/base.rb +2 -1
  87. data/lib/bundler/resolver/incompatibility.rb +1 -1
  88. data/lib/bundler/resolver.rb +73 -23
  89. data/lib/bundler/ruby_version.rb +0 -2
  90. data/lib/bundler/rubygems_ext.rb +71 -1
  91. data/lib/bundler/rubygems_gem_installer.rb +41 -2
  92. data/lib/bundler/rubygems_integration.rb +7 -2
  93. data/lib/bundler/runtime.rb +69 -2
  94. data/lib/bundler/self_manager.rb +9 -15
  95. data/lib/bundler/settings.rb +373 -30
  96. data/lib/bundler/shared_helpers.rb +2 -1
  97. data/lib/bundler/source/git/git_proxy.rb +2 -10
  98. data/lib/bundler/source/git.rb +15 -6
  99. data/lib/bundler/source/path/installer.rb +1 -1
  100. data/lib/bundler/source/rubygems/remote.rb +10 -5
  101. data/lib/bundler/source/rubygems.rb +48 -12
  102. data/lib/bundler/spec_set.rb +16 -4
  103. data/lib/bundler/stub_specification.rb +2 -1
  104. data/lib/bundler/templates/newgem/Gemfile.tt +4 -4
  105. data/lib/bundler/templates/newgem/newgem.gemspec.tt +3 -3
  106. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +1 -1
  107. data/lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt +1 -1
  108. data/lib/bundler/ui/shell.rb +0 -4
  109. data/lib/bundler/ui/silent.rb +0 -4
  110. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +35 -2
  111. data/lib/bundler/vendor/thor/lib/thor/base.rb +2 -1
  112. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +14 -6
  113. data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +2 -0
  114. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  115. data/lib/bundler/vendor/thor/lib/thor.rb +34 -1
  116. data/lib/bundler/vendored_pub_grub.rb +5 -2
  117. data/lib/bundler/vendored_securerandom.rb +11 -8
  118. data/lib/bundler/vendored_uri.rb +14 -14
  119. data/lib/bundler/version.rb +1 -1
  120. data/lib/bundler/worker.rb +3 -2
  121. data/lib/bundler.rb +1 -1
  122. data/lib/rubygems/compact_index_client/cache.rb +122 -0
  123. data/lib/rubygems/compact_index_client/cache_file.rb +147 -0
  124. data/lib/rubygems/compact_index_client/http_fetcher.rb +88 -0
  125. data/lib/rubygems/compact_index_client/parser.rb +90 -0
  126. data/lib/rubygems/compact_index_client/updater.rb +113 -0
  127. data/lib/rubygems/compact_index_client.rb +111 -0
  128. data/lib/rubygems/cooldown_settings.rb +57 -0
  129. data/lib/rubygems/credential_store/native/linux.rb +97 -0
  130. data/lib/rubygems/credential_store/native/macos.rb +88 -0
  131. data/lib/rubygems/credential_store/native/windows.rb +130 -0
  132. data/lib/rubygems/credential_store.rb +332 -0
  133. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/assignment.rb +1 -1
  134. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +7 -7
  135. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/failure_writer.rb +1 -1
  136. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/incompatibility.rb +4 -4
  137. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/package.rb +1 -1
  138. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/partial_solution.rb +1 -1
  139. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/rubygems.rb +3 -3
  140. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/solve_failure.rb +1 -1
  141. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/static_package_source.rb +3 -3
  142. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/strategy.rb +2 -2
  143. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/term.rb +1 -1
  144. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version.rb +1 -1
  145. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_constraint.rb +3 -3
  146. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_range.rb +1 -1
  147. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_solver.rb +2 -2
  148. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_union.rb +1 -1
  149. data/lib/rubygems/vendor/pub_grub/lib/pub_grub.rb +57 -0
  150. data/lib/{bundler → rubygems}/vendor/securerandom/lib/securerandom.rb +10 -6
  151. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/common.rb +119 -119
  152. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/file.rb +13 -13
  153. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ftp.rb +24 -24
  154. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/generic.rb +132 -132
  155. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/http.rb +18 -18
  156. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/https.rb +4 -4
  157. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ldap.rb +14 -14
  158. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ldaps.rb +4 -4
  159. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/mailto.rb +21 -21
  160. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/rfc2396_parser.rb +39 -39
  161. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/rfc3986_parser.rb +14 -14
  162. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/version.rb +1 -1
  163. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ws.rb +12 -12
  164. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/wss.rb +4 -4
  165. data/lib/{bundler → rubygems}/vendor/uri/lib/uri.rb +35 -31
  166. data/lib/rubygems/yaml_serializer.rb +880 -0
  167. metadata +77 -68
  168. data/CHANGELOG.md +0 -5784
  169. data/LICENSE.md +0 -22
  170. data/README.md +0 -58
  171. data/lib/bundler/compact_index_client/cache.rb +0 -107
  172. data/lib/bundler/compact_index_client/cache_file.rb +0 -148
  173. data/lib/bundler/compact_index_client/parser.rb +0 -87
  174. data/lib/bundler/compact_index_client/updater.rb +0 -105
  175. data/lib/bundler/compact_index_client.rb +0 -92
  176. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +0 -227
  177. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +0 -3
  178. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +0 -56
  179. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +0 -230
  180. data/lib/bundler/vendor/net-http-persistent/README.rdoc +0 -82
  181. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb +0 -41
  182. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb +0 -65
  183. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb +0 -80
  184. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +0 -1153
  185. data/lib/bundler/vendor/pub_grub/lib/pub_grub.rb +0 -31
  186. data/lib/bundler/vendored_persistent.rb +0 -11
  187. data/lib/bundler/yaml_serializer.rb +0 -98
  188. /data/lib/{bundler → rubygems}/vendor/pub_grub/LICENSE.txt +0 -0
  189. /data/lib/{bundler → rubygems}/vendor/securerandom/COPYING +0 -0
  190. /data/lib/{bundler → rubygems}/vendor/uri/COPYING +0 -0
@@ -1,227 +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
- # +:timeout+ is the only checked entry in +options+ and is preferred over
58
- # the +timeout+ argument (which will be removed in a future release). Other
59
- # options may be used by subclasses that extend TimedStack.
60
- def pop(timeout = 0.5, options = {})
61
- options, timeout = timeout, 0.5 if Hash === timeout
62
- timeout = options.fetch :timeout, timeout
63
-
64
- deadline = current_time + timeout
65
- @mutex.synchronize do
66
- loop do
67
- raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block
68
- if (conn = try_fetch_connection(options))
69
- return conn
70
- end
71
-
72
- connection = try_create(options)
73
- return connection if connection
74
-
75
- to_wait = deadline - current_time
76
- raise Bundler::ConnectionPool::TimeoutError, "Waited #{timeout} sec, #{length}/#{@max} available" if to_wait <= 0
77
- @resource.wait(@mutex, to_wait)
78
- end
79
- end
80
- end
81
-
82
- ##
83
- # Shuts down the TimedStack by passing each connection to +block+ and then
84
- # removing it from the pool. Attempting to checkout a connection after
85
- # shutdown will raise +Bundler::ConnectionPool::PoolShuttingDownError+ unless
86
- # +:reload+ is +true+.
87
- def shutdown(reload: false, &block)
88
- raise ArgumentError, "shutdown must receive a block" unless block
89
-
90
- @mutex.synchronize do
91
- @shutdown_block = block
92
- @resource.broadcast
93
-
94
- shutdown_connections
95
- @shutdown_block = nil if reload
96
- end
97
- end
98
-
99
- ##
100
- # Reaps connections that were checked in more than +idle_seconds+ ago.
101
- def reap(idle_seconds, &block)
102
- raise ArgumentError, "reap must receive a block" unless block
103
- raise ArgumentError, "idle_seconds must be a number" unless idle_seconds.is_a?(Numeric)
104
- raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block
105
-
106
- idle.times do
107
- conn =
108
- @mutex.synchronize do
109
- raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block
110
-
111
- reserve_idle_connection(idle_seconds)
112
- end
113
- break unless conn
114
-
115
- block.call(conn)
116
- end
117
- end
118
-
119
- ##
120
- # Returns +true+ if there are no available connections.
121
- def empty?
122
- (@created - @que.length) >= @max
123
- end
124
-
125
- ##
126
- # The number of connections available on the stack.
127
- def length
128
- @max - @created + @que.length
129
- end
130
-
131
- ##
132
- # The number of connections created and available on the stack.
133
- def idle
134
- @que.length
135
- end
136
-
137
- ##
138
- # Reduce the created count
139
- def decrement_created
140
- @created -= 1 unless @created == 0
141
- end
142
-
143
- private
144
-
145
- def current_time
146
- Process.clock_gettime(Process::CLOCK_MONOTONIC)
147
- end
148
-
149
- ##
150
- # This is an extension point for TimedStack and is called with a mutex.
151
- #
152
- # This method must returns a connection from the stack if one exists. Allows
153
- # subclasses with expensive match/search algorithms to avoid double-handling
154
- # their stack.
155
- def try_fetch_connection(options = nil)
156
- connection_stored?(options) && fetch_connection(options)
157
- end
158
-
159
- ##
160
- # This is an extension point for TimedStack and is called with a mutex.
161
- #
162
- # This method must returns true if a connection is available on the stack.
163
- def connection_stored?(options = nil)
164
- !@que.empty?
165
- end
166
-
167
- ##
168
- # This is an extension point for TimedStack and is called with a mutex.
169
- #
170
- # This method must return a connection from the stack.
171
- def fetch_connection(options = nil)
172
- @que.pop&.first
173
- end
174
-
175
- ##
176
- # This is an extension point for TimedStack and is called with a mutex.
177
- #
178
- # This method must shut down all connections on the stack.
179
- def shutdown_connections(options = nil)
180
- while (conn = try_fetch_connection(options))
181
- @created -= 1 unless @created == 0
182
- @shutdown_block.call(conn)
183
- end
184
- end
185
-
186
- ##
187
- # This is an extension point for TimedStack and is called with a mutex.
188
- #
189
- # This method returns the oldest idle connection if it has been idle for more than idle_seconds.
190
- # This requires that the stack is kept in order of checked in time (oldest first).
191
- def reserve_idle_connection(idle_seconds)
192
- return unless idle_connections?(idle_seconds)
193
-
194
- @created -= 1 unless @created == 0
195
-
196
- @que.shift.first
197
- end
198
-
199
- ##
200
- # This is an extension point for TimedStack and is called with a mutex.
201
- #
202
- # Returns true if the first connection in the stack has been idle for more than idle_seconds
203
- def idle_connections?(idle_seconds)
204
- connection_stored? && (current_time - @que.first.last > idle_seconds)
205
- end
206
-
207
- ##
208
- # This is an extension point for TimedStack and is called with a mutex.
209
- #
210
- # This method must return +obj+ to the stack.
211
- def store_connection(obj, options = nil)
212
- @que.push [obj, current_time]
213
- end
214
-
215
- ##
216
- # This is an extension point for TimedStack and is called with a mutex.
217
- #
218
- # This method must create a connection if and only if the total number of
219
- # connections allowed has not been met.
220
- def try_create(options = nil)
221
- unless @created == @max
222
- object = @create_block.call
223
- @created += 1
224
- object
225
- end
226
- end
227
- end
@@ -1,3 +0,0 @@
1
- class Bundler::ConnectionPool
2
- VERSION = "2.5.4"
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,230 +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
- Thread.handle_interrupt(Exception => :never) do
108
- conn = checkout(options)
109
- begin
110
- Thread.handle_interrupt(Exception => :immediate) do
111
- yield conn
112
- end
113
- ensure
114
- checkin
115
- end
116
- end
117
- end
118
- alias_method :then, :with
119
-
120
- ##
121
- # Marks the current thread's checked-out connection for discard.
122
- #
123
- # When a connection is marked for discard, it will not be returned to the pool
124
- # when checked in. Instead, the connection will be discarded.
125
- # This is useful when a connection has become invalid or corrupted
126
- # and should not be reused.
127
- #
128
- # Takes an optional block that will be called with the connection to be discarded.
129
- # The block should perform any necessary clean-up on the connection.
130
- #
131
- # @yield [conn]
132
- # @yieldparam conn [Object] The connection to be discarded.
133
- # @yieldreturn [void]
134
- #
135
- #
136
- # Note: This only affects the connection currently checked out by the calling thread.
137
- # The connection will be discarded when +checkin+ is called.
138
- #
139
- # @return [void]
140
- #
141
- # @example
142
- # pool.with do |conn|
143
- # begin
144
- # conn.execute("SELECT 1")
145
- # rescue SomeConnectionError
146
- # pool.discard_current_connection # Mark connection as bad
147
- # raise
148
- # end
149
- # end
150
- def discard_current_connection(&block)
151
- ::Thread.current[@discard_key] = block || proc { |conn| conn }
152
- end
153
-
154
- def checkout(options = {})
155
- if ::Thread.current[@key]
156
- ::Thread.current[@key_count] += 1
157
- ::Thread.current[@key]
158
- else
159
- ::Thread.current[@key_count] = 1
160
- ::Thread.current[@key] = @available.pop(options[:timeout] || @timeout, options)
161
- end
162
- end
163
-
164
- def checkin(force: false)
165
- if ::Thread.current[@key]
166
- if ::Thread.current[@key_count] == 1 || force
167
- if ::Thread.current[@discard_key]
168
- begin
169
- @available.decrement_created
170
- ::Thread.current[@discard_key].call(::Thread.current[@key])
171
- rescue
172
- nil
173
- ensure
174
- ::Thread.current[@discard_key] = nil
175
- end
176
- else
177
- @available.push(::Thread.current[@key])
178
- end
179
- ::Thread.current[@key] = nil
180
- ::Thread.current[@key_count] = nil
181
- else
182
- ::Thread.current[@key_count] -= 1
183
- end
184
- elsif !force
185
- raise Bundler::ConnectionPool::Error, "no connections are checked out"
186
- end
187
-
188
- nil
189
- end
190
-
191
- ##
192
- # Shuts down the Bundler::ConnectionPool by passing each connection to +block+ and
193
- # then removing it from the pool. Attempting to checkout a connection after
194
- # shutdown will raise +Bundler::ConnectionPool::PoolShuttingDownError+.
195
- def shutdown(&block)
196
- @available.shutdown(&block)
197
- end
198
-
199
- ##
200
- # Reloads the Bundler::ConnectionPool by passing each connection to +block+ and then
201
- # removing it the pool. Subsequent checkouts will create new connections as
202
- # needed.
203
- def reload(&block)
204
- @available.shutdown(reload: true, &block)
205
- end
206
-
207
- ## Reaps idle connections that have been idle for over +idle_seconds+.
208
- # +idle_seconds+ defaults to 60.
209
- def reap(idle_seconds = 60, &block)
210
- @available.reap(idle_seconds, &block)
211
- end
212
-
213
- # Size of this connection pool
214
- attr_reader :size
215
- # Automatically drop all connections after fork
216
- attr_reader :auto_reload_after_fork
217
-
218
- # Number of pool entries available for checkout at this instant.
219
- def available
220
- @available.length
221
- end
222
-
223
- # Number of pool entries created and idle in the pool.
224
- def idle
225
- @available.idle
226
- end
227
- end
228
-
229
- require_relative "connection_pool/timed_stack"
230
- 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
@@ -1,65 +0,0 @@
1
- class Gem::Net::HTTP::Persistent::Pool < Bundler::ConnectionPool # :nodoc:
2
-
3
- attr_reader :available # :nodoc:
4
- attr_reader :key # :nodoc:
5
-
6
- def initialize(options = {}, &block)
7
- super
8
-
9
- @available = Gem::Net::HTTP::Persistent::TimedStackMulti.new(@size, &block)
10
- @key = "current-#{@available.object_id}"
11
- end
12
-
13
- def checkin net_http_args
14
- if net_http_args.is_a?(Hash) && net_http_args.size == 1 && net_http_args[:force]
15
- # Bundler::ConnectionPool 2.4+ calls `checkin(force: true)` after fork.
16
- # When this happens, we should remove all connections from Thread.current
17
- if stacks = Thread.current[@key]
18
- stacks.each do |http_args, connections|
19
- connections.each do |conn|
20
- @available.push conn, connection_args: http_args
21
- end
22
- connections.clear
23
- end
24
- end
25
- else
26
- stack = Thread.current[@key][net_http_args] ||= []
27
-
28
- raise Bundler::ConnectionPool::Error, 'no connections are checked out' if
29
- stack.empty?
30
-
31
- conn = stack.pop
32
-
33
- if stack.empty?
34
- @available.push conn, connection_args: net_http_args
35
-
36
- Thread.current[@key].delete(net_http_args)
37
- Thread.current[@key] = nil if Thread.current[@key].empty?
38
- end
39
- end
40
- nil
41
- end
42
-
43
- def checkout net_http_args
44
- stacks = Thread.current[@key] ||= {}
45
- stack = stacks[net_http_args] ||= []
46
-
47
- if stack.empty? then
48
- conn = @available.pop connection_args: net_http_args
49
- else
50
- conn = stack.last
51
- end
52
-
53
- stack.push conn
54
-
55
- conn
56
- end
57
-
58
- def shutdown
59
- Thread.current[@key] = nil
60
- super
61
- end
62
- end
63
-
64
- require_relative 'timed_stack_multi'
65
-