adhearsion 2.5.0 → 2.5.2

Sign up to get free protection for your applications and to get access to all the features.
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