Skip to content

Commit 879327c

Browse files
chore: sdk client internal refactoring (#21)
1 parent 02e8b1f commit 879327c

14 files changed

+83
-84
lines changed

lib/openai/base_client.rb

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,20 @@ def follow_redirect(request, status:, response_headers:)
124124

125125
request
126126
end
127+
128+
# @api private
129+
#
130+
# @param status [Integer, OpenAI::APIConnectionError]
131+
# @param stream [Enumerable, nil]
132+
def reap_connection!(status, stream:)
133+
case status
134+
in (..199) | (300..499)
135+
stream&.each { next }
136+
in OpenAI::APIConnectionError | (500..)
137+
OpenAI::Util.close_fused!(stream)
138+
else
139+
end
140+
end
127141
end
128142

129143
# @api private
@@ -321,28 +335,23 @@ def initialize(
321335
end
322336

323337
begin
324-
response, stream = @requester.execute(input)
325-
status = Integer(response.code)
338+
status, response, stream = @requester.execute(input)
326339
rescue OpenAI::APIConnectionError => e
327340
status = e
328341
end
329342

330-
# normally we want to drain the response body and reuse the HTTP session by clearing the socket buffers
331-
# unless we hit a server error
332-
srv_fault = (500...).include?(status)
333-
334343
case status
335344
in ..299
336345
[status, response, stream]
337346
in 300..399 if redirect_count >= self.class::MAX_REDIRECTS
338-
message = "Failed to complete the request within #{self.class::MAX_REDIRECTS} redirects."
347+
self.class.reap_connection!(status, stream: stream)
339348

340-
stream.each { next }
349+
message = "Failed to complete the request within #{self.class::MAX_REDIRECTS} redirects."
341350
raise OpenAI::APIConnectionError.new(url: url, message: message)
342351
in 300..399
343-
request = self.class.follow_redirect(request, status: status, response_headers: response)
352+
self.class.reap_connection!(status, stream: stream)
344353

345-
stream.each { next }
354+
request = self.class.follow_redirect(request, status: status, response_headers: response)
346355
send_request(
347356
request,
348357
redirect_count: redirect_count + 1,
@@ -352,12 +361,10 @@ def initialize(
352361
in OpenAI::APIConnectionError if retry_count >= max_retries
353362
raise status
354363
in (400..) if retry_count >= max_retries || !self.class.should_retry?(status, headers: response)
355-
decoded = OpenAI::Util.decode_content(response, stream: stream, suppress_error: true)
356-
357-
if srv_fault
358-
OpenAI::Util.close_fused!(stream)
359-
else
360-
stream.each { next }
364+
decoded = Kernel.then do
365+
OpenAI::Util.decode_content(response, stream: stream, suppress_error: true)
366+
ensure
367+
self.class.reap_connection!(status, stream: stream)
361368
end
362369

363370
raise OpenAI::APIStatusError.for(
@@ -368,13 +375,9 @@ def initialize(
368375
response: response
369376
)
370377
in (400..) | OpenAI::APIConnectionError
371-
delay = retry_delay(response, retry_count: retry_count)
378+
self.class.reap_connection!(status, stream: stream)
372379

373-
if srv_fault
374-
OpenAI::Util.close_fused!(stream)
375-
else
376-
stream&.each { next }
377-
end
380+
delay = retry_delay(response, retry_count: retry_count)
378381
sleep(delay)
379382

380383
send_request(

lib/openai/cursor_page.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ def next_page?
6868
# @return [OpenAI::CursorPage]
6969
def next_page
7070
unless next_page?
71-
raise RuntimeError.new("No more pages available. Please check #next_page? before calling ##{__method__}")
71+
message = "No more pages available. Please check #next_page? before calling ##{__method__}"
72+
raise RuntimeError.new(message)
7273
end
7374

7475
req = OpenAI::Util.deep_merge(@req, {query: {after: data&.last&.id}})

lib/openai/pooled_net_requester.rb

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ def build_request(request, &)
6161

6262
case body
6363
in nil
64+
nil
6465
in String
6566
req["content-length"] ||= body.bytesize.to_s unless req["transfer-encoding"]
6667
req.body_stream = OpenAI::Util::ReadIOAdapter.new(body, &)
@@ -79,17 +80,19 @@ def build_request(request, &)
7980
# @api private
8081
#
8182
# @param url [URI::Generic]
83+
# @param deadline [Float]
8284
# @param blk [Proc]
83-
private def with_pool(url, &)
85+
private def with_pool(url, deadline:, &blk)
8486
origin = OpenAI::Util.uri_origin(url)
87+
timeout = deadline - OpenAI::Util.monotonic_secs
8588
pool =
8689
@mutex.synchronize do
8790
@pools[origin] ||= ConnectionPool.new(size: @size) do
8891
self.class.connect(url)
8992
end
9093
end
9194

92-
pool.with(&)
95+
pool.with(timeout: timeout, &blk)
9396
end
9497

9598
# @api private
@@ -106,14 +109,14 @@ def build_request(request, &)
106109
#
107110
# @option request [Float] :deadline
108111
#
109-
# @return [Array(Net::HTTPResponse, Enumerable)]
112+
# @return [Array(Integer, Net::HTTPResponse, Enumerable)]
110113
def execute(request)
111114
url, deadline = request.fetch_values(:url, :deadline)
112115

113116
eof = false
114117
finished = false
115118
enum = Enumerator.new do |y|
116-
with_pool(url) do |conn|
119+
with_pool(url, deadline: deadline) do |conn|
117120
next if finished
118121

119122
req = self.class.build_request(request) do
@@ -125,7 +128,7 @@ def execute(request)
125128

126129
self.class.calibrate_socket_timeout(conn, deadline)
127130
conn.request(req) do |rsp|
128-
y << [conn, rsp]
131+
y << [conn, req, rsp]
129132
break if finished
130133

131134
rsp.read_body do |bytes|
@@ -137,9 +140,11 @@ def execute(request)
137140
eof = true
138141
end
139142
end
143+
rescue Timeout::Error
144+
raise OpenAI::APITimeoutError
140145
end
141146

142-
conn, response = enum.next
147+
conn, _, response = enum.next
143148
body = OpenAI::Util.fused_enum(enum, external: true) do
144149
finished = true
145150
tap do
@@ -149,7 +154,7 @@ def execute(request)
149154
end
150155
conn.finish if !eof && conn&.started?
151156
end
152-
[response, (response.body = body)]
157+
[Integer(response.code), response, (response.body = body)]
153158
end
154159

155160
# @api private

lib/openai/util.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class << self
5757
#
5858
# @param input [Object]
5959
#
60-
# @return [Boolean, Object]
60+
# @return [Boolean]
6161
def primitive?(input)
6262
case input
6363
in true | false | Integer | Float | Symbol | String
@@ -627,6 +627,8 @@ def close_fused!(enum)
627627
#
628628
# @param enum [Enumerable, nil]
629629
# @param blk [Proc]
630+
#
631+
# @return [Enumerable]
630632
def chain_fused(enum, &blk)
631633
iter = Enumerator.new { blk.call(_1) }
632634
fused_enum(iter) { close_fused!(enum) }

rbi/lib/openai/base_client.rbi

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,16 @@ module OpenAI
6767
end
6868
def follow_redirect(request, status:, response_headers:)
6969
end
70+
71+
# @api private
72+
sig do
73+
params(
74+
status: T.any(Integer, OpenAI::APIConnectionError),
75+
stream: T.nilable(T::Enumerable[String])
76+
).void
77+
end
78+
def reap_connection!(status, stream:)
79+
end
7080
end
7181

7282
sig { returns(T.anything) }

rbi/lib/openai/base_model.rbi

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ module OpenAI
228228
# @api private
229229
#
230230
# All of the specified variant info for this union.
231-
sig { returns(T::Array[[T.nilable(Symbol), Proc]]) }
231+
sig { returns(T::Array[[T.nilable(Symbol), T.proc.returns(Variants)]]) }
232232
private def known_variants
233233
end
234234

@@ -250,25 +250,16 @@ module OpenAI
250250
# @api private
251251
sig do
252252
params(
253-
key: T.any(
254-
Symbol,
255-
T::Hash[Symbol, T.anything],
256-
T.proc.returns(OpenAI::Converter::Input),
257-
OpenAI::Converter::Input
258-
),
259-
spec: T.any(
260-
T::Hash[Symbol, T.anything],
261-
T.proc.returns(OpenAI::Converter::Input),
262-
OpenAI::Converter::Input
263-
)
253+
key: T.any(Symbol, T::Hash[Symbol, T.anything], T.proc.returns(Variants), Variants),
254+
spec: T.any(T::Hash[Symbol, T.anything], T.proc.returns(Variants), Variants)
264255
)
265256
.void
266257
end
267258
private def variant(key, spec = nil)
268259
end
269260

270261
# @api private
271-
sig { params(value: T.anything).returns(T.nilable(OpenAI::Converter::Input)) }
262+
sig { params(value: T.anything).returns(T.nilable(Variants)) }
272263
private def resolve_variant(value)
273264
end
274265
end

rbi/lib/openai/pooled_net_requester.rbi

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ module OpenAI
2727
end
2828

2929
# @api private
30-
sig { params(url: URI::Generic, blk: T.proc.params(arg0: Net::HTTP).void).void }
31-
private def with_pool(url, &blk)
30+
sig { params(url: URI::Generic, deadline: Float, blk: T.proc.params(arg0: Net::HTTP).void).void }
31+
private def with_pool(url, deadline:, &blk)
3232
end
3333

3434
# @api private
3535
sig do
3636
params(request: OpenAI::PooledNetRequester::RequestShape)
37-
.returns([Net::HTTPResponse, T::Enumerable[String]])
37+
.returns([Integer, Net::HTTPResponse, T::Enumerable[String]])
3838
end
3939
def execute(request)
4040
end

rbi/lib/openai/util.rbi

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ module OpenAI
2222

2323
class << self
2424
# @api private
25-
sig { params(input: T.anything).returns(T.any(T::Boolean, T.anything)) }
25+
sig { params(input: T.anything).returns(T::Boolean) }
2626
def primitive?(input)
2727
end
2828

@@ -239,10 +239,8 @@ module OpenAI
239239

240240
# @api private
241241
sig do
242-
params(
243-
enum: T.nilable(T::Enumerable[T.anything]),
244-
blk: T.proc.params(arg0: Enumerator::Yielder).void
245-
).void
242+
params(enum: T.nilable(T::Enumerable[T.anything]), blk: T.proc.params(arg0: Enumerator::Yielder).void)
243+
.returns(T::Enumerable[T.anything])
246244
end
247245
def chain_fused(enum, &blk)
248246
end

sig/openai/base_client.rbs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ module OpenAI
4343
response_headers: ::Hash[String, String]
4444
) -> OpenAI::BaseClient::request_input
4545

46+
def self.reap_connection!: (
47+
Integer | OpenAI::APIConnectionError status,
48+
stream: Enumerable[String]?
49+
) -> void
50+
4651
# @api private
4752
attr_accessor requester: top
4853

sig/openai/base_model.rbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ module OpenAI
8585
class Union
8686
extend OpenAI::Converter
8787

88-
private def self.known_variants: -> ::Array[[Symbol?, Proc]]
88+
private def self.known_variants: -> ::Array[[Symbol?, (^-> OpenAI::Converter::input)]]
8989

9090
def self.derefed_variants: -> ::Array[[Symbol?, top]]
9191

0 commit comments

Comments
 (0)