lib/adhearsion/call_controller/dial.rb in adhearsion-2.6.4 vs lib/adhearsion/call_controller/dial.rb in adhearsion-3.0.0.beta1

- old
+ new

@@ -31,13 +31,15 @@ # policy of VoIP termination providers with respect to caller id values. Defaults to the caller ID of the dialing call, so for normal bridging scenarios, you do not need to set this. # # @option options [Numeric] :for this option can be thought of best as a timeout. # i.e. timeout after :for if no one answers the call # - # @option options [CallController] :confirm the controller to execute on the first outbound call to be answered, to give an opportunity to screen the call. The calls will be joined if the outbound call is still active after this controller completes. + # @option options [CallController] :confirm Confirmation controller to execute. Confirmation will be attempted on all answered calls, and calls will be allowed to progress through confirmation in parallel. The first to complete confirmation will be joined to the A-leg, with the others being hung up. # @option options [Hash] :confirm_metadata Metadata to set on the confirmation controller before executing it. This is shared between all calls if dialing multiple endpoints; if you care about it being mutated, you should provide an immutable value (using eg https://github.com/harukizaemon/hamster). # + # @option options [CallController] :apology controller to execute on calls which lose the race to complete confirmation before they are hung up + # # @option options [CallController] :cleanup The controller to execute on each call being cleaned up. This can be used, for instance, to notify that the call is being terminated. Calls are terminated right after this controller completes execution. If this is not specified, calls are silently terminated during cleanup. # @option options [Hash] :cleanup_metadata Metadata to set on the cleanup controller before executing it. Defaults to :confirm_metadata if not specified. # # @option options [Hash] :join_options Options to specify the kind of join operation to perform. See `Call#join` for details. # @option options [Call, String, Hash] :join_target the target to join to. May be a Call object, a call ID (String, Hash) or a mixer name (Hash). See `Call#join` for details. @@ -66,27 +68,10 @@ dial.status ensure catching_standard_errors { dial.delete_logger if dial } end - # Dial one or more third parties and join one to this call after execution of a confirmation controller. - # Confirmation will be attempted on all answered calls, and calls will be allowed to progress through confirmation in parallel. The first to complete confirmation will be joined to the A-leg, with the others being hung up. - # - # @option options [CallController] :apology controller to execute on calls which lose the race to complete confirmation before they are hung up - # - # @see #dial - def dial_and_confirm(to, options = {}) - dial = ParallelConfirmationDial.new to, options, call - dial.run(self) - dial.await_completion - dial.terminate_ringback - dial.cleanup_calls - dial.status - ensure - catching_standard_errors { dial.delete_logger if dial } - end - class Dial attr_accessor :status def initialize(to, options, call) raise Call::Hangup unless call.alive? && call.active? @@ -161,12 +146,10 @@ 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.timestamp.to_time end new_call.on_unjoined @call do |unjoined| @@ -375,10 +358,12 @@ @options[:timeout] ||= _for if _for @confirmation_controller = @options.delete :confirm @confirmation_metadata = @options.delete :confirm_metadata + @apology_controller = @options.delete :apology + @pre_join = @options.delete :pre_join @ringback = @options.delete :ringback @join_options = @options.delete(:join_options) || {} @join_target = @options.delete(:join_target) || @call @@ -386,20 +371,22 @@ @cleanup_controller = @options.delete :cleanup @cleanup_metadata = @options.delete :cleanup_metadata || @confirmation_metadata @skip_cleanup = false end - def pre_confirmation_tasks(call) - on_all_except call do |target_call| - logger.info "#dial hanging up call #{target_call.id} because this call has been answered by another channel" - target_call.hangup - end - end - def pre_join_tasks(call) @pre_join.call(call) if @pre_join terminate_ringback + on_all_except call do |target_call| + if @apology_controller + logger.info "#dial executing apology controller #{@apology_controller} on call #{target_call.id} because this call has been confirmed by another channel" + target_call.async.execute_controller @apology_controller.new(target_call, @confirmation_metadata), ->(call) { call.hangup } + else + logger.info "#dial hanging up call #{target_call.id} because this call has been confirmed by another channel" + target_call.hangup + end + end end def on_all_except(call) @calls.each do |target_call| ignoring_ended_calls do @@ -409,42 +396,17 @@ end end def ignoring_missing_joins yield - rescue Punchblock::ProtocolError => e + rescue Adhearsion::ProtocolError => e raise unless e.name == :service_unavailable end def ignoring_ended_calls yield rescue Celluloid::DeadActorError, Adhearsion::Call::Hangup, Adhearsion::Call::ExpiredError # This actor may previously have been shut down due to the call ending - end - end - - class ParallelConfirmationDial < Dial - private - - def set_defaults - super - @apology_controller = @options.delete :apology - end - - def pre_confirmation_tasks(call) - end - - def pre_join_tasks(call) - super - on_all_except call do |target_call| - if @apology_controller - logger.info "#dial executing apology controller #{@apology_controller} on call #{target_call.id} because this call has been confirmed by another channel" - target_call.async.execute_controller @apology_controller.new(target_call, @confirmation_metadata), ->(call) { call.hangup } - else - logger.info "#dial hanging up call #{target_call.id} because this call has been confirmed by another channel" - target_call.hangup - end - end end end class DialStatus # The collection of calls created during the dial operation