adhearsion 2.0.0.rc1 → 2.0.0.rc2

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