Class: Freeswitch::ESL::Connection::CommandRequest

Inherits:
Object
  • Object
show all
Defined in:
lib/freeswitch/esl/connection/command_request.rb

Overview

Represents a pending command execution waiting for a response.

Created before sending a command to the socket; the response is delivered asynchronously by the command dispatcher via #process_reply, #process_error or #disconnected!.

Handles timeout: if the caller exceeds the deadline, #wait raises TimeoutError and marks the execution as expired. A late-arriving response is silently discarded (callback not invoked), keeping the command queue in sync with the wire protocol.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(command, timeout = nil) ⇒ CommandRequest

Returns a new instance of CommandRequest.



19
20
21
22
23
24
25
26
27
28
29
# File 'lib/freeswitch/esl/connection/command_request.rb', line 19

def initialize(command, timeout = nil)
  @command = command
  @mutex = Mutex.new
  @condition = ConditionVariable.new
  @response = nil
  @status = :queued
  @created_at = Time.now
  @sent_at = nil
  @finished_at = nil
  @timeout = timeout
end

Instance Attribute Details

#commandObject (readonly)

Returns the value of attribute command.



17
18
19
# File 'lib/freeswitch/esl/connection/command_request.rb', line 17

def command
  @command
end

#created_atObject (readonly)

Returns the value of attribute created_at.



17
18
19
# File 'lib/freeswitch/esl/connection/command_request.rb', line 17

def created_at
  @created_at
end

#finished_atObject (readonly)

Returns the value of attribute finished_at.



17
18
19
# File 'lib/freeswitch/esl/connection/command_request.rb', line 17

def finished_at
  @finished_at
end

#sent_atObject (readonly)

Returns the value of attribute sent_at.



17
18
19
# File 'lib/freeswitch/esl/connection/command_request.rb', line 17

def sent_at
  @sent_at
end

#statusObject (readonly)

Returns the value of attribute status.



17
18
19
# File 'lib/freeswitch/esl/connection/command_request.rb', line 17

def status
  @status
end

Instance Method Details

#disconnected!(error) ⇒ Object



69
70
71
72
73
74
75
76
77
78
# File 'lib/freeswitch/esl/connection/command_request.rb', line 69

def disconnected!(error)
  @mutex.synchronize do
    return if terminated? # already completed/failed/timeout

    @error = error
    @status = :disconnected
    @finished_at = Time.now
    @condition.signal
  end
end

#errorObject

Return the terminal error, blocking without raising so callers can branch on the request outcome after completion.



90
91
92
93
94
# File 'lib/freeswitch/esl/connection/command_request.rb', line 90

def error
  wait(raise_error: false) unless terminated?

  @error
end

#ok?Boolean

Returns:

  • (Boolean)


31
32
33
# File 'lib/freeswitch/esl/connection/command_request.rb', line 31

def ok?
  @status == :completed
end

#process_error(error) ⇒ Object



58
59
60
61
62
63
64
65
66
67
# File 'lib/freeswitch/esl/connection/command_request.rb', line 58

def process_error(error)
  @mutex.synchronize do
    return if terminated?

    @error = error
    @status = :failed
    @finished_at = Time.now
    @condition.signal
  end
end

#process_reply(reply) ⇒ Object

Called by reader thread to deliver the response message or exception. No-op if the execution has already expired due to timeout.



46
47
48
49
50
51
52
53
54
55
56
# File 'lib/freeswitch/esl/connection/command_request.rb', line 46

def process_reply(reply)
  return if terminated?

  @mutex.synchronize do
    @response = reply
    @status = reply.successful? ? :completed : :failed
    @error = reply.successful? ? nil : CommandError.new(failed_reply_error_message(reply))
    @condition.signal
    @finished_at = Time.now
  end
end

#responseObject

Return the terminal reply, blocking without raising so callers can inspect failures through #error instead of exceptions.



82
83
84
85
86
# File 'lib/freeswitch/esl/connection/command_request.rb', line 82

def response
  wait(raise_error: false) unless terminated?

  @response
end

#sent!Object



35
36
37
38
39
40
41
42
# File 'lib/freeswitch/esl/connection/command_request.rb', line 35

def sent!
  @mutex.synchronize do
    return if terminated?

    @status = :sent
    @sent_at = Time.now
  end
end

#wait(raise_error: true) ⇒ Protocol::Message

Block the calling thread until a response arrives or the deadline passes.

Returns:

Raises:

  • (TimeoutError)

    when the deadline passes without a response

  • (DisconnectedError)

    when the socket is closed

  • (StandardError)

    any error previously delivered through #process_error or a failed reply when raise_error is true.



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/freeswitch/esl/connection/command_request.rb', line 103

def wait(raise_error: true)
  @mutex.synchronize do
    raise_error_if_necessary(raise_error:)
    return self if terminated?

    @condition.wait(@mutex, @timeout)

    # If still pending after the wait window, mark as timed-out and raise.
    if %i[queued sent].include?(@status)
      @status = :timeout
      @error = TimeoutError.new("Command timed out after #{@timeout}s waiting for response")
    end

    raise_error_if_necessary(raise_error:)
  end

  self
end