Class: Adhearsion::CallController::Dial::Dial
- Defined in:
- lib/adhearsion/call_controller/dial.rb
Instance Attribute Summary collapse
-
#status ⇒ Object
Returns the value of attribute status.
Instance Method Summary collapse
-
#await_completion ⇒ Object
Block until the dial operation is completed by an appropriate quorum of the involved calls ending.
-
#cleanup_calls ⇒ Object
Hangup any remaining calls.
- #delete_logger ⇒ Object
-
#initialize(to, options, call) ⇒ Dial
constructor
A new instance of Dial.
- #inspect ⇒ Object
-
#merge(other) ⇒ Object
Merge another Dial into this one, joining all calls to a mixer.
-
#place_calls ⇒ Object
Dials the set of outbound calls.
-
#prep_calls { ... } ⇒ Object
Prepares a set of OutboundCall actors to be dialed and links their lifecycles to the Dial operation.
-
#rejoin(target = nil, join_options = nil) ⇒ Object
Rejoin parties that were previously split.
-
#run(controller) ⇒ Object
Prep outbound calls, link call lifecycles and place outbound calls.
-
#skip_cleanup ⇒ Object
Do not hangup outbound calls when the Dial operation finishes.
-
#split(targets = {}) ⇒ Object
Split calls party to the dial Marks the end time in the status of each join, but does not unblock #dial until one of the calls ends Optionally executes call controllers on calls once split, where ‘current_dial’ is available in controller metadata in order to perform further operations on the Dial, including rejoining and termination.
-
#start_ringback(controller) ⇒ Object
Starts ringback on the specified controller.
-
#terminate_ringback ⇒ Object
Terminates any ringback that might be playing.
-
#track_originating_call ⇒ Object
Links the lifecycle of the originating call to the Dial operation such that the Dial is unblocked when the originating call ends.
Constructor Details
#initialize(to, options, call) ⇒ Dial
Returns a new instance of Dial.
79 80 81 82 83 84 85 86 |
# File 'lib/adhearsion/call_controller/dial.rb', line 79 def initialize(to, , call) raise Call::Hangup unless call.active? @id = SecureRandom.uuid @options, @call = , call @targets = to.respond_to?(:has_key?) ? to : Array(to) @call_targets = {} set_defaults end |
Instance Attribute Details
#status ⇒ Object
Returns the value of attribute status.
77 78 79 |
# File 'lib/adhearsion/call_controller/dial.rb', line 77 def status @status end |
Instance Method Details
#await_completion ⇒ Object
Block until the dial operation is completed by an appropriate quorum of the involved calls ending
287 288 289 290 291 292 293 |
# File 'lib/adhearsion/call_controller/dial.rb', line 287 def await_completion @latch.wait(@options[:timeout]) || status.timeout! return unless status.result == :answer logger.debug "Main calls were completed, waiting for any added calls: #{@waiters.inspect}" @waiters.each(&:wait) logger.debug "All calls were completed, unblocking." end |
#cleanup_calls ⇒ Object
Hangup any remaining calls
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 |
# File 'lib/adhearsion/call_controller/dial.rb', line 303 def cleanup_calls calls_to_hangup = @calls.map do |call| ignoring_ended_calls do [call.id, call] if call.active? end end.compact if calls_to_hangup.size.zero? logger.info "#dial finished with no remaining outbound calls" return end if @skip_cleanup logger.info "#dial finished. Leaving #{calls_to_hangup.size} outbound calls going which are still active: #{calls_to_hangup.map(&:first).join ", "}." else logger.info "#dial finished. Hanging up #{calls_to_hangup.size} outbound calls which are still active: #{calls_to_hangup.map(&:first).join ", "}." calls_to_hangup.each do |id, outbound_call| ignoring_ended_calls do if @cleanup_controller logger.info "#dial running #{@cleanup_controller.class.name} on #{outbound_call.id}" outbound_call.execute_controller @cleanup_controller.new(outbound_call, @cleanup_metadata), ->(call) { call.hangup } else logger.info "#dial hanging up #{outbound_call.id}" outbound_call.hangup end end end end end |
#delete_logger ⇒ Object
331 332 333 |
# File 'lib/adhearsion/call_controller/dial.rb', line 331 def delete_logger ::Logging::Repository.instance.delete logger_id end |
#inspect ⇒ Object
88 89 90 |
# File 'lib/adhearsion/call_controller/dial.rb', line 88 def inspect "#<#{self.class}[#{@id}] to=#{@to.inspect} options=#{@options.inspect}>" end |
#merge(other) ⇒ Object
Merge another Dial into this one, joining all calls to a mixer
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
# File 'lib/adhearsion/call_controller/dial.rb', line 266 def merge(other) logger.info "Merging with #{other.inspect}" split other.split rejoin({mixer_name: @id}, {}) other.rejoin({mixer_name: @id}, {}) calls_to_merge = other.status.calls + [other.root_call] @calls.merge calls_to_merge latch = CountDownLatch.new calls_to_merge.size calls_to_merge.each do |call| call.on_end { |event| latch.countdown! } end @waiters << latch end |
#place_calls ⇒ Object
Dials the set of outbound calls
200 201 202 203 204 205 206 |
# File 'lib/adhearsion/call_controller/dial.rb', line 200 def place_calls @calls.each do |call| target, = @call_targets[call] = @options.dup.deep_merge if call.dial target, ( || @options) end end |
#prep_calls { ... } ⇒ Object
Prepares a set of OutboundCall actors to be dialed and links their lifecycles to the Dial operation
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/adhearsion/call_controller/dial.rb', line 137 def prep_calls @calls = Set.new @targets.map do |target, | new_call = OutboundCall.new join_status = JoinStatus.new status.joins[new_call] = join_status new_call.on_end do |event| @latch.countdown! unless new_call["dial_countdown_#{@id}"] if event.reason == :error status.error! join_status.errored! end end new_call.on_answer do |event| new_call.on_joined @call do |joined| join_status.started joined..to_time end new_call.on_unjoined @call do |unjoined| join_status.ended unjoined..to_time unless @splitting new_call["dial_countdown_#{@id}"] = true @latch.countdown! end end if @confirmation_controller status.unconfirmed! join_status.unconfirmed! condition = Celluloid::Condition.new new_call.execute_controller @confirmation_controller.new(new_call, @confirmation_metadata), lambda { |call| condition.broadcast } condition.wait end if new_call.active? && status.result != :answer logger.info "#dial joining call #{new_call.id} to #{@call.id}" pre_join_tasks new_call @call.answer new_call.join @join_target, @join_options unless @join_target == @call @call.join @join_target, @join_options end status.answer! elsif status.result == :answer join_status.lost_confirmation! end end @call_targets[new_call] = [target, ] yield new_call if block_given? @calls << new_call end status.calls = @calls end |
#rejoin(target = nil, join_options = nil) ⇒ Object
Rejoin parties that were previously split
249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/adhearsion/call_controller/dial.rb', line 249 def rejoin(target = nil, = nil) target ||= join_target ||= @join_options logger.info "Rejoining to #{target}" ignoring_ended_calls do unless target == @call @join_target = target @call.join target, end end @calls.each do |call| ignoring_ended_calls { call.join target, } end end |
#run(controller) ⇒ Object
Prep outbound calls, link call lifecycles and place outbound calls
93 94 95 96 97 98 |
# File 'lib/adhearsion/call_controller/dial.rb', line 93 def run(controller) track_originating_call start_ringback controller prep_calls place_calls end |
#skip_cleanup ⇒ Object
Do not hangup outbound calls when the Dial operation finishes. This allows outbound calls to continue with other processing once they are unjoined.
297 298 299 |
# File 'lib/adhearsion/call_controller/dial.rb', line 297 def skip_cleanup @skip_cleanup = true end |
#split(targets = {}) ⇒ Object
Split calls party to the dial Marks the end time in the status of each join, but does not unblock #dial until one of the calls ends Optionally executes call controllers on calls once split, where ‘current_dial’ is available in controller metadata in order to perform further operations on the Dial, including rejoining and termination.
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/adhearsion/call_controller/dial.rb', line 216 def split(targets = {}) @splitting = true calls_to_split = @calls.map do |call| ignoring_ended_calls do [call.id, call] if call.active? end end.compact logger.info "Splitting off peer calls #{calls_to_split.map(&:first).join ", "}" calls_to_split.each do |id, call| ignoring_ended_calls do logger.debug "Unjoining peer #{call.id} from #{join_target}" ignoring_missing_joins { call.unjoin join_target } if split_controller = targets[:others] logger.info "Executing controller #{split_controller} on split call #{call.id}" call.execute_controller split_controller.new(call, 'current_dial' => self), targets[:others_callback] end end end ignoring_ended_calls do if join_target != @call logger.debug "Unjoining main call #{@call.id} from #{join_target}" @call.unjoin join_target end if split_controller = targets[:main] logger.info "Executing controller #{split_controller} on main call" @call.execute_controller split_controller.new(@call, 'current_dial' => self), targets[:main_callback] end end end |
#start_ringback(controller) ⇒ Object
Starts ringback on the specified controller
115 116 117 118 119 120 121 122 |
# File 'lib/adhearsion/call_controller/dial.rb', line 115 def start_ringback(controller) return unless @ringback @ringback_component = if @ringback.respond_to?(:call) @ringback.call else controller.play! @ringback, repeat_times: 0 end end |
#terminate_ringback ⇒ Object
Terminates any ringback that might be playing
127 128 129 130 131 |
# File 'lib/adhearsion/call_controller/dial.rb', line 127 def terminate_ringback return unless @ringback_component return unless @ringback_component.executing? @ringback_component.stop! end |
#track_originating_call ⇒ Object
Links the lifecycle of the originating call to the Dial operation such that the Dial is unblocked when the originating call ends
102 103 104 105 106 107 108 109 |
# File 'lib/adhearsion/call_controller/dial.rb', line 102 def track_originating_call @call.on_end do |_| logger.debug "Root call ended, unblocking connected calls" @waiters.each do |latch| latch.countdown! until latch.count == 0 end end end |