Class: Adhearsion::CallController::Dial::Dial
- Defined in:
- lib/adhearsion/call_controller/dial.rb
Direct Known Subclasses
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.
91 92 93 94 95 96 97 98 |
# File 'lib/adhearsion/call_controller/dial.rb', line 91 def initialize(to, , call) raise Call::Hangup unless call.alive? && 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.
89 90 91 |
# File 'lib/adhearsion/call_controller/dial.rb', line 89 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
301 302 303 304 305 306 307 |
# File 'lib/adhearsion/call_controller/dial.rb', line 301 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
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'lib/adhearsion/call_controller/dial.rb', line 317 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
345 346 347 |
# File 'lib/adhearsion/call_controller/dial.rb', line 345 def delete_logger ::Logging::Repository.instance.delete logger_id end |
#inspect ⇒ Object
100 101 102 |
# File 'lib/adhearsion/call_controller/dial.rb', line 100 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
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/adhearsion/call_controller/dial.rb', line 280 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
214 215 216 217 218 219 220 |
# File 'lib/adhearsion/call_controller/dial.rb', line 214 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
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 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/adhearsion/call_controller/dial.rb', line 149 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| pre_confirmation_tasks new_call 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.alive? && 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
263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
# File 'lib/adhearsion/call_controller/dial.rb', line 263 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
105 106 107 108 109 110 |
# File 'lib/adhearsion/call_controller/dial.rb', line 105 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.
311 312 313 |
# File 'lib/adhearsion/call_controller/dial.rb', line 311 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.
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/adhearsion/call_controller/dial.rb', line 230 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
127 128 129 130 131 132 133 134 |
# File 'lib/adhearsion/call_controller/dial.rb', line 127 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
139 140 141 142 143 |
# File 'lib/adhearsion/call_controller/dial.rb', line 139 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
114 115 116 117 118 119 120 121 |
# File 'lib/adhearsion/call_controller/dial.rb', line 114 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 |