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.
@@ -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`
@@ -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.9.1"]
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"]
@@ -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 ||= Calls.new
84
+ if @calls && @calls.alive?
85
+ @calls
86
+ else
87
+ @calls = Calls.new
88
+ end
83
89
  end
84
90
 
85
91
  def status
@@ -8,9 +8,9 @@ module Adhearsion
8
8
  #
9
9
  class Call
10
10
 
11
- Hangup = Class.new StandardError
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 StandardError, [complete_event.reason.details, component.inspect].join(": ") if complete_event.reason.is_a? Punchblock::Event::Complete::Error
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 StandardError # Represents failure to play audio, such as when the sound file cannot be found
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)
@@ -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
- attr_reader :semaphore, :calls
6
+ class Calls < Hash
7
+ include Celluloid
10
8
 
11
- def initialize
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
- atomically do
24
- calls[call.id] = call
25
- end
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
- atomically { calls.delete call.id }
35
- end
36
-
37
- # Searches all active calls by their id
38
- def find(id)
39
- atomically { calls[id] }
40
- end
41
- alias :[] :find
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
- atomically do
49
- calls.inject([]) do |calls_with_tag,(_,call)|
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
- atomically { calls.values.each(&block) }
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 atomically(&block)
78
- semaphore.synchronize(&block)
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 StandardError # Error raised while trying to configure a non existent plugin
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
- say_number
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
- @attempt = input @number.length
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
- say 'good'
29
+ speak 'good'
34
30
  else
35
- say "#{@number.length - 1} times wrong, try again smarty"
31
+ speak "#{@number.length - 1} times wrong, try again smarty"
36
32
  reset
37
33
  end
38
34
  end
@@ -299,6 +299,6 @@ module Adhearsion
299
299
  end
300
300
  end
301
301
 
302
- InitializationFailedError = Class.new StandardError
302
+ InitializationFailedError = Class.new Adhearsion::Error
303
303
  end
304
304
  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 StandardError
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
 
@@ -74,7 +74,7 @@ module Adhearsion
74
74
 
75
75
  def final_shutdown
76
76
  Adhearsion.active_calls.each do |call|
77
- call.hangup
77
+ call.hangup!
78
78
  end
79
79
 
80
80
  # This should shut down any remaining threads. Once those threads have
@@ -150,7 +150,7 @@ module Adhearsion
150
150
  end
151
151
 
152
152
  def dispatch_call_event(event)
153
- if call = Adhearsion.active_calls.find(event.call_id)
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}"
@@ -1,32 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Adhearsion #:nodoc:
4
- VERSION = '2.0.0.rc1'
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
- flexmock(Events).should_receive(:trigger).once.with(:exception, TestException)
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(StandardError, "#{details}: #{component}")
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
- flexmock(Adhearsion::Events).should_receive(:trigger).times(4).with :exception, StandardError
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 || rand, :headers => headers
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 active calls' do
16
- Adhearsion.active_calls.any?.should be == false
17
- call = Adhearsion.active_calls.from_offer new_offer
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
- Adhearsion.active_calls.size.should be == 1
22
+ subject.size.should be == 1
23
+ subject[call.id].should be call
20
24
  end
21
25
 
22
- it '#size should return the size of the collection' do
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
- it '#remove_inactive_call should delete the call in the Hash' do
29
- number_of_calls = 10
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
- deleted_call = calls[number_of_calls / 2]
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
- it '#find should pull the Call from the Hash using the id' do
39
- subject << call
40
- subject.find(call.id).should be call
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 Object.new, :id => rand
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
@@ -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
@@ -70,3 +70,4 @@ end
70
70
  def new_uuid
71
71
  UUID.new.generate.to_s
72
72
  end
73
+ alias :random_call_id :new_uuid
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.rc1
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-20 00:00:00.000000000 Z
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: &2160607180 !ruby/object:Gem::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: *2160607180
27
+ version_requirements: *2156226700
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: punchblock
30
- requirement: &2160605540 !ruby/object:Gem::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.9.1
35
+ version: 0.10.0
36
36
  type: :runtime
37
37
  prerelease: false
38
- version_requirements: *2160605540
38
+ version_requirements: *2156221520
39
39
  - !ruby/object:Gem::Dependency
40
40
  name: logging
41
- requirement: &2160604040 !ruby/object:Gem::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: *2160604040
49
+ version_requirements: *2156220200
50
50
  - !ruby/object:Gem::Dependency
51
51
  name: adhearsion-loquacious
52
- requirement: &2160578160 !ruby/object:Gem::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: *2160578160
60
+ version_requirements: *2156218540
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: activesupport
63
- requirement: &2160576060 !ruby/object:Gem::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: *2160576060
71
+ version_requirements: *2156217580
72
72
  - !ruby/object:Gem::Dependency
73
73
  name: i18n
74
- requirement: &2160574920 !ruby/object:Gem::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: *2160574920
82
+ version_requirements: *2156213900
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: json
85
- requirement: &2160574020 !ruby/object:Gem::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: *2160574020
93
+ version_requirements: *2156213080
94
94
  - !ruby/object:Gem::Dependency
95
95
  name: thor
96
- requirement: &2160571980 !ruby/object:Gem::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: *2160571980
104
+ version_requirements: *2156212120
105
105
  - !ruby/object:Gem::Dependency
106
106
  name: rake
107
- requirement: &2160571280 !ruby/object:Gem::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: *2160571280
115
+ version_requirements: *2156211580
116
116
  - !ruby/object:Gem::Dependency
117
117
  name: pry
118
- requirement: &2160570360 !ruby/object:Gem::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: *2160570360
126
+ version_requirements: *2156210340
127
127
  - !ruby/object:Gem::Dependency
128
128
  name: uuid
129
- requirement: &2160532560 !ruby/object:Gem::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: *2160532560
137
+ version_requirements: *2156209660
138
138
  - !ruby/object:Gem::Dependency
139
139
  name: future-resource
140
- requirement: &2160531060 !ruby/object:Gem::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: *2160531060
148
+ version_requirements: *2156208320
149
149
  - !ruby/object:Gem::Dependency
150
150
  name: ruby_speech
151
- requirement: &2160530200 !ruby/object:Gem::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: *2160530200
159
+ version_requirements: *2156207180
160
160
  - !ruby/object:Gem::Dependency
161
161
  name: countdownlatch
162
- requirement: &2160529380 !ruby/object:Gem::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: *2160529380
170
+ version_requirements: *2156193500
171
171
  - !ruby/object:Gem::Dependency
172
172
  name: has-guarded-handlers
173
- requirement: &2160528360 !ruby/object:Gem::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: *2160528360
181
+ version_requirements: *2156188320
182
182
  - !ruby/object:Gem::Dependency
183
183
  name: girl_friday
184
- requirement: &2160527640 !ruby/object:Gem::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: *2160527640
192
+ version_requirements: *2156187600
193
193
  - !ruby/object:Gem::Dependency
194
194
  name: ffi
195
- requirement: &2160526260 !ruby/object:Gem::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: *2160526260
203
+ version_requirements: *2156186680
204
204
  - !ruby/object:Gem::Dependency
205
205
  name: celluloid
206
- requirement: &2160525580 !ruby/object:Gem::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: *2160525580
214
+ version_requirements: *2156186020
215
215
  - !ruby/object:Gem::Dependency
216
216
  name: deep_merge
217
- requirement: &2160504660 !ruby/object:Gem::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: *2160504660
225
+ version_requirements: *2152014220
226
226
  - !ruby/object:Gem::Dependency
227
227
  name: rspec
228
- requirement: &2160503420 !ruby/object:Gem::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: *2160503420
236
+ version_requirements: *2152012400
237
237
  - !ruby/object:Gem::Dependency
238
238
  name: flexmock
239
- requirement: &2160502300 !ruby/object:Gem::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: *2160502300
247
+ version_requirements: *2152011380
248
248
  - !ruby/object:Gem::Dependency
249
249
  name: activerecord
250
- requirement: &2160498180 !ruby/object:Gem::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: *2160498180
258
+ version_requirements: *2152009540
259
259
  - !ruby/object:Gem::Dependency
260
260
  name: simplecov
261
- requirement: &2160497260 !ruby/object:Gem::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: *2160497260
269
+ version_requirements: *2152008640
270
270
  - !ruby/object:Gem::Dependency
271
271
  name: simplecov-rcov
272
- requirement: &2160471000 !ruby/object:Gem::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: *2160471000
280
+ version_requirements: *2152007400
281
281
  - !ruby/object:Gem::Dependency
282
282
  name: ci_reporter
283
- requirement: &2160469500 !ruby/object:Gem::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: *2160469500
291
+ version_requirements: *2152006220
292
292
  - !ruby/object:Gem::Dependency
293
293
  name: yard
294
- requirement: &2160468520 !ruby/object:Gem::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: *2160468520
302
+ version_requirements: *2156172140
303
303
  - !ruby/object:Gem::Dependency
304
304
  name: guard-rspec
305
- requirement: &2160466580 !ruby/object:Gem::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: *2160466580
313
+ version_requirements: *2156170840
314
314
  - !ruby/object:Gem::Dependency
315
315
  name: guard-cucumber
316
- requirement: &2160464820 !ruby/object:Gem::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: *2160464820
324
+ version_requirements: *2156169560
325
325
  - !ruby/object:Gem::Dependency
326
326
  name: ruby_gntp
327
- requirement: &2160436460 !ruby/object:Gem::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: *2160436460
335
+ version_requirements: *2156167960
336
336
  - !ruby/object:Gem::Dependency
337
337
  name: cucumber
338
- requirement: &2160435420 !ruby/object:Gem::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: *2160435420
346
+ version_requirements: *2156120960
347
347
  - !ruby/object:Gem::Dependency
348
348
  name: aruba
349
- requirement: &2160434400 !ruby/object:Gem::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: *2160434400
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: -1319504717136623069
520
+ hash: -2676474875029582124
521
521
  required_rubygems_version: !ruby/object:Gem::Requirement
522
522
  none: false
523
523
  requirements: