Skip to content

Commit b957278

Browse files
fix: coroutine leaks from connection pool
1 parent 4b79b41 commit b957278

File tree

2 files changed

+32
-10
lines changed

2 files changed

+32
-10
lines changed

lib/scrapegraphai/internal/transport/pooled_net_requester.rb

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,9 @@ def execute(request)
134134

135135
# rubocop:disable Metrics/BlockLength
136136
enum = Enumerator.new do |y|
137-
with_pool(url, deadline: deadline) do |conn|
138-
next if finished
137+
next if finished
139138

139+
with_pool(url, deadline: deadline) do |conn|
140140
req, closing = self.class.build_request(request) do
141141
self.class.calibrate_socket_timeout(conn, deadline)
142142
end
@@ -149,7 +149,7 @@ def execute(request)
149149

150150
self.class.calibrate_socket_timeout(conn, deadline)
151151
conn.request(req) do |rsp|
152-
y << [conn, req, rsp]
152+
y << [req, rsp]
153153
break if finished
154154

155155
rsp.read_body do |bytes|
@@ -160,6 +160,8 @@ def execute(request)
160160
end
161161
eof = true
162162
end
163+
ensure
164+
conn.finish if !eof && conn&.started?
163165
end
164166
rescue Timeout::Error
165167
raise Scrapegraphai::Errors::APITimeoutError.new(url: url, request: req)
@@ -168,16 +170,11 @@ def execute(request)
168170
end
169171
# rubocop:enable Metrics/BlockLength
170172

171-
conn, _, response = enum.next
173+
_, response = enum.next
172174
body = Scrapegraphai::Internal::Util.fused_enum(enum, external: true) do
173175
finished = true
174-
tap do
175-
enum.next
176-
rescue StopIteration
177-
nil
178-
end
176+
loop { enum.next }
179177
ensure
180-
conn.finish if !eof && conn&.started?
181178
closing&.call
182179
end
183180
[Integer(response.code), response, body]

test/scrapegraphai/internal/util_test.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,31 @@ def test_copy_write
310310
end
311311

312312
class Scrapegraphai::Test::UtilFusedEnumTest < Minitest::Test
313+
def test_rewind_closing
314+
touched = false
315+
once = 0
316+
steps = 0
317+
enum = Enumerator.new do |y|
318+
next if touched
319+
320+
10.times do
321+
steps = _1
322+
y << _1
323+
end
324+
ensure
325+
once = once.succ
326+
end
327+
328+
fused = Scrapegraphai::Internal::Util.fused_enum(enum, external: true) do
329+
touched = true
330+
loop { enum.next }
331+
end
332+
Scrapegraphai::Internal::Util.close_fused!(fused)
333+
334+
assert_equal(1, once)
335+
assert_equal(0, steps)
336+
end
337+
313338
def test_closing
314339
arr = [1, 2, 3]
315340
once = 0

0 commit comments

Comments
 (0)