adhearsion 2.0.0.rc1 → 2.0.0.rc2
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.
- data/CHANGELOG.md +7 -0
- data/adhearsion.gemspec +1 -1
- data/lib/adhearsion.rb +7 -1
- data/lib/adhearsion/call.rb +3 -3
- data/lib/adhearsion/call_controller.rb +1 -1
- data/lib/adhearsion/call_controller/output.rb +1 -1
- data/lib/adhearsion/calls.rb +27 -50
- data/lib/adhearsion/configuration.rb +3 -2
- data/lib/adhearsion/foundation/exception_handler.rb +2 -2
- data/lib/adhearsion/generators/app/templates/lib/simon_game.rb +5 -9
- data/lib/adhearsion/initializer.rb +1 -1
- data/lib/adhearsion/menu_dsl/menu.rb +1 -1
- data/lib/adhearsion/process.rb +1 -1
- data/lib/adhearsion/punchblock_plugin/initializer.rb +1 -1
- data/lib/adhearsion/version.rb +1 -28
- data/spec/adhearsion/call_controller/record_spec.rb +8 -1
- data/spec/adhearsion/call_controller_spec.rb +9 -2
- data/spec/adhearsion/call_spec.rb +40 -0
- data/spec/adhearsion/calls_spec.rb +89 -20
- data/spec/adhearsion/process_spec.rb +6 -4
- data/spec/adhearsion_spec.rb +10 -0
- data/spec/spec_helper.rb +1 -0
- metadata +66 -66
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# [develop](https://github.com/adhearsion/adhearsion)
|
2
2
|
|
3
|
+
# [2.0.0.rc2](https://github.com/adhearsion/adhearsion/compare/v2.0.0.rc1...v2.0.0.rc2) - [2012-03-22](https://rubygems.org/gems/adhearsion/versions/2.0.0.rc2)
|
4
|
+
* Bugfix: Exceptions raised in call event handlers no longer kill the call actor
|
5
|
+
* Bugfix: More exceptions handled internally by Adhearsion are logged in an appropriate context
|
6
|
+
* Bugfix/Change: `Adhearsion::Calls` (`Adhearsion.active_calls`) is now an actor for better thread-safety, and mirrors the Hash API more closely.
|
7
|
+
* Bugfix: Calls are now removed from the active call collection and hung up if their actor dies
|
8
|
+
* Bugfix: SimonGame now works using the new `CallController#ask` api
|
9
|
+
|
3
10
|
# [2.0.0.rc1](https://github.com/adhearsion/adhearsion/compare/v2.0.0.beta1...v2.0.0.rc1) - [2012-03-20](https://rubygems.org/gems/adhearsion/versions/2.0.0.rc1)
|
4
11
|
* Change: `CallController#join` now blocks until a corresponding unjoined event is received
|
5
12
|
* Change: `CallController#speak` is now `CallController#say`
|
data/adhearsion.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
|
21
21
|
# Runtime dependencies
|
22
22
|
s.add_runtime_dependency 'bundler', [">= 1.0.10"]
|
23
|
-
s.add_runtime_dependency 'punchblock', [">= 0.
|
23
|
+
s.add_runtime_dependency 'punchblock', [">= 0.10.0"]
|
24
24
|
s.add_runtime_dependency 'logging', [">= 1.6.1"]
|
25
25
|
s.add_runtime_dependency 'adhearsion-loquacious', [">= 1.9.0"]
|
26
26
|
s.add_runtime_dependency 'activesupport', [">= 3.0.10"]
|
data/lib/adhearsion.rb
CHANGED
@@ -24,6 +24,8 @@ abort "ERROR: You are running Adhearsion on an unsupported version of Ruby (Ruby
|
|
24
24
|
module Adhearsion
|
25
25
|
extend ActiveSupport::Autoload
|
26
26
|
|
27
|
+
Error = Class.new StandardError
|
28
|
+
|
27
29
|
autoload :Process
|
28
30
|
autoload :Call
|
29
31
|
autoload :CallController
|
@@ -79,7 +81,11 @@ module Adhearsion
|
|
79
81
|
end
|
80
82
|
|
81
83
|
def active_calls
|
82
|
-
@calls
|
84
|
+
if @calls && @calls.alive?
|
85
|
+
@calls
|
86
|
+
else
|
87
|
+
@calls = Calls.new
|
88
|
+
end
|
83
89
|
end
|
84
90
|
|
85
91
|
def status
|
data/lib/adhearsion/call.rb
CHANGED
@@ -8,9 +8,9 @@ module Adhearsion
|
|
8
8
|
#
|
9
9
|
class Call
|
10
10
|
|
11
|
-
Hangup = Class.new
|
11
|
+
Hangup = Class.new Adhearsion::Error
|
12
|
+
CommandTimeout = Class.new Adhearsion::Error
|
12
13
|
ExpiredError = Class.new Celluloid::DeadActorError
|
13
|
-
CommandTimeout = Class.new StandardError
|
14
14
|
|
15
15
|
include Celluloid
|
16
16
|
include HasGuardedHandlers
|
@@ -72,7 +72,7 @@ module Adhearsion
|
|
72
72
|
|
73
73
|
def deliver_message(message)
|
74
74
|
logger.debug "Receiving message: #{message.inspect}"
|
75
|
-
trigger_handler :event, message
|
75
|
+
catching_standard_errors { trigger_handler :event, message }
|
76
76
|
end
|
77
77
|
|
78
78
|
alias << deliver_message
|
@@ -113,7 +113,7 @@ module Adhearsion
|
|
113
113
|
yield component if block_given?
|
114
114
|
|
115
115
|
complete_event = component.complete_event
|
116
|
-
raise
|
116
|
+
raise Adhearsion::Error, [complete_event.reason.details, component.inspect].join(": ") if complete_event.reason.is_a? Punchblock::Event::Complete::Error
|
117
117
|
component
|
118
118
|
end
|
119
119
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module Adhearsion
|
4
4
|
class CallController
|
5
5
|
module Output
|
6
|
-
PlaybackError = Class.new
|
6
|
+
PlaybackError = Class.new Adhearsion::Error # Represents failure to play audio, such as when the sound file cannot be found
|
7
7
|
|
8
8
|
def say(text, options = {})
|
9
9
|
play_ssml(text, options) || output(:text, text.to_s, options)
|
data/lib/adhearsion/calls.rb
CHANGED
@@ -1,17 +1,12 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require 'thread'
|
4
|
-
|
5
3
|
module Adhearsion
|
6
4
|
##
|
7
5
|
# This manages the list of calls the Adhearsion service receives
|
8
|
-
class Calls
|
9
|
-
|
6
|
+
class Calls < Hash
|
7
|
+
include Celluloid
|
10
8
|
|
11
|
-
|
12
|
-
@semaphore = Monitor.new
|
13
|
-
@calls = {}
|
14
|
-
end
|
9
|
+
trap_exit :call_died
|
15
10
|
|
16
11
|
def from_offer(offer)
|
17
12
|
Call.new(offer).tap do |call|
|
@@ -20,63 +15,45 @@ module Adhearsion
|
|
20
15
|
end
|
21
16
|
|
22
17
|
def <<(call)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
self
|
27
|
-
end
|
28
|
-
|
29
|
-
def any?
|
30
|
-
atomically { !calls.empty? }
|
18
|
+
link call
|
19
|
+
self[call.id] = call
|
20
|
+
current_actor
|
31
21
|
end
|
32
22
|
|
33
23
|
def remove_inactive_call(call)
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def clear!
|
44
|
-
atomically { calls.clear }
|
24
|
+
if call_is_dead?(call) != nil
|
25
|
+
call_id = key call
|
26
|
+
delete call_id if call_id
|
27
|
+
elsif call.respond_to?(:id)
|
28
|
+
delete call.id
|
29
|
+
else
|
30
|
+
delete call
|
31
|
+
end
|
45
32
|
end
|
46
33
|
|
47
34
|
def with_tag(tag)
|
48
|
-
|
49
|
-
|
50
|
-
call.tagged_with?(tag) ? calls_with_tag << call : calls_with_tag
|
51
|
-
end
|
35
|
+
find_all do |call|
|
36
|
+
call.tagged_with? tag
|
52
37
|
end
|
53
38
|
end
|
54
39
|
|
55
40
|
def each(&block)
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
def each_pair
|
60
|
-
calls.each_pair { |id, call| yield id, call }
|
61
|
-
end
|
62
|
-
|
63
|
-
def to_a
|
64
|
-
calls.values
|
65
|
-
end
|
66
|
-
|
67
|
-
def to_h
|
68
|
-
calls
|
69
|
-
end
|
70
|
-
|
71
|
-
def method_missing(m, *args)
|
72
|
-
atomically { calls.send m.to_sym, *args }
|
41
|
+
values.each(&block)
|
73
42
|
end
|
74
43
|
|
75
44
|
private
|
76
45
|
|
77
|
-
def
|
78
|
-
|
46
|
+
def call_is_dead?(call)
|
47
|
+
!call.alive?
|
48
|
+
rescue NoMethodError
|
79
49
|
end
|
80
50
|
|
51
|
+
def call_died(call, reason)
|
52
|
+
catching_standard_errors do
|
53
|
+
call_id = key call
|
54
|
+
remove_inactive_call call
|
55
|
+
PunchblockPlugin.client.execute_command Punchblock::Command::Hangup, :async => true, :call_id => call_id
|
56
|
+
end
|
57
|
+
end
|
81
58
|
end
|
82
59
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module Adhearsion
|
4
4
|
class Configuration
|
5
5
|
|
6
|
-
ConfigurationError = Class.new
|
6
|
+
ConfigurationError = Class.new Adhearsion::Error # Error raised while trying to configure a non existent plugin
|
7
7
|
|
8
8
|
##
|
9
9
|
# Initialize the configuration object
|
@@ -45,7 +45,8 @@ module Adhearsion
|
|
45
45
|
Supported levels (in increasing severity) -- :trace < :debug < :info < :warn < :error < :fatal
|
46
46
|
__
|
47
47
|
outputters ["log/adhearsion.log"], :transform => Proc.new { |val| Array(val) }, :desc => <<-__
|
48
|
-
An array of log outputters to use. The default is to log to stdout and log/adhearsion.log
|
48
|
+
An array of log outputters to use. The default is to log to stdout and log/adhearsion.log.
|
49
|
+
Each item must be either a string to use as a filename, or a valid Logging appender (see http://github.com/TwP/logging)
|
49
50
|
__
|
50
51
|
formatter nil, :desc => <<-__
|
51
52
|
A log formatter to apply to all active outputters. If nil, the Adhearsion default formatter will be used.
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
class Object
|
4
|
-
def catching_standard_errors(&block)
|
4
|
+
def catching_standard_errors(l = logger, &block)
|
5
5
|
begin
|
6
6
|
yield
|
7
7
|
rescue StandardError => e
|
8
|
-
Adhearsion::Events.trigger :exception, e
|
8
|
+
Adhearsion::Events.trigger :exception, [e, l]
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -5,7 +5,7 @@ class SimonGame < Adhearsion::CallController
|
|
5
5
|
answer
|
6
6
|
reset
|
7
7
|
loop do
|
8
|
-
|
8
|
+
update_number
|
9
9
|
collect_attempt
|
10
10
|
verify_attempt
|
11
11
|
end
|
@@ -19,20 +19,16 @@ class SimonGame < Adhearsion::CallController
|
|
19
19
|
@number << random_number
|
20
20
|
end
|
21
21
|
|
22
|
-
def say_number
|
23
|
-
update_number
|
24
|
-
say @number
|
25
|
-
end
|
26
|
-
|
27
22
|
def collect_attempt
|
28
|
-
|
23
|
+
result = ask @number, :limit => @number.length
|
24
|
+
@attempt = result.response
|
29
25
|
end
|
30
26
|
|
31
27
|
def verify_attempt
|
32
28
|
if attempt_correct?
|
33
|
-
|
29
|
+
speak 'good'
|
34
30
|
else
|
35
|
-
|
31
|
+
speak "#{@number.length - 1} times wrong, try again smarty"
|
36
32
|
reset
|
37
33
|
end
|
38
34
|
end
|
@@ -8,7 +8,7 @@ module Adhearsion
|
|
8
8
|
DEFAULT_MAX_NUMBER_OF_TRIES = 1
|
9
9
|
DEFAULT_TIMEOUT = 5
|
10
10
|
|
11
|
-
InvalidStructureError = Class.new
|
11
|
+
InvalidStructureError = Class.new Adhearsion::Error
|
12
12
|
|
13
13
|
attr_reader :builder, :timeout, :tries_count, :max_number_of_tries, :terminator, :limit, :interruptible, :status
|
14
14
|
|
data/lib/adhearsion/process.rb
CHANGED
@@ -150,7 +150,7 @@ module Adhearsion
|
|
150
150
|
end
|
151
151
|
|
152
152
|
def dispatch_call_event(event)
|
153
|
-
if call = Adhearsion.active_calls
|
153
|
+
if call = Adhearsion.active_calls[event.call_id]
|
154
154
|
call.deliver_message! event
|
155
155
|
else
|
156
156
|
logger.error "Event received for inactive call #{event.call_id}: #{event.inspect}"
|
data/lib/adhearsion/version.rb
CHANGED
@@ -1,32 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module Adhearsion #:nodoc:
|
4
|
-
VERSION = '2.0.0.
|
5
|
-
|
6
|
-
class PkgVersion
|
7
|
-
include Comparable
|
8
|
-
|
9
|
-
attr_reader :major, :minor, :revision
|
10
|
-
|
11
|
-
def initialize(version = nil)
|
12
|
-
version ||= ""
|
13
|
-
@major, @minor, @revision, @patchlevel = version.split(".", 4).map(&:to_i)
|
14
|
-
@major = 0 unless @major
|
15
|
-
end
|
16
|
-
|
17
|
-
def <=>(other)
|
18
|
-
return @major <=> other.major unless (@major <=> other.major) == 0
|
19
|
-
return @minor <=> other.minor unless (@minor <=> other.minor) == 0
|
20
|
-
return @revision <=> other.revision unless (@revision <=> other.revision) == 0
|
21
|
-
return 0
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.sort
|
25
|
-
self.sort! { |a,b| a <=> b }
|
26
|
-
end
|
27
|
-
|
28
|
-
def to_s
|
29
|
-
"#{@major}.#{@minor}.#{@revision}"
|
30
|
-
end
|
31
|
-
end
|
4
|
+
VERSION = '2.0.0.rc2'
|
32
5
|
end
|
@@ -43,12 +43,19 @@ module Adhearsion
|
|
43
43
|
end
|
44
44
|
|
45
45
|
it "should pass the exception to the events system" do
|
46
|
-
|
46
|
+
latch = CountDownLatch.new 1
|
47
|
+
Adhearsion::Events.exception do |e, l|
|
48
|
+
e.should be_a TestException
|
49
|
+
l.should be subject.logger
|
50
|
+
latch.countdown!
|
51
|
+
end
|
47
52
|
expect_component_execution component
|
48
53
|
subject.record { |rec| raise TestException }
|
49
54
|
component.request!
|
50
55
|
component.execute!
|
51
56
|
component.trigger_event_handler response
|
57
|
+
latch.wait(1).should be true
|
58
|
+
Adhearsion::Events.clear_handlers :exception
|
52
59
|
end
|
53
60
|
end
|
54
61
|
|
@@ -354,7 +354,7 @@ module Adhearsion
|
|
354
354
|
let(:details) { "Oh noes, it's all borked" }
|
355
355
|
|
356
356
|
it "raises the error" do
|
357
|
-
lambda { subject.execute_component_and_await_completion component }.should raise_error(
|
357
|
+
lambda { subject.execute_component_and_await_completion component }.should raise_error(Adhearsion::Error, "#{details}: #{component}")
|
358
358
|
end
|
359
359
|
end
|
360
360
|
|
@@ -424,8 +424,15 @@ describe ExampleCallController do
|
|
424
424
|
it "should capture errors in callbacks" do
|
425
425
|
subject.should_receive(:setup_models).and_raise StandardError
|
426
426
|
subject.should_receive(:clean_up_models).and_raise StandardError
|
427
|
-
|
427
|
+
latch = CountDownLatch.new 4
|
428
|
+
Adhearsion::Events.exception do |e, l|
|
429
|
+
e.should be_a StandardError
|
430
|
+
l.should be subject.logger
|
431
|
+
latch.countdown!
|
432
|
+
end
|
428
433
|
subject.execute!
|
434
|
+
latch.wait(1).should be true
|
435
|
+
Adhearsion::Events.clear_handlers :exception
|
429
436
|
end
|
430
437
|
|
431
438
|
describe "when the controller finishes without a hangup" do
|
@@ -2,6 +2,12 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
+
class BrokenController < Adhearsion::CallController
|
6
|
+
def run
|
7
|
+
raise "Blat!"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
5
11
|
module Adhearsion
|
6
12
|
describe Call do
|
7
13
|
let(:mock_client) { flexmock('Client').tap(&:should_ignore_missing) }
|
@@ -117,6 +123,28 @@ module Adhearsion
|
|
117
123
|
subject << event
|
118
124
|
end
|
119
125
|
end
|
126
|
+
|
127
|
+
context "when raising an exception" do
|
128
|
+
it "does not kill the call actor" do
|
129
|
+
subject.register_event_handler { |e| raise 'foo' }
|
130
|
+
lambda { subject << :foo }.should_not raise_error
|
131
|
+
sleep 1
|
132
|
+
subject.should be_alive
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'passes the exception through the Events system' do
|
136
|
+
latch = CountDownLatch.new 1
|
137
|
+
Adhearsion::Events.exception do |e, l|
|
138
|
+
e.should be_a RuntimeError
|
139
|
+
l.should be subject.logger
|
140
|
+
latch.countdown!
|
141
|
+
end
|
142
|
+
subject.register_event_handler { |e| raise 'foo' }
|
143
|
+
lambda { subject << :foo }.should_not raise_error
|
144
|
+
latch.wait(3).should be true
|
145
|
+
Adhearsion::Events.clear_handlers :exception
|
146
|
+
end
|
147
|
+
end
|
120
148
|
end
|
121
149
|
|
122
150
|
describe "#<<" do
|
@@ -605,6 +633,18 @@ module Adhearsion
|
|
605
633
|
controller_thread = subject.execute_controller mock_controller, latch
|
606
634
|
Adhearsion::Process.important_threads.should include controller_thread
|
607
635
|
end
|
636
|
+
|
637
|
+
it "should pass the exception to the events system" do
|
638
|
+
latch = CountDownLatch.new 1
|
639
|
+
Adhearsion::Events.exception do |e, l|
|
640
|
+
e.should be_a RuntimeError
|
641
|
+
l.should be subject.logger
|
642
|
+
latch.countdown!
|
643
|
+
end
|
644
|
+
subject.execute_controller BrokenController.new(subject), latch
|
645
|
+
latch.wait(3).should be true
|
646
|
+
Adhearsion::Events.clear_handlers :exception
|
647
|
+
end
|
608
648
|
end
|
609
649
|
|
610
650
|
describe "#register_controller" do
|
@@ -4,44 +4,70 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
module Adhearsion
|
6
6
|
describe Calls do
|
7
|
-
before { Adhearsion.active_calls.clear! }
|
8
|
-
|
9
7
|
let(:call) { Adhearsion::Call.new new_offer }
|
10
8
|
|
9
|
+
let(:number_of_calls) { 10 }
|
10
|
+
let :calls do
|
11
|
+
Array.new(number_of_calls) { Adhearsion::Call.new new_offer }
|
12
|
+
end
|
13
|
+
|
11
14
|
def new_offer(call_id = nil, headers = {})
|
12
|
-
Punchblock::Event::Offer.new :call_id => call_id ||
|
15
|
+
Punchblock::Event::Offer.new :call_id => call_id || random_call_id, :headers => headers
|
13
16
|
end
|
14
17
|
|
15
|
-
it 'can create a call and add it to the
|
16
|
-
|
17
|
-
call =
|
18
|
+
it 'can create a call and add it to the collection' do
|
19
|
+
subject.any?.should be == false
|
20
|
+
call = subject.from_offer new_offer
|
18
21
|
call.should be_a Adhearsion::Call
|
19
|
-
|
22
|
+
subject.size.should be == 1
|
23
|
+
subject[call.id].should be call
|
20
24
|
end
|
21
25
|
|
22
|
-
it '#size should return the
|
26
|
+
it '#size should return the number of calls in the collection' do
|
23
27
|
subject.size.should be == 0
|
24
28
|
subject << call
|
25
29
|
subject.size.should be == 1
|
26
30
|
end
|
27
31
|
|
28
|
-
|
29
|
-
number_of_calls
|
30
|
-
calls = Array.new(number_of_calls) { Adhearsion::Call.new new_offer }
|
31
|
-
calls.each { |call| subject << call }
|
32
|
+
describe "removing a call" do
|
33
|
+
let(:deleted_call) { calls[number_of_calls / 2] }
|
32
34
|
|
33
|
-
|
34
|
-
subject.remove_inactive_call deleted_call
|
35
|
-
subject.size.should be == number_of_calls - 1
|
36
|
-
end
|
35
|
+
before { calls.each { |call| subject << call } }
|
37
36
|
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
context "by call object" do
|
38
|
+
before { subject.remove_inactive_call deleted_call }
|
39
|
+
|
40
|
+
it "should remove the call from the collection" do
|
41
|
+
subject.size.should be == number_of_calls - 1
|
42
|
+
subject[deleted_call.id].should be_nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "by dead call object" do
|
47
|
+
before do
|
48
|
+
@call_id = deleted_call.id
|
49
|
+
deleted_call.terminate
|
50
|
+
deleted_call.should_not be_alive
|
51
|
+
subject.remove_inactive_call deleted_call
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should remove the call from the collection" do
|
55
|
+
subject.size.should be == number_of_calls - 1
|
56
|
+
subject[@call_id].should be_nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "by ID" do
|
61
|
+
before { subject.remove_inactive_call deleted_call.id }
|
62
|
+
|
63
|
+
it "should remove the call from the collection" do
|
64
|
+
subject.size.should be == number_of_calls - 1
|
65
|
+
subject[deleted_call.id].should be_nil
|
66
|
+
end
|
67
|
+
end
|
41
68
|
end
|
42
69
|
|
43
70
|
it "finding calls by a tag" do
|
44
|
-
calls = Array.new(3) { Adhearsion::Call.new new_offer }
|
45
71
|
calls.each { |call| subject << call }
|
46
72
|
|
47
73
|
tagged_call = calls.last
|
@@ -56,5 +82,48 @@ module Adhearsion
|
|
56
82
|
subject.size.should be == 2
|
57
83
|
end
|
58
84
|
end
|
85
|
+
|
86
|
+
describe "when a call in the collection crashes" do
|
87
|
+
let(:wrapped_object) { call.wrapped_object }
|
88
|
+
|
89
|
+
before do
|
90
|
+
def wrapped_object.crash_me
|
91
|
+
raise StandardError, "Someone crashed me"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def crash
|
96
|
+
lambda { call.crash_me }.should raise_error(StandardError, "Someone crashed me")
|
97
|
+
sleep 0.5
|
98
|
+
end
|
99
|
+
|
100
|
+
it "is removed from the collection" do
|
101
|
+
call_id = call.id
|
102
|
+
size_before = subject.size
|
103
|
+
|
104
|
+
subject << call
|
105
|
+
subject.size.should be > size_before
|
106
|
+
subject[call_id].should be call
|
107
|
+
|
108
|
+
crash
|
109
|
+
subject.size.should be == size_before
|
110
|
+
subject[call_id].should be_nil
|
111
|
+
end
|
112
|
+
|
113
|
+
it "is sends a hangup command for the call" do
|
114
|
+
call_id = call.id
|
115
|
+
flexmock PunchblockPlugin, :client => flexmock('Client')
|
116
|
+
flexmock(PunchblockPlugin.client).should_receive(:execute_command).once.with(Punchblock::Command::Hangup, :async => true, :call_id => call_id)
|
117
|
+
|
118
|
+
subject << call
|
119
|
+
|
120
|
+
crash
|
121
|
+
end
|
122
|
+
|
123
|
+
it "shuts down the actor" do
|
124
|
+
crash
|
125
|
+
call.should_not be_alive
|
126
|
+
end
|
127
|
+
end
|
59
128
|
end
|
60
129
|
end
|
@@ -5,7 +5,7 @@ require 'spec_helper'
|
|
5
5
|
module Adhearsion
|
6
6
|
describe Adhearsion::Process do
|
7
7
|
before :all do
|
8
|
-
Adhearsion.active_calls.clear
|
8
|
+
Adhearsion.active_calls.clear
|
9
9
|
end
|
10
10
|
|
11
11
|
before :each do
|
@@ -17,6 +17,7 @@ module Adhearsion
|
|
17
17
|
flexmock(Events).should_receive(:trigger_immediately).once.with(:shutdown).ordered
|
18
18
|
Adhearsion::Process.booted
|
19
19
|
Adhearsion::Process.shutdown
|
20
|
+
sleep 0.2
|
20
21
|
end
|
21
22
|
|
22
23
|
it '#stop_when_zero_calls should wait until the list of active calls reaches 0' do
|
@@ -48,14 +49,14 @@ module Adhearsion
|
|
48
49
|
describe "#final_shutdown" do
|
49
50
|
it "should hang up active calls" do
|
50
51
|
3.times do
|
51
|
-
fake_call = flexmock
|
52
|
-
flexmock(fake_call).should_receive(:hangup).once
|
52
|
+
fake_call = flexmock Call.new, :id => random_call_id
|
53
|
+
flexmock(fake_call).should_receive(:hangup!).once
|
53
54
|
Adhearsion.active_calls << fake_call
|
54
55
|
end
|
55
56
|
|
56
57
|
Adhearsion::Process.final_shutdown
|
57
58
|
|
58
|
-
Adhearsion.active_calls.clear
|
59
|
+
Adhearsion.active_calls.clear
|
59
60
|
end
|
60
61
|
|
61
62
|
it "should trigger shutdown handlers synchronously" do
|
@@ -89,6 +90,7 @@ module Adhearsion
|
|
89
90
|
Adhearsion::Process.state_name.should be :stopped
|
90
91
|
flexmock(Adhearsion::Process.instance).should_receive(:die_now!).once
|
91
92
|
Adhearsion::Process.shutdown
|
93
|
+
sleep 0.2
|
92
94
|
end
|
93
95
|
|
94
96
|
it 'should forcibly kill the Adhearsion process on :force_stop' do
|
data/spec/adhearsion_spec.rb
CHANGED
@@ -61,6 +61,16 @@ describe Adhearsion do
|
|
61
61
|
it "should return the same instance each time" do
|
62
62
|
Adhearsion.active_calls.should be Adhearsion.active_calls
|
63
63
|
end
|
64
|
+
|
65
|
+
it "should create a new collection if the existing one dies" do
|
66
|
+
original = Adhearsion.active_calls
|
67
|
+
original.terminate
|
68
|
+
original.should_not be_alive
|
69
|
+
|
70
|
+
current = Adhearsion.active_calls
|
71
|
+
current.should be_alive
|
72
|
+
current.should_not be original
|
73
|
+
end
|
64
74
|
end
|
65
75
|
|
66
76
|
describe "#status" do
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adhearsion
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.
|
4
|
+
version: 2.0.0.rc2
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -12,11 +12,11 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2012-03-
|
15
|
+
date: 2012-03-22 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: bundler
|
19
|
-
requirement: &
|
19
|
+
requirement: &2156226700 !ruby/object:Gem::Requirement
|
20
20
|
none: false
|
21
21
|
requirements:
|
22
22
|
- - ! '>='
|
@@ -24,21 +24,21 @@ dependencies:
|
|
24
24
|
version: 1.0.10
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
|
-
version_requirements: *
|
27
|
+
version_requirements: *2156226700
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: punchblock
|
30
|
-
requirement: &
|
30
|
+
requirement: &2156221520 !ruby/object:Gem::Requirement
|
31
31
|
none: false
|
32
32
|
requirements:
|
33
33
|
- - ! '>='
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version: 0.
|
35
|
+
version: 0.10.0
|
36
36
|
type: :runtime
|
37
37
|
prerelease: false
|
38
|
-
version_requirements: *
|
38
|
+
version_requirements: *2156221520
|
39
39
|
- !ruby/object:Gem::Dependency
|
40
40
|
name: logging
|
41
|
-
requirement: &
|
41
|
+
requirement: &2156220200 !ruby/object:Gem::Requirement
|
42
42
|
none: false
|
43
43
|
requirements:
|
44
44
|
- - ! '>='
|
@@ -46,10 +46,10 @@ dependencies:
|
|
46
46
|
version: 1.6.1
|
47
47
|
type: :runtime
|
48
48
|
prerelease: false
|
49
|
-
version_requirements: *
|
49
|
+
version_requirements: *2156220200
|
50
50
|
- !ruby/object:Gem::Dependency
|
51
51
|
name: adhearsion-loquacious
|
52
|
-
requirement: &
|
52
|
+
requirement: &2156218540 !ruby/object:Gem::Requirement
|
53
53
|
none: false
|
54
54
|
requirements:
|
55
55
|
- - ! '>='
|
@@ -57,10 +57,10 @@ dependencies:
|
|
57
57
|
version: 1.9.0
|
58
58
|
type: :runtime
|
59
59
|
prerelease: false
|
60
|
-
version_requirements: *
|
60
|
+
version_requirements: *2156218540
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: activesupport
|
63
|
-
requirement: &
|
63
|
+
requirement: &2156217580 !ruby/object:Gem::Requirement
|
64
64
|
none: false
|
65
65
|
requirements:
|
66
66
|
- - ! '>='
|
@@ -68,10 +68,10 @@ dependencies:
|
|
68
68
|
version: 3.0.10
|
69
69
|
type: :runtime
|
70
70
|
prerelease: false
|
71
|
-
version_requirements: *
|
71
|
+
version_requirements: *2156217580
|
72
72
|
- !ruby/object:Gem::Dependency
|
73
73
|
name: i18n
|
74
|
-
requirement: &
|
74
|
+
requirement: &2156213900 !ruby/object:Gem::Requirement
|
75
75
|
none: false
|
76
76
|
requirements:
|
77
77
|
- - ! '>='
|
@@ -79,10 +79,10 @@ dependencies:
|
|
79
79
|
version: 0.5.0
|
80
80
|
type: :runtime
|
81
81
|
prerelease: false
|
82
|
-
version_requirements: *
|
82
|
+
version_requirements: *2156213900
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: json
|
85
|
-
requirement: &
|
85
|
+
requirement: &2156213080 !ruby/object:Gem::Requirement
|
86
86
|
none: false
|
87
87
|
requirements:
|
88
88
|
- - ! '>='
|
@@ -90,10 +90,10 @@ dependencies:
|
|
90
90
|
version: '0'
|
91
91
|
type: :runtime
|
92
92
|
prerelease: false
|
93
|
-
version_requirements: *
|
93
|
+
version_requirements: *2156213080
|
94
94
|
- !ruby/object:Gem::Dependency
|
95
95
|
name: thor
|
96
|
-
requirement: &
|
96
|
+
requirement: &2156212120 !ruby/object:Gem::Requirement
|
97
97
|
none: false
|
98
98
|
requirements:
|
99
99
|
- - ! '>='
|
@@ -101,10 +101,10 @@ dependencies:
|
|
101
101
|
version: '0'
|
102
102
|
type: :runtime
|
103
103
|
prerelease: false
|
104
|
-
version_requirements: *
|
104
|
+
version_requirements: *2156212120
|
105
105
|
- !ruby/object:Gem::Dependency
|
106
106
|
name: rake
|
107
|
-
requirement: &
|
107
|
+
requirement: &2156211580 !ruby/object:Gem::Requirement
|
108
108
|
none: false
|
109
109
|
requirements:
|
110
110
|
- - ! '>='
|
@@ -112,10 +112,10 @@ dependencies:
|
|
112
112
|
version: '0'
|
113
113
|
type: :runtime
|
114
114
|
prerelease: false
|
115
|
-
version_requirements: *
|
115
|
+
version_requirements: *2156211580
|
116
116
|
- !ruby/object:Gem::Dependency
|
117
117
|
name: pry
|
118
|
-
requirement: &
|
118
|
+
requirement: &2156210340 !ruby/object:Gem::Requirement
|
119
119
|
none: false
|
120
120
|
requirements:
|
121
121
|
- - ! '>='
|
@@ -123,10 +123,10 @@ dependencies:
|
|
123
123
|
version: '0'
|
124
124
|
type: :runtime
|
125
125
|
prerelease: false
|
126
|
-
version_requirements: *
|
126
|
+
version_requirements: *2156210340
|
127
127
|
- !ruby/object:Gem::Dependency
|
128
128
|
name: uuid
|
129
|
-
requirement: &
|
129
|
+
requirement: &2156209660 !ruby/object:Gem::Requirement
|
130
130
|
none: false
|
131
131
|
requirements:
|
132
132
|
- - ! '>='
|
@@ -134,10 +134,10 @@ dependencies:
|
|
134
134
|
version: '0'
|
135
135
|
type: :runtime
|
136
136
|
prerelease: false
|
137
|
-
version_requirements: *
|
137
|
+
version_requirements: *2156209660
|
138
138
|
- !ruby/object:Gem::Dependency
|
139
139
|
name: future-resource
|
140
|
-
requirement: &
|
140
|
+
requirement: &2156208320 !ruby/object:Gem::Requirement
|
141
141
|
none: false
|
142
142
|
requirements:
|
143
143
|
- - ! '>='
|
@@ -145,10 +145,10 @@ dependencies:
|
|
145
145
|
version: 0.0.2
|
146
146
|
type: :runtime
|
147
147
|
prerelease: false
|
148
|
-
version_requirements: *
|
148
|
+
version_requirements: *2156208320
|
149
149
|
- !ruby/object:Gem::Dependency
|
150
150
|
name: ruby_speech
|
151
|
-
requirement: &
|
151
|
+
requirement: &2156207180 !ruby/object:Gem::Requirement
|
152
152
|
none: false
|
153
153
|
requirements:
|
154
154
|
- - ! '>='
|
@@ -156,10 +156,10 @@ dependencies:
|
|
156
156
|
version: 0.4.0
|
157
157
|
type: :runtime
|
158
158
|
prerelease: false
|
159
|
-
version_requirements: *
|
159
|
+
version_requirements: *2156207180
|
160
160
|
- !ruby/object:Gem::Dependency
|
161
161
|
name: countdownlatch
|
162
|
-
requirement: &
|
162
|
+
requirement: &2156193500 !ruby/object:Gem::Requirement
|
163
163
|
none: false
|
164
164
|
requirements:
|
165
165
|
- - ! '>='
|
@@ -167,10 +167,10 @@ dependencies:
|
|
167
167
|
version: '0'
|
168
168
|
type: :runtime
|
169
169
|
prerelease: false
|
170
|
-
version_requirements: *
|
170
|
+
version_requirements: *2156193500
|
171
171
|
- !ruby/object:Gem::Dependency
|
172
172
|
name: has-guarded-handlers
|
173
|
-
requirement: &
|
173
|
+
requirement: &2156188320 !ruby/object:Gem::Requirement
|
174
174
|
none: false
|
175
175
|
requirements:
|
176
176
|
- - ! '>='
|
@@ -178,10 +178,10 @@ dependencies:
|
|
178
178
|
version: 1.1.0
|
179
179
|
type: :runtime
|
180
180
|
prerelease: false
|
181
|
-
version_requirements: *
|
181
|
+
version_requirements: *2156188320
|
182
182
|
- !ruby/object:Gem::Dependency
|
183
183
|
name: girl_friday
|
184
|
-
requirement: &
|
184
|
+
requirement: &2156187600 !ruby/object:Gem::Requirement
|
185
185
|
none: false
|
186
186
|
requirements:
|
187
187
|
- - ! '>='
|
@@ -189,10 +189,10 @@ dependencies:
|
|
189
189
|
version: '0'
|
190
190
|
type: :runtime
|
191
191
|
prerelease: false
|
192
|
-
version_requirements: *
|
192
|
+
version_requirements: *2156187600
|
193
193
|
- !ruby/object:Gem::Dependency
|
194
194
|
name: ffi
|
195
|
-
requirement: &
|
195
|
+
requirement: &2156186680 !ruby/object:Gem::Requirement
|
196
196
|
none: false
|
197
197
|
requirements:
|
198
198
|
- - ! '>='
|
@@ -200,10 +200,10 @@ dependencies:
|
|
200
200
|
version: 1.0.11
|
201
201
|
type: :runtime
|
202
202
|
prerelease: false
|
203
|
-
version_requirements: *
|
203
|
+
version_requirements: *2156186680
|
204
204
|
- !ruby/object:Gem::Dependency
|
205
205
|
name: celluloid
|
206
|
-
requirement: &
|
206
|
+
requirement: &2156186020 !ruby/object:Gem::Requirement
|
207
207
|
none: false
|
208
208
|
requirements:
|
209
209
|
- - ! '>='
|
@@ -211,10 +211,10 @@ dependencies:
|
|
211
211
|
version: 0.9.0
|
212
212
|
type: :runtime
|
213
213
|
prerelease: false
|
214
|
-
version_requirements: *
|
214
|
+
version_requirements: *2156186020
|
215
215
|
- !ruby/object:Gem::Dependency
|
216
216
|
name: deep_merge
|
217
|
-
requirement: &
|
217
|
+
requirement: &2152014220 !ruby/object:Gem::Requirement
|
218
218
|
none: false
|
219
219
|
requirements:
|
220
220
|
- - ! '>='
|
@@ -222,10 +222,10 @@ dependencies:
|
|
222
222
|
version: '0'
|
223
223
|
type: :runtime
|
224
224
|
prerelease: false
|
225
|
-
version_requirements: *
|
225
|
+
version_requirements: *2152014220
|
226
226
|
- !ruby/object:Gem::Dependency
|
227
227
|
name: rspec
|
228
|
-
requirement: &
|
228
|
+
requirement: &2152012400 !ruby/object:Gem::Requirement
|
229
229
|
none: false
|
230
230
|
requirements:
|
231
231
|
- - ~>
|
@@ -233,10 +233,10 @@ dependencies:
|
|
233
233
|
version: 2.7.0
|
234
234
|
type: :development
|
235
235
|
prerelease: false
|
236
|
-
version_requirements: *
|
236
|
+
version_requirements: *2152012400
|
237
237
|
- !ruby/object:Gem::Dependency
|
238
238
|
name: flexmock
|
239
|
-
requirement: &
|
239
|
+
requirement: &2152011380 !ruby/object:Gem::Requirement
|
240
240
|
none: false
|
241
241
|
requirements:
|
242
242
|
- - ! '>='
|
@@ -244,10 +244,10 @@ dependencies:
|
|
244
244
|
version: '0'
|
245
245
|
type: :development
|
246
246
|
prerelease: false
|
247
|
-
version_requirements: *
|
247
|
+
version_requirements: *2152011380
|
248
248
|
- !ruby/object:Gem::Dependency
|
249
249
|
name: activerecord
|
250
|
-
requirement: &
|
250
|
+
requirement: &2152009540 !ruby/object:Gem::Requirement
|
251
251
|
none: false
|
252
252
|
requirements:
|
253
253
|
- - ! '>='
|
@@ -255,10 +255,10 @@ dependencies:
|
|
255
255
|
version: 3.0.10
|
256
256
|
type: :development
|
257
257
|
prerelease: false
|
258
|
-
version_requirements: *
|
258
|
+
version_requirements: *2152009540
|
259
259
|
- !ruby/object:Gem::Dependency
|
260
260
|
name: simplecov
|
261
|
-
requirement: &
|
261
|
+
requirement: &2152008640 !ruby/object:Gem::Requirement
|
262
262
|
none: false
|
263
263
|
requirements:
|
264
264
|
- - ! '>='
|
@@ -266,10 +266,10 @@ dependencies:
|
|
266
266
|
version: '0'
|
267
267
|
type: :development
|
268
268
|
prerelease: false
|
269
|
-
version_requirements: *
|
269
|
+
version_requirements: *2152008640
|
270
270
|
- !ruby/object:Gem::Dependency
|
271
271
|
name: simplecov-rcov
|
272
|
-
requirement: &
|
272
|
+
requirement: &2152007400 !ruby/object:Gem::Requirement
|
273
273
|
none: false
|
274
274
|
requirements:
|
275
275
|
- - ! '>='
|
@@ -277,10 +277,10 @@ dependencies:
|
|
277
277
|
version: '0'
|
278
278
|
type: :development
|
279
279
|
prerelease: false
|
280
|
-
version_requirements: *
|
280
|
+
version_requirements: *2152007400
|
281
281
|
- !ruby/object:Gem::Dependency
|
282
282
|
name: ci_reporter
|
283
|
-
requirement: &
|
283
|
+
requirement: &2152006220 !ruby/object:Gem::Requirement
|
284
284
|
none: false
|
285
285
|
requirements:
|
286
286
|
- - ! '>='
|
@@ -288,10 +288,10 @@ dependencies:
|
|
288
288
|
version: '0'
|
289
289
|
type: :development
|
290
290
|
prerelease: false
|
291
|
-
version_requirements: *
|
291
|
+
version_requirements: *2152006220
|
292
292
|
- !ruby/object:Gem::Dependency
|
293
293
|
name: yard
|
294
|
-
requirement: &
|
294
|
+
requirement: &2156172140 !ruby/object:Gem::Requirement
|
295
295
|
none: false
|
296
296
|
requirements:
|
297
297
|
- - ! '>='
|
@@ -299,10 +299,10 @@ dependencies:
|
|
299
299
|
version: '0'
|
300
300
|
type: :development
|
301
301
|
prerelease: false
|
302
|
-
version_requirements: *
|
302
|
+
version_requirements: *2156172140
|
303
303
|
- !ruby/object:Gem::Dependency
|
304
304
|
name: guard-rspec
|
305
|
-
requirement: &
|
305
|
+
requirement: &2156170840 !ruby/object:Gem::Requirement
|
306
306
|
none: false
|
307
307
|
requirements:
|
308
308
|
- - ! '>='
|
@@ -310,10 +310,10 @@ dependencies:
|
|
310
310
|
version: '0'
|
311
311
|
type: :development
|
312
312
|
prerelease: false
|
313
|
-
version_requirements: *
|
313
|
+
version_requirements: *2156170840
|
314
314
|
- !ruby/object:Gem::Dependency
|
315
315
|
name: guard-cucumber
|
316
|
-
requirement: &
|
316
|
+
requirement: &2156169560 !ruby/object:Gem::Requirement
|
317
317
|
none: false
|
318
318
|
requirements:
|
319
319
|
- - ! '>='
|
@@ -321,10 +321,10 @@ dependencies:
|
|
321
321
|
version: '0'
|
322
322
|
type: :development
|
323
323
|
prerelease: false
|
324
|
-
version_requirements: *
|
324
|
+
version_requirements: *2156169560
|
325
325
|
- !ruby/object:Gem::Dependency
|
326
326
|
name: ruby_gntp
|
327
|
-
requirement: &
|
327
|
+
requirement: &2156167960 !ruby/object:Gem::Requirement
|
328
328
|
none: false
|
329
329
|
requirements:
|
330
330
|
- - ! '>='
|
@@ -332,10 +332,10 @@ dependencies:
|
|
332
332
|
version: '0'
|
333
333
|
type: :development
|
334
334
|
prerelease: false
|
335
|
-
version_requirements: *
|
335
|
+
version_requirements: *2156167960
|
336
336
|
- !ruby/object:Gem::Dependency
|
337
337
|
name: cucumber
|
338
|
-
requirement: &
|
338
|
+
requirement: &2156120960 !ruby/object:Gem::Requirement
|
339
339
|
none: false
|
340
340
|
requirements:
|
341
341
|
- - ! '>='
|
@@ -343,10 +343,10 @@ dependencies:
|
|
343
343
|
version: '0'
|
344
344
|
type: :development
|
345
345
|
prerelease: false
|
346
|
-
version_requirements: *
|
346
|
+
version_requirements: *2156120960
|
347
347
|
- !ruby/object:Gem::Dependency
|
348
348
|
name: aruba
|
349
|
-
requirement: &
|
349
|
+
requirement: &2156118080 !ruby/object:Gem::Requirement
|
350
350
|
none: false
|
351
351
|
requirements:
|
352
352
|
- - ! '>='
|
@@ -354,7 +354,7 @@ dependencies:
|
|
354
354
|
version: '0'
|
355
355
|
type: :development
|
356
356
|
prerelease: false
|
357
|
-
version_requirements: *
|
357
|
+
version_requirements: *2156118080
|
358
358
|
description: Adhearsion is an open-source telephony development framework
|
359
359
|
email: dev&Adhearsion.com
|
360
360
|
executables:
|
@@ -517,7 +517,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
517
517
|
version: '0'
|
518
518
|
segments:
|
519
519
|
- 0
|
520
|
-
hash: -
|
520
|
+
hash: -2676474875029582124
|
521
521
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
522
522
|
none: false
|
523
523
|
requirements:
|