Class: Freeswitch::ESL::Command

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

Overview

Represents the asynchronous execution of a bgapi command.

A Command is created by Freeswitch::ESL::Client#exec and tracks the full lifecycle of the request: pending → completed (success or failure).

Async usage (non-blocking)

cmd = client.exec("originate", "sofia/default/1234@example.com")
cmd.on_complete { |c| puts c.response.body }
# ... do other work ...
cmd.response  # blocks until completed (or timeout)

Sync usage (blocking)

cmd = client.exec("originate", "sofia/default/1234@example.com")
cmd.wait
puts cmd.response.body

Timeout

The default timeout is DEFAULT_TIMEOUT seconds. If the bgapi result event does not arrive in time the command transitions to :timeout and any subsequent result is silently ignored.

Constant Summary collapse

DEFAULT_TIMEOUT =
60

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client, command, *args, timeout: DEFAULT_TIMEOUT, raise_error: true, &block) ⇒ Command

Returns a new instance of Command.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/freeswitch/esl/command.rb', line 42

def initialize(client, command, *args, timeout: DEFAULT_TIMEOUT, raise_error: true, &block)
  @client = client
  @command = command
  @args = args
  @timeout = timeout
  @raise_error = raise_error
  @status = :pending
  @job_uuid = nil
  @response = nil
  @error = nil
  @callbacks = block ? [block] : []
  @mutex = Mutex.new
  @cond = ConditionVariable.new
  @sent_at = nil
  @finished_at = nil

  validate_command!
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



40
41
42
# File 'lib/freeswitch/esl/command.rb', line 40

def args
  @args
end

#commandObject (readonly)

Returns the value of attribute command.



40
41
42
# File 'lib/freeswitch/esl/command.rb', line 40

def command
  @command
end

#errorCommandError, ... (readonly)

Returns the error that caused the command to fail (nil if successful).

Returns:



38
39
40
# File 'lib/freeswitch/esl/command.rb', line 38

def error
  @error
end

#finished_atObject (readonly)

Returns the value of attribute finished_at.



40
41
42
# File 'lib/freeswitch/esl/command.rb', line 40

def finished_at
  @finished_at
end

#job_uuidString? (readonly)

Returns Job-UUID assigned by FreeSWITCH (nil if invalid).

Returns:

  • (String, nil)

    Job-UUID assigned by FreeSWITCH (nil if invalid)



35
36
37
# File 'lib/freeswitch/esl/command.rb', line 35

def job_uuid
  @job_uuid
end

#sent_atObject (readonly)

Returns the value of attribute sent_at.



40
41
42
# File 'lib/freeswitch/esl/command.rb', line 40

def sent_at
  @sent_at
end

#status:pending, ... (readonly)

Returns current status of the command.

Returns:

  • (:pending, :ok, :failed, :timeout)

    current status of the command



32
33
34
# File 'lib/freeswitch/esl/command.rb', line 32

def status
  @status
end

Instance Method Details

#completed?Boolean

Returns true when the command has finished (success or failure).

Returns:

  • (Boolean)

    true when the command has finished (success or failure)



117
118
119
# File 'lib/freeswitch/esl/command.rb', line 117

def completed?
  !pending?
end

#execute!Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/freeswitch/esl/command.rb', line 61

def execute!
  configure_timeout!
  return unless wait_until_client_ready

  @sent_at = now
  @status = :sent
  @job_uuid = @client.bgapi(@command, *@args) do |event|
    event.error? ? fail!(event) : complete!(event)
  end
rescue StandardError => e
  @status = :failed
  @error = e
  @finished_at = now
  raise e if @raise_error
end

#execution_timeObject



141
142
143
144
145
# File 'lib/freeswitch/esl/command.rb', line 141

def execution_time
  return nil unless @sent_at

  (@finished_at || now) - @sent_at
end

#failed?Boolean

Returns true when the command failed or timed out.

Returns:

  • (Boolean)

    true when the command failed or timed out



137
138
139
# File 'lib/freeswitch/esl/command.rb', line 137

def failed?
  %i[failed timeout].include?(@status)
end

#ok?Boolean

Returns true when the command completed successfully.

Returns:

  • (Boolean)

    true when the command completed successfully



127
128
129
# File 'lib/freeswitch/esl/command.rb', line 127

def ok?
  @status == :ok
end

#on_complete(&block) ⇒ Object

Register a callback to be called when the command completes (success or failure). Multiple callbacks are supported and are called in order. If the command is already completed the block is called immediately. Returns self for chaining.

Raises:

  • (ArgumentError)


81
82
83
84
85
86
87
88
# File 'lib/freeswitch/esl/command.rb', line 81

def on_complete(&block)
  raise ArgumentError, "Block is required" unless block_given?

  @callbacks << block
  block.call(self) if completed?

  self
end

#pending?Boolean

Returns true when the command is still waiting for a result.

Returns:

  • (Boolean)

    true when the command is still waiting for a result



122
123
124
# File 'lib/freeswitch/esl/command.rb', line 122

def pending?
  %i[pending sent].include?(@status)
end

#responseProtocol::Event?

Block the calling thread until the command completes or the timeout expires.

Returns:

  • (Protocol::Event)

    the event returned by FreeSWITCH when the command completed successfully

  • (nil)

    if the command failed or timed out but did not raise an exception (raise_error: false)

Raises:



95
96
97
98
99
# File 'lib/freeswitch/esl/command.rb', line 95

def response
  wait unless completed?

  @response
end

#timeout?Boolean

Returns true when the command terminated with a timeout (a special kind of failure).

Returns:

  • (Boolean)

    true when the command terminated with a timeout (a special kind of failure)



132
133
134
# File 'lib/freeswitch/esl/command.rb', line 132

def timeout?
  @status == :timeout
end

#waitCommand

Wait for the command to complete, fail or timeout.

Returns:

  • (Command)

    self after completion

Raises:



103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/freeswitch/esl/command.rb', line 103

def wait
  @mutex.synchronize do
    return self if completed?

    wait_time = @timeout ? (@timeout - execution_time.to_f) : nil
    @cond.wait(@mutex, wait_time)
  end

  raise @error if @error && @raise_error

  self
end