adhearsion 2.5.0 → 2.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9155fcf025c8ed90e014e5262b70387e46e31937
4
- data.tar.gz: dcb5d1f0104f854e3b487f34cf199e3134d5d38d
3
+ metadata.gz: 514090f6f124b09e72ebe60bea5691b5bbad141e
4
+ data.tar.gz: 3cb8255d9057e5a7731ea5960cb98406e1bdb3d4
5
5
  SHA512:
6
- metadata.gz: 00076ee1fdd8a0d208dc1895dbb74f33f5c0adc23a2348248c0c8938378715d2bd40b7f8bfe64e42b05d2cd3e9594a0159d00af5b64f8e3285e37d2336249011
7
- data.tar.gz: 7b1e9f478d6860f662e485a1c5add9e69ed0d1c2cf0f1d038ed661c47e2fd791224855bd452d89c79c09b18ebec16988df30af6650fb03870b77cde1f190ab14
6
+ metadata.gz: 2f4e33832002eb3201f8fc77782972ec63ce07b65a81429e5b875a366aa4ea66daa7ca6ffa4f84bd6d8b3582c1ad12255c44bb07249c8dd2b047ff96fc78d29a
7
+ data.tar.gz: 0432281ea39a81eb779a6ffedfe69d6817afd64b5be958d3fd128effe329c55525d366506b18d1ea0a2fe93208826d2d536600160b4b53d4e806ca512ab79d65
@@ -3,7 +3,7 @@ rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
5
  - 2.1.0
6
- - jruby-19mode
6
+ - jruby
7
7
  - rbx-2.1.1
8
8
  - ruby-head
9
9
  matrix:
@@ -1,5 +1,20 @@
1
1
  # [develop](https://github.com/adhearsion/adhearsion)
2
2
 
3
+ # [2.5.2](https://github.com/adhearsion/adhearsion/compare/v2.5.1...v2.5.2) - [2014-04-11](https://rubygems.org/gems/adhearsion/versions/2.5.2)
4
+ * All changes from 2.5.1 (re-released)
5
+ * Further fix for outbound call race conditions. When a Rayo server does not support client-supplied outbound call URIs, or refuses a requested URI by silently replacing it with a different one, the behaviour of Adhearsion falls back to the one with a race condition.
6
+
7
+ # [2.5.1](https://github.com/adhearsion/adhearsion/compare/v2.5.0...v2.5.1) - [2014-04-07](https://rubygems.org/gems/adhearsion/versions/2.5.1) - yanked
8
+ * Bugfix: Avoid race conditions in event delivery for outbound calls. **note: This requires a Rayo server compliant with Rayo v0.4, which includes changes outlined in [rayo/xmpp#89](https://github.com/rayo/xmpp/issues/89). For FreeSWITCH mod_rayo, this means v1.2.23 of FreeSWITCH or the latest v1.2.stable branch.**([#439](https://github.com/adhearsion/adhearsion/issues/444))
9
+ * Bugfix: Fix some omissions in 2.5.0 relating to the new application layout ([#439](https://github.com/adhearsion/adhearsion/pull/439))
10
+ * Bugfix: Log to correct file when supplying an absolute path
11
+ * Bugfix: Delay configuring plugins until after initialisation. Allows plugin config to use things which are not set until initialisation like the current working directory, Adhearsion.root, etc. ([adhearsion/adhearsion-i18n#4](https://github.com/adhearsion/adhearsion-i18n/issues/4))
12
+ * Bugfix: Calls which are dead but can still be found now log a warning when receiving events
13
+ * Bugfix: Cleanup generated application routes spacing
14
+ * Bugfix: Use Rayo event timestamps for timing call operations. These timestamps are more accurate than using the time of event processing since event delivery/processing might be delayed due to network conditions or application load. This enables more reliable billing. ([#454](https://github.com/adhearsion/adhearsion/pull/454))
15
+ * Bugfix: Plugins should be more comprehensively loaded for rake tasks
16
+ * Bugfix: Millisecond-level timestamps now appear not only STDOUT, but in the default adhearsion.log as well.
17
+
3
18
  # [2.5.0](https://github.com/adhearsion/adhearsion/compare/v2.4.0...v2.5.0) - [2014-02-03](https://rubygems.org/gems/adhearsion/versions/2.5.0)
4
19
  * **Change: Ruby 1.9.2 is no longer supported**
5
20
  * Change: Set default call post-hangup lifetime to one second for better out of the box performance.
@@ -33,7 +33,7 @@ Gem::Specification.new do |s|
33
33
  s.add_runtime_dependency 'jruby-openssl' if RUBY_PLATFORM == 'java'
34
34
  s.add_runtime_dependency 'logging', ["~> 1.8"]
35
35
  s.add_runtime_dependency 'pry'
36
- s.add_runtime_dependency 'punchblock', ["~> 2.3"]
36
+ s.add_runtime_dependency 'punchblock', ["~> 2.4"]
37
37
  s.add_runtime_dependency 'rake'
38
38
  s.add_runtime_dependency 'ruby_speech', ["~> 2.0"]
39
39
  s.add_runtime_dependency 'thor', "~> 0.18.0"
@@ -43,7 +43,7 @@ Gem::Specification.new do |s|
43
43
  s.add_development_dependency 'cucumber'
44
44
  s.add_development_dependency 'guard-cucumber'
45
45
  s.add_development_dependency 'guard-rspec'
46
- s.add_development_dependency 'rspec', ["~> 2.11"]
46
+ s.add_development_dependency 'rspec', ["~> 2.13"]
47
47
  s.add_development_dependency 'simplecov'
48
48
  s.add_development_dependency 'simplecov-rcov'
49
49
  s.add_development_dependency 'yard'
@@ -73,7 +73,7 @@ module Adhearsion
73
73
  _config = Configuration.new
74
74
  env = environment.to_sym if environment.respond_to? :to_sym
75
75
  unless _config.valid_environment? env
76
- puts "You tried to initialize with an invalid environment name #{env}. Valid values are #{_config.valid_environments}."
76
+ puts "You tried to initialize with an invalid environment name #{env}; environment-specific config may not load successfully. Valid values are #{_config.valid_environments}."
77
77
  env = nil
78
78
  end
79
79
  _config.platform.environment = env if env
@@ -101,8 +101,7 @@ module Adhearsion
101
101
  end
102
102
 
103
103
  def active_calls
104
- Celluloid::Actor[:active_calls] || Calls.supervise_as(:active_calls)
105
- Celluloid::Actor[:active_calls]
104
+ @active_calls ||= Calls.new
106
105
  end
107
106
 
108
107
  #
@@ -17,7 +17,7 @@ module Adhearsion
17
17
  include Celluloid
18
18
  include HasGuardedHandlers
19
19
 
20
- execute_block_on_receiver :register_handler, :register_tmp_handler, :register_handler_with_priority, :register_event_handler, :on_joined, :on_unjoined, :on_end, :execute_controller, *execute_block_on_receiver
20
+ execute_block_on_receiver :register_handler, :register_tmp_handler, :register_handler_with_priority, :register_handler_with_options, :register_event_handler, :on_joined, :on_unjoined, :on_end, :execute_controller, *execute_block_on_receiver
21
21
  finalizer :finalize
22
22
 
23
23
  def self.new(*args, &block)
@@ -195,7 +195,7 @@ module Adhearsion
195
195
  register_event_handler Punchblock::Event::Offer do |offer|
196
196
  @offer = offer
197
197
  @client = offer.client
198
- @start_time = Time.now
198
+ @start_time = offer.timestamp.to_time
199
199
  end
200
200
 
201
201
  register_event_handler Punchblock::HasHeaders do |event|
@@ -231,7 +231,7 @@ module Adhearsion
231
231
 
232
232
  on_end do |event|
233
233
  logger.info "Call ended due to #{event.reason}"
234
- @end_time = Time.now
234
+ @end_time = event.timestamp.to_time
235
235
  @duration = @end_time - @start_time if @start_time
236
236
  clear_from_active_calls
237
237
  @end_reason = event.reason
@@ -439,7 +439,11 @@ module Adhearsion
439
439
  abort Hangup.new(@end_reason) unless active? || command.is_a?(Punchblock::Command::Hangup)
440
440
  merge_headers command.headers if command.respond_to? :headers
441
441
  logger.debug "Executing command #{command.inspect}"
442
- client.execute_command command, call_id: id, domain: domain, async: true
442
+ unless command.is_a?(Punchblock::Command::Dial)
443
+ command.target_call_id = id
444
+ command.domain = domain
445
+ end
446
+ client.execute_command command
443
447
  end
444
448
 
445
449
  ##
@@ -110,7 +110,7 @@ module Adhearsion
110
110
  # Links the lifecycle of the originating call to the Dial operation such that the Dial is unblocked when the originating call ends
111
111
  def track_originating_call
112
112
  @call.on_end do |_|
113
- logger.info "Root call ended, unblocking everything..."
113
+ logger.debug "Root call ended, unblocking connected calls"
114
114
  @waiters.each do |latch|
115
115
  latch.countdown! until latch.count == 0
116
116
  end
@@ -163,7 +163,7 @@ module Adhearsion
163
163
  pre_confirmation_tasks new_call
164
164
 
165
165
  new_call.on_unjoined @call do |unjoined|
166
- join_status.ended
166
+ join_status.ended unjoined.timestamp.to_time
167
167
  unless @splitting
168
168
  new_call["dial_countdown_#{@id}"] = true
169
169
  @latch.countdown!
@@ -520,8 +520,8 @@ module Adhearsion
520
520
  @result = :joined
521
521
  end
522
522
 
523
- def ended
524
- @end_time = Time.now
523
+ def ended(time)
524
+ @end_time = time
525
525
  end
526
526
  end
527
527
 
@@ -15,7 +15,7 @@ module Adhearsion
15
15
  # @param [Adhearsion::CallController] controller on which to execute the recording
16
16
  # @param [Hash] options
17
17
  # @option options [Boolean, Optional] :async Execute asynchronously. Defaults to false
18
- # @option options [Boolean, Optional] :start_beep Indicates whether subsequent record will be preceded with a beep. Default is true.
18
+ # @option options [Boolean, Optional] :start_beep Indicates whether subsequent record will be preceded with a beep. Default is false.
19
19
  # @option options [Boolean, Optional] :start_paused Whether subsequent record will start in PAUSE mode. Default is false.
20
20
  # @option options [String, Optional] :max_duration Indicates the maximum duration (seconds) for a recording.
21
21
  # @option options [String, Optional] :format File format used during recording.
@@ -108,7 +108,7 @@ module Adhearsion
108
108
  #
109
109
  # @param [Hash] options
110
110
  # @option options [Boolean, Optional] :async Execute asynchronously. Defaults to false
111
- # @option options [Boolean, Optional] :start_beep Indicates whether subsequent record will be preceded with a beep. Default is true.
111
+ # @option options [Boolean, Optional] :start_beep Indicates whether subsequent record will be preceded with a beep. Default is false.
112
112
  # @option options [Boolean, Optional] :start_paused Whether subsequent record will start in PAUSE mode. Default is false.
113
113
  # @option options [String, Optional] :max_duration Indicates the maximum duration (seconds) for a recording.
114
114
  # @option options [String, Optional] :format File format used during recording.
@@ -1,18 +1,24 @@
1
1
  # encoding: utf-8
2
2
 
3
+ require 'thread'
4
+
3
5
  module Adhearsion
4
6
  ##
5
7
  # This manages the list of calls the Adhearsion service receives
6
- class Calls < Hash
7
- include Celluloid
8
-
9
- trap_exit :call_died
8
+ class Calls
9
+ def initialize
10
+ @mutex = ::Monitor.new
11
+ @calls = {}
12
+ restart_supervisor
13
+ end
10
14
 
11
15
  def <<(call)
12
- link call
13
- self[call.id] = call
14
- by_uri[call.uri] = call
15
- current_actor
16
+ @supervisor.link call
17
+ @mutex.synchronize do
18
+ self[call.id] = call
19
+ by_uri[call.uri] = call
20
+ end
21
+ self
16
22
  end
17
23
 
18
24
  def remove_inactive_call(call)
@@ -40,6 +46,11 @@ module Adhearsion
40
46
  by_uri[uri]
41
47
  end
42
48
 
49
+ def restart_supervisor
50
+ @supervisor.terminate if @supervisor
51
+ @supervisor = Supervisor.new self
52
+ end
53
+
43
54
  private
44
55
 
45
56
  def by_uri
@@ -53,18 +64,34 @@ module Adhearsion
53
64
 
54
65
  def call_is_dead?(call)
55
66
  !call.alive?
56
- rescue NoMethodError
67
+ rescue ::NoMethodError
57
68
  false
58
69
  end
59
70
 
60
- def call_died(call, reason)
61
- catching_standard_errors do
62
- call_id = key call
63
- remove_inactive_call call
64
- return unless reason
65
- Adhearsion::Events.trigger :exception, reason
66
- logger.error "Call #{call_id} terminated abnormally due to #{reason}. Forcing hangup."
67
- PunchblockPlugin.client.execute_command Punchblock::Command::Hangup.new, :async => true, :call_id => call_id
71
+ def method_missing(method, *args, &block)
72
+ @mutex.synchronize do
73
+ @calls.send method, *args, &block
74
+ end
75
+ end
76
+
77
+ class Supervisor
78
+ include Celluloid
79
+
80
+ trap_exit :call_died
81
+
82
+ def initialize(collection)
83
+ @collection = collection
84
+ end
85
+
86
+ def call_died(call, reason)
87
+ catching_standard_errors do
88
+ call_id = @collection.key call
89
+ @collection.remove_inactive_call call
90
+ return unless reason
91
+ Adhearsion::Events.trigger :exception, reason
92
+ logger.error "Call #{call_id} terminated abnormally due to #{reason}. Forcing hangup."
93
+ PunchblockPlugin.client.execute_command Punchblock::Command::Hangup.new, :async => true, :call_id => call_id
94
+ end
68
95
  end
69
96
  end
70
97
  end
@@ -2,9 +2,10 @@ source 'https://rubygems.org'
2
2
 
3
3
  gem 'adhearsion', '~> <%= Adhearsion::VERSION.split('.')[0,2].join('.') %>'
4
4
 
5
- # Adhearsion depends on the Punchblock library, but here you can specify the major version your application depends on.
6
- # Exercise care when updating the major version, since you might encounter API compatability in parts of your Adhearsion application that rely on the Punchblock API.
7
- # On occasion, an update of Adhearsion might necessitate an update to Punchblock. You will have to manually allow that here, and take care in the upgrade.
5
+ # Exercise care when updating the Punchblock major version, since Adhearsion
6
+ # apps sometimes make use of underlying features from the Punchblock API.
7
+ # Occasionally an update of Adhearsion will necessitate an update to
8
+ # Punchblock; in those cases update this line and test your app thoroughly.
8
9
  gem 'punchblock', '~> <%= require "punchblock/version"; Punchblock::VERSION.split('.')[0,2].join('.') %>'
9
10
 
10
11
  # This is here by default due to deprecation of #ask and #menu.
@@ -9,12 +9,13 @@ Edit `extensions.conf` to include the following:
9
9
  ```
10
10
  [your_context_name]
11
11
  exten => _.,1,AGI(agi:async)
12
+
13
+ [adhearsion-redirect]
14
+ exten => 1,1,AGI(agi:async)
12
15
  ```
13
16
 
14
17
  and setup a user in `manager.conf` with read/write access to `all`.
15
18
 
16
- If you are using Asterisk 1.8, you will need to add an additional context with the name `adhearsion-redirect`. On Asterisk 10 and above this is auto-provisioned.
17
-
18
19
  ## FreeSWITCH
19
20
 
20
21
  * Ensure that mod_rayo is installed and configured according to its' documentation.
@@ -1,19 +1,18 @@
1
1
  # encoding: utf-8
2
2
 
3
- <% unless options[:empty] %>
3
+ <% unless options[:empty] -%>
4
4
  require 'call_controllers/simon_game'
5
- <% end %>
6
5
 
6
+ <% end -%>
7
7
  Adhearsion.router do
8
- <% if options[:empty] %>
8
+ <% if options[:empty] -%>
9
9
  route 'default' do
10
10
 
11
11
  end
12
- <% else %>
13
- #
12
+ <% else -%>
13
+
14
14
  # Specify your call routes, directing calls with particular attributes to a controller
15
- #
16
15
 
17
16
  route 'default', SimonGame
18
- <% end %>
17
+ <% end -%>
19
18
  end
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'spec_helper'
4
+ require 'call_controllers/simon_game'
4
5
 
5
6
  describe SimonGame do
6
7
 
@@ -40,6 +40,7 @@ module Adhearsion
40
40
  def start
41
41
  catch :boot_aborted do
42
42
  resolve_pid_file_path
43
+ configure_plugins
43
44
  load_lib_folder
44
45
  load_config_file
45
46
  load_events_file
@@ -217,10 +218,14 @@ module Adhearsion
217
218
  appenders.map! do |a|
218
219
  case a
219
220
  when String
220
- f = File.expand_path(Adhearsion.config.root.dup.concat("/").concat(a)) unless a.start_with?("/")
221
+ f = if a.start_with?("/")
222
+ a
223
+ else
224
+ File.expand_path(Adhearsion.config.root.dup.concat("/").concat(a))
225
+ end
221
226
  ::Logging.appenders.file(f,
222
227
  :layout => ::Logging.layouts.pattern(
223
- :pattern => Adhearsion::Logging.adhearsion_pattern
228
+ Adhearsion::Logging.adhearsion_pattern_options
224
229
  ),
225
230
  :auto_flushing => 2,
226
231
  :flush_period => 2
@@ -237,6 +242,10 @@ module Adhearsion
237
242
  end
238
243
  end
239
244
 
245
+ def configure_plugins
246
+ Plugin.configure_plugins
247
+ end
248
+
240
249
  def init_plugins
241
250
  Plugin.init_plugins
242
251
  end
@@ -34,8 +34,11 @@ module Adhearsion
34
34
  :date => [:bold, :blue],
35
35
  :logger => :cyan
36
36
 
37
- def adhearsion_pattern
38
- '[%d] %-5l %c: %m\n'
37
+ def adhearsion_pattern_options
38
+ {
39
+ :pattern => '[%d] %-5l %c: %m\n',
40
+ :date_pattern => '%Y-%m-%d %H:%M:%S.%L'
41
+ }
39
42
  end
40
43
 
41
44
  # Silence Adhearsion's logging, printing only FATAL messages
@@ -87,9 +90,9 @@ module Adhearsion
87
90
  [::Logging.appenders.stdout(
88
91
  'stdout',
89
92
  :layout => ::Logging.layouts.pattern(
90
- :pattern => adhearsion_pattern,
91
- :date_pattern => "%Y-%m-%d %H:%M:%S.%L",
92
- :color_scheme => 'bright'
93
+ adhearsion_pattern_options.merge(
94
+ :color_scheme => 'bright'
95
+ )
93
96
  ),
94
97
  :auto_flushing => 2,
95
98
  :flush_period => 2
@@ -33,11 +33,19 @@ module Adhearsion
33
33
  end
34
34
 
35
35
  def id
36
- dial_command.target_call_id if dial_command
36
+ if dial_command
37
+ dial_command.target_call_id || @id
38
+ else
39
+ @id
40
+ end
37
41
  end
38
42
 
39
43
  def domain
40
- dial_command.domain if dial_command
44
+ if dial_command
45
+ dial_command.domain || @domain
46
+ else
47
+ @domain
48
+ end
41
49
  end
42
50
 
43
51
  def client
@@ -73,17 +81,35 @@ module Adhearsion
73
81
  wait_timeout = 60
74
82
  end
75
83
 
76
- write_and_await_response(Punchblock::Command::Dial.new(options), wait_timeout, true).tap do |dial_command|
77
- @dial_command = dial_command
78
- Adhearsion.active_calls << current_actor
84
+ uri = client.new_call_uri
85
+ options[:uri] = uri
86
+
87
+ @dial_command = Punchblock::Command::Dial.new(options)
88
+
89
+ ref = Punchblock::Ref.new uri: uri
90
+ @transport = ref.scheme
91
+ @id = ref.call_id
92
+ @domain = ref.domain
93
+
94
+ Adhearsion.active_calls << current_actor
95
+
96
+ write_and_await_response(@dial_command, wait_timeout, true).tap do |dial_command|
97
+ if @dial_command.uri != self.uri
98
+ logger.warn "Requested call URI (#{uri}) was not respected. Tracking by new URI #{self.uri}. This might cause a race in event handling, please upgrade your Rayo server."
99
+ Adhearsion.active_calls << current_actor
100
+ Adhearsion.active_calls.delete(@id)
101
+ end
79
102
  Adhearsion::Events.trigger_immediately :call_dialed, current_actor
80
103
  end
104
+ rescue
105
+ clear_from_active_calls
106
+ raise
81
107
  end
82
108
 
83
109
  # @private
84
110
  def register_initial_handlers
85
111
  super
86
- on_answer { |event| @start_time = Time.now }
112
+ on_answer { |event| @start_time = event.timestamp.to_time }
87
113
  end
88
114
 
89
115
  def run_router
@@ -115,7 +141,11 @@ module Adhearsion
115
141
  private
116
142
 
117
143
  def transport
118
- dial_command.transport if dial_command
144
+ if dial_command
145
+ dial_command.transport || @transport
146
+ else
147
+ @transport
148
+ end
119
149
  end
120
150
  end
121
151
  end