Class: Quicsilver::Client::Request

Inherits:
Object
  • Object
show all
Defined in:
lib/quicsilver/client/request.rb

Defined Under Namespace

Classes: ResetError

Constant Summary collapse

CancelledError =
Class.new(StandardError)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client, stream) ⇒ Request

Returns a new instance of Request.



19
20
21
22
23
24
25
26
# File 'lib/quicsilver/client/request.rb', line 19

def initialize(client, stream)
  @client = client
  @stream = stream
  @status = :pending
  @queue = Queue.new
  @mutex = Mutex.new
  @response = nil
end

Instance Attribute Details

#statusObject (readonly)

Returns the value of attribute status.



6
7
8
# File 'lib/quicsilver/client/request.rb', line 6

def status
  @status
end

#streamObject (readonly)

Returns the value of attribute stream.



6
7
8
# File 'lib/quicsilver/client/request.rb', line 6

def stream
  @stream
end

Instance Method Details

#cancel(error_code: Protocol::H3_REQUEST_CANCELLED) ⇒ Object

Cancel the request (sends RESET_STREAM + STOP_SENDING to server) error_code defaults to H3_REQUEST_CANCELLED (0x10c)



57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/quicsilver/client/request.rb', line 57

def cancel(error_code: Protocol::H3_REQUEST_CANCELLED)
  @mutex.synchronize do
    return false unless @status == :pending

    @stream.reset(error_code)
    @stream.stop_sending(error_code)
    @status = :cancelled
  end
  true
rescue => e
  Quicsilver.logger.error("Failed to cancel request: #{e.message}")
  false
end

#cancelled?Boolean

Returns:

  • (Boolean)


79
80
81
# File 'lib/quicsilver/client/request.rb', line 79

def cancelled?
  @status == :cancelled
end

#complete(response) ⇒ Object

Called by Client when response arrives



84
85
86
# File 'lib/quicsilver/client/request.rb', line 84

def complete(response) # :nodoc:
  @queue.push(response)
end

#completed?Boolean

Returns:

  • (Boolean)


75
76
77
# File 'lib/quicsilver/client/request.rb', line 75

def completed?
  @status == :completed
end

#fail(error_code, message = nil) ⇒ Object

Called by Client on stream reset from peer or connection close



89
90
91
92
93
94
95
# File 'lib/quicsilver/client/request.rb', line 89

def fail(error_code, message = nil) # :nodoc:
  @mutex.synchronize do
    return if @status == :cancelled
    @status = :error
  end
  @queue.push({ error: true, error_code: error_code, message: message })
end

#pending?Boolean

Returns:

  • (Boolean)


71
72
73
# File 'lib/quicsilver/client/request.rb', line 71

def pending?
  @status == :pending
end

#response(timeout: nil) ⇒ Object

Block until response arrives or timeout Returns response hash { status:, headers:, body: } Raises TimeoutError, CancelledError, or ResetError



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/quicsilver/client/request.rb', line 31

def response(timeout: nil)
  timeout ||= @client.request_timeout
  return @response if @status == :completed

  result = @queue.pop(timeout: timeout)

  @mutex.synchronize do
    case result
    when nil
      raise Quicsilver::TimeoutError, "Request timeout after #{timeout}s"
    when Hash
      if result[:error]
        @status = :error
        raise ResetError.new(result[:message] || "Stream reset by peer", result[:error_code])
      else
        @status = :completed
        @response = result
      end
    end
  end

  @response
end