punchblock 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6fd9d8e6a3b698f31b5807e789454fc7231ed468
4
- data.tar.gz: 4128a656a2bbbba2a1dedf0cb9a8a7269a8f73be
3
+ metadata.gz: b8dddb3e5a8b1158136add6d851f6f40fbe94438
4
+ data.tar.gz: ff999c1ed2536e739167e74ab6d9ac96c188f0e9
5
5
  SHA512:
6
- metadata.gz: a89def0af7a9299fe9278115c9495694c7092d34b54d6a20148e00761999b484a21682b9ed867dd3880e5720177a7e8341f5487677f0aa9d38df28d268d17f9d
7
- data.tar.gz: 9a6a06392dc2c41a29f55443c2093d1505be65974f2796308ce9ea3b3b1e02b5b6b198ff634e7794d27d89319ceede8d73dcd1de157b4b2aeae01e3645b50bff
6
+ metadata.gz: 8817401f7029230cc46119a8fabe2a525b72c0af9375eb09127dfbbf8855617ac1a553b2fca2699accec6311df9d9bb378a6dff5322a9df0b26e6a994d2f66fb
7
+ data.tar.gz: 43668278a0c3943259fbbc75f4b0704e6cc617d41fb2f405b3b0fac1d6aa8093ea78bbf24a8c868b55b3ccced90da00648af8d3b5a18163cecb074dd1b845510
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # [develop](https://github.com/adhearsion/punchblock)
2
2
 
3
+ # [v2.0.2](https://github.com/adhearsion/punchblock/compare/v2.0.1...v2.0.2) - [2013-10-17](https://rubygems.org/gems/punchblock/versions/2.0.2)
4
+ * Bugfix: Reject commands against components which have finished on Asterisk, and garbage collect them
5
+ * Bugfix: Register/lookup components by their full URI rather than component ID since the component ID may only be unique per call
6
+ * Bugfix: Hold back Virtus dependency to avoid API-breaking changes
7
+
3
8
  # [v2.0.1](https://github.com/adhearsion/punchblock/compare/v2.0.0...v2.0.1) - [2013-09-17](https://rubygems.org/gems/punchblock/versions/2.0.1)
4
9
  * Bugfix: Allow audio file URIs with file extensions on Asterisk
5
10
  * Bugfix: Input timers were being started before output finished on Asterisk composed prompts
data/Guardfile CHANGED
@@ -4,6 +4,6 @@ guard 'rspec', :cli => '--format documentation' do
4
4
  watch('spec/spec_helper.rb') { "spec/" }
5
5
  end
6
6
 
7
- guard 'rake', task: 'benchmark' do
7
+ guard 'rake', task: 'benchmark', run_on_start: false do
8
8
  watch(/benchmarks\/*/)
9
9
  end
@@ -38,8 +38,8 @@ module Punchblock
38
38
  component_registry << component
39
39
  end
40
40
 
41
- def find_component_by_id(component_id)
42
- component_registry.find_by_id component_id
41
+ def find_component_by_uri(uri)
42
+ component_registry.find_by_uri uri
43
43
  end
44
44
 
45
45
  def delete_component_registration(component)
@@ -10,20 +10,20 @@ module Punchblock
10
10
 
11
11
  def <<(component)
12
12
  @mutex.synchronize do
13
- @components[component.component_id] = component
13
+ @components[component.source_uri] = component
14
14
  end
15
15
  end
16
16
 
17
- def find_by_id(component_id)
17
+ def find_by_uri(uri)
18
18
  @mutex.synchronize do
19
- @components[component_id]
19
+ @components[uri]
20
20
  end
21
21
  end
22
22
 
23
23
  def delete(component)
24
24
  @mutex.synchronize do
25
- id = @components.key component
26
- @components.delete id
25
+ uri = @components.key component
26
+ @components.delete uri
27
27
  end
28
28
  end
29
29
  end
@@ -38,6 +38,7 @@ module Punchblock
38
38
  def response=(other)
39
39
  if other.is_a?(Ref)
40
40
  @component_id = other.component_id
41
+ @source_uri = other.uri.to_s
41
42
  client.register_component self if client
42
43
  end
43
44
  super
@@ -28,10 +28,10 @@ module Punchblock
28
28
  # @return [Float] Indicates how sensitive the interpreter should be to loud versus quiet input. Higher values represent greater sensitivity.
29
29
  attribute :sensitivity, Float
30
30
 
31
- # @return [Integer] Indicates the amount of time preceding input which may expire before a timeout is triggered.
31
+ # @return [Integer] Indicates the amount of time (in milliseconds) preceding input which may expire before a timeout is triggered.
32
32
  attribute :initial_timeout, Integer
33
33
 
34
- # @return [Integer] Indicates (in the case of DTMF input) the amount of time between input digits which may expire before a timeout is triggered.
34
+ # @return [Integer] Indicates (in the case of DTMF input) the amount of time (in milliseconds) between input digits which may expire before a timeout is triggered.
35
35
  attribute :inter_digit_timeout, Integer
36
36
 
37
37
  attribute :grammars, Array, default: []
@@ -10,7 +10,7 @@ module Blather
10
10
  def rayo_node
11
11
  @rayo_node ||= begin
12
12
  first_child = at_xpath RAYO_NODE_PATH, Punchblock::RAYO_NAMESPACES
13
- Punchblock::RayoNode.from_xml first_child, nil, component_id if first_child
13
+ Punchblock::RayoNode.from_xml first_child, nil, component_id, "xmpp:#{from}" if first_child
14
14
  end
15
15
  end
16
16
 
@@ -14,6 +14,7 @@ module Punchblock
14
14
  attribute :target_call_id
15
15
  attribute :target_mixer_name
16
16
  attribute :component_id
17
+ attribute :source_uri
17
18
  attribute :domain
18
19
  attribute :transport
19
20
 
@@ -48,7 +49,7 @@ module Punchblock
48
49
  # elements of the XML::Node
49
50
  # @param [XML::Node] node the node to import
50
51
  # @return the appropriate object based on the node name and namespace
51
- def self.from_xml(node, call_id = nil, component_id = nil)
52
+ def self.from_xml(node, call_id = nil, component_id = nil, uri = nil)
52
53
  ns = (node.namespace.href if node.namespace)
53
54
  klass = class_from_registration(node.name, ns)
54
55
  if klass && klass != self
@@ -58,6 +59,7 @@ module Punchblock
58
59
  end.tap do |event|
59
60
  event.target_call_id = call_id
60
61
  event.component_id = component_id
62
+ event.source_uri = uri
61
63
  end
62
64
  end
63
65
 
@@ -85,7 +87,7 @@ module Punchblock
85
87
  # @return [RayoNode] the original command issued that lead to this event
86
88
  #
87
89
  def source
88
- @source ||= client.find_component_by_id component_id if client && component_id
90
+ @source ||= client.find_component_by_uri source_uri if client && source_uri
89
91
  @source ||= original_component
90
92
  end
91
93
 
@@ -291,10 +291,10 @@ module Punchblock
291
291
  end
292
292
 
293
293
  def actor_died(actor, reason)
294
- return unless reason
295
294
  if id = @components.key(actor)
296
295
  @components.delete id
297
- complete_event = Punchblock::Event::Complete.new :component_id => id, :reason => Punchblock::Event::Complete::Error.new
296
+ return unless reason
297
+ complete_event = Punchblock::Event::Complete.new :component_id => id, source_uri: id, :reason => Punchblock::Event::Complete::Error.new
298
298
  send_pb_event complete_event
299
299
  end
300
300
  end
@@ -48,6 +48,7 @@ module Punchblock
48
48
  def send_event(event)
49
49
  event.component_id = id
50
50
  event.target_call_id = call_id
51
+ event.source_uri = id
51
52
  safe_from_dead_actors { translator.handle_pb_event event }
52
53
  end
53
54
 
@@ -236,7 +236,7 @@ module Punchblock
236
236
  pb_logger.error "A linked actor (#{actor.inspect}) died due to #{reason.inspect}"
237
237
  if id = @components.key(actor)
238
238
  @components.delete id
239
- complete_event = Punchblock::Event::Complete.new :component_id => id, :reason => Punchblock::Event::Complete::Error.new
239
+ complete_event = Punchblock::Event::Complete.new :component_id => id, source_uri: id, :reason => Punchblock::Event::Complete::Error.new
240
240
  send_pb_event complete_event
241
241
  end
242
242
  end
@@ -53,6 +53,7 @@ module Punchblock
53
53
  def send_event(event)
54
54
  event.component_id = id
55
55
  event.target_call_id = call_id
56
+ event.source_uri = id
56
57
  safe_from_dead_actors { translator.handle_pb_event event }
57
58
  end
58
59
 
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Punchblock
4
- VERSION = "2.0.1"
4
+ VERSION = "2.0.2"
5
5
  end
data/punchblock.gemspec CHANGED
@@ -32,7 +32,7 @@ Gem::Specification.new do |s|
32
32
  s.add_runtime_dependency %q<ruby_ami>, ["~> 2.0"]
33
33
  s.add_runtime_dependency %q<ruby_fs>, ["~> 1.1"]
34
34
  s.add_runtime_dependency %q<ruby_speech>, ["~> 2.0"]
35
- s.add_runtime_dependency %q<virtus>
35
+ s.add_runtime_dependency %q<virtus>, ["~> 0.5"]
36
36
  s.add_runtime_dependency %q<ruby_jid>, ["~> 1.0"]
37
37
 
38
38
  s.add_development_dependency %q<bundler>, ["~> 1.0"]
@@ -5,19 +5,19 @@ require 'spec_helper'
5
5
  module Punchblock
6
6
  class Client
7
7
  describe ComponentRegistry do
8
- let(:component_id) { 'abc123' }
9
- let(:component) { double 'Component', :component_id => component_id }
8
+ let(:uri) { 'abc123' }
9
+ let(:component) { double 'Component', source_uri: uri }
10
10
 
11
11
  it 'should store components and allow lookup by ID' do
12
12
  subject << component
13
- subject.find_by_id(component_id).should be component
13
+ subject.find_by_uri(uri).should be component
14
14
  end
15
15
 
16
16
  it 'should allow deletion of components' do
17
17
  subject << component
18
- subject.find_by_id(component_id).should be component
18
+ subject.find_by_uri(uri).should be component
19
19
  subject.delete component
20
- subject.find_by_id(component_id).should be_nil
20
+ subject.find_by_uri(uri).should be_nil
21
21
  end
22
22
  end
23
23
  end
@@ -14,7 +14,8 @@ module Punchblock
14
14
  let(:call_id) { 'abc123' }
15
15
  let(:mock_event) { double('Event').as_null_object }
16
16
  let(:component_id) { 'abc123' }
17
- let(:mock_component) { double 'Component', :component_id => component_id }
17
+ let(:component_uri) { 'callid@server/abc123' }
18
+ let(:mock_component) { double 'Component', source_uri: component_uri }
18
19
  let(:mock_command) { double 'Command' }
19
20
 
20
21
  describe '#run' do
@@ -77,7 +78,7 @@ module Punchblock
77
78
 
78
79
  it 'should be able to register and retrieve components' do
79
80
  subject.register_component mock_component
80
- subject.find_component_by_id(component_id).should be mock_component
81
+ subject.find_component_by_uri(component_uri).should be mock_component
81
82
  end
82
83
 
83
84
  describe '#execute_command' do
@@ -71,16 +71,17 @@ module Punchblock
71
71
  subject.client = Client.new
72
72
  end
73
73
 
74
- let(:component_id) { 'abc123' }
74
+ let(:uri) { 'xmpp:callid@server/abc123' }
75
75
 
76
76
  let :ref do
77
- Ref.new uri: component_id
77
+ Ref.new uri: uri
78
78
  end
79
79
 
80
80
  it "should set the component ID from the ref" do
81
81
  subject.response = ref
82
- subject.component_id.should be == component_id
83
- subject.client.find_component_by_id(component_id).should be subject
82
+ subject.component_id.should be == 'abc123'
83
+ subject.source_uri.should be == uri
84
+ subject.client.find_component_by_uri(uri).should be subject
84
85
  end
85
86
  end
86
87
 
@@ -89,7 +90,7 @@ module Punchblock
89
90
  subject.request!
90
91
  subject.client = Client.new
91
92
  subject.response = Ref.new uri: 'abc'
92
- subject.client.find_component_by_id('abc').should be subject
93
+ subject.client.find_component_by_uri('abc').should be subject
93
94
  end
94
95
 
95
96
  it "should set the command to executing status" do
@@ -105,7 +106,7 @@ module Punchblock
105
106
 
106
107
  it "should remove the component from the registry" do
107
108
  subject.complete_event = :foo
108
- subject.client.find_component_by_id('abc').should be_nil
109
+ subject.client.find_component_by_uri('abc').should be_nil
109
110
  end
110
111
  end
111
112
  end # ComponentNode
@@ -172,6 +172,7 @@ module Punchblock
172
172
  mock_event_handler.should_receive(:call).once.with do |event|
173
173
  event.should be_instance_of Event::Offer
174
174
  event.target_call_id.should be == '9f00061'
175
+ event.source_uri.should be == 'xmpp:9f00061@call.rayo.net'
175
176
  event.domain.should be == 'call.rayo.net'
176
177
  event.transport.should be == 'xmpp'
177
178
  end
@@ -312,7 +312,7 @@ module Punchblock
312
312
  comp_command.request!
313
313
  component = subject.execute_command comp_command
314
314
  comp_command.response(0.1).should be_a Ref
315
- expected_complete_event = Punchblock::Event::Complete.new :target_call_id => subject.id, :component_id => component.id
315
+ expected_complete_event = Punchblock::Event::Complete.new :target_call_id => subject.id, :component_id => component.id, source_uri: component.id
316
316
  expected_complete_event.reason = Punchblock::Event::Complete::Hangup.new
317
317
  expected_end_event = Punchblock::Event::End.new :reason => :hangup, platform_code: cause, :target_call_id => subject.id
318
318
 
@@ -1298,7 +1298,7 @@ module Punchblock
1298
1298
  end
1299
1299
  end
1300
1300
 
1301
- context "for a component which began executing but crashed" do
1301
+ context "for a component which began executing but terminated" do
1302
1302
  let :component_command do
1303
1303
  Punchblock::Component::Asterisk::AGI::Command.new :name => 'Wait'
1304
1304
  end
@@ -1310,6 +1310,7 @@ module Punchblock
1310
1310
  let :expected_event do
1311
1311
  Punchblock::Event::Complete.new target_call_id: subject.id,
1312
1312
  component_id: comp_id,
1313
+ source_uri: comp_id,
1313
1314
  reason: Punchblock::Event::Complete::Error.new
1314
1315
  end
1315
1316
 
@@ -1318,35 +1319,52 @@ module Punchblock
1318
1319
  subject.execute_command component_command
1319
1320
  end
1320
1321
 
1321
- it 'sends an error in response to the command' do
1322
- component = subject.component_with_id comp_id
1323
-
1324
- component.wrapped_object.define_singleton_method(:oops) do
1325
- raise 'Woops, I died'
1326
- end
1327
-
1328
- translator.should_receive(:handle_pb_event).once.with expected_event
1322
+ context "normally" do
1323
+ it 'sends an error in response to the command' do
1324
+ component = subject.component_with_id comp_id
1329
1325
 
1330
- lambda { component.oops }.should raise_error(/Woops, I died/)
1331
- sleep 0.1
1332
- component.should_not be_alive
1333
- subject.component_with_id(comp_id).should be_nil
1326
+ component.terminate
1327
+ sleep 0.1
1328
+ component.should_not be_alive
1329
+ subject.component_with_id(comp_id).should be_nil
1334
1330
 
1335
- subsequent_command.request!
1336
- subject.execute_command subsequent_command
1337
- subsequent_command.response.should be == ProtocolError.new.setup(:item_not_found, "Could not find a component with ID #{comp_id} for call #{subject.id}", subject.id, comp_id)
1331
+ subsequent_command.request!
1332
+ subject.execute_command subsequent_command
1333
+ subsequent_command.response.should be == ProtocolError.new.setup(:item_not_found, "Could not find a component with ID #{comp_id} for call #{subject.id}", subject.id, comp_id)
1334
+ end
1338
1335
  end
1339
1336
 
1340
- context "when we dispatch the command to it" do
1337
+ context "by crashing" do
1341
1338
  it 'sends an error in response to the command' do
1342
1339
  component = subject.component_with_id comp_id
1343
1340
 
1344
- component.should_receive(:execute_command).and_raise(Celluloid::DeadActorError)
1341
+ component.wrapped_object.define_singleton_method(:oops) do
1342
+ raise 'Woops, I died'
1343
+ end
1344
+
1345
+ translator.should_receive(:handle_pb_event).once.with expected_event
1346
+
1347
+ lambda { component.oops }.should raise_error(/Woops, I died/)
1348
+ sleep 0.1
1349
+ component.should_not be_alive
1350
+ subject.component_with_id(comp_id).should be_nil
1345
1351
 
1346
1352
  subsequent_command.request!
1347
1353
  subject.execute_command subsequent_command
1348
1354
  subsequent_command.response.should be == ProtocolError.new.setup(:item_not_found, "Could not find a component with ID #{comp_id} for call #{subject.id}", subject.id, comp_id)
1349
1355
  end
1356
+
1357
+ context "when we dispatch the command to it" do
1358
+ it 'sends an error in response to the command' do
1359
+ component = subject.component_with_id comp_id
1360
+
1361
+ component.should_receive(:execute_command).and_raise(Celluloid::DeadActorError)
1362
+
1363
+ subsequent_command.request!
1364
+ subject.execute_command subsequent_command
1365
+ subsequent_command.response.should be == ProtocolError.new.setup(:item_not_found, "Could not find a component with ID #{comp_id} for call #{subject.id}", subject.id, comp_id)
1366
+ end
1367
+ end
1350
1368
  end
1351
1369
  end
1352
1370
 
@@ -90,7 +90,7 @@ module Punchblock
90
90
  end
91
91
 
92
92
  let :event_node do
93
- Punchblock::Event::Asterisk::AMI::Event.new name: 'CoreShowChannel', component_id: subject.id, headers: {
93
+ Punchblock::Event::Asterisk::AMI::Event.new name: 'CoreShowChannel', component_id: subject.id, source_uri: subject.id, headers: {
94
94
  'Channel' => 'SIP/127.0.0.1-00000013',
95
95
  'UniqueID' => '1287686437.19',
96
96
  'Context' => 'adhearsion',
@@ -155,6 +155,7 @@ module Punchblock
155
155
  let :expected_event do
156
156
  Punchblock::Event::Complete.new reason: expected_reason,
157
157
  component_id: subject.id,
158
+ source_uri: subject.id,
158
159
  target_call_id: call.id
159
160
  end
160
161
 
@@ -215,6 +216,7 @@ module Punchblock
215
216
  expected_reason = Punchblock::Event::Complete::Stop.new
216
217
  expected_event = Punchblock::Event::Complete.new reason: expected_reason,
217
218
  component_id: subject.id,
219
+ source_uri: subject.id,
218
220
  target_call_id: call.id
219
221
 
220
222
  call.async.should_receive(:redirect_back)
@@ -30,7 +30,7 @@ module Punchblock
30
30
 
31
31
  let :expected_event do
32
32
  Punchblock::Event::Complete.new target_call_id: call.id,
33
- component_id: subject.id
33
+ component_id: subject.id, source_uri: subject.id
34
34
  end
35
35
 
36
36
  it "should send the event to the connection" do
@@ -358,7 +358,7 @@ module Punchblock
358
358
  component = subject.execute_command comp_command
359
359
  comp_command.response(0.1).should be_a Ref
360
360
 
361
- expected_complete_event = Punchblock::Event::Complete.new :target_call_id => subject.id, :component_id => component.id
361
+ expected_complete_event = Punchblock::Event::Complete.new :target_call_id => subject.id, :component_id => component.id, source_uri: component.id
362
362
  expected_complete_event.reason = Punchblock::Event::Complete::Hangup.new
363
363
  expected_end_event = Punchblock::Event::End.new :reason => :hangup, :target_call_id => subject.id
364
364
 
@@ -886,6 +886,7 @@ module Punchblock
886
886
  let :expected_event do
887
887
  Punchblock::Event::Complete.new target_call_id: subject.id,
888
888
  component_id: comp_id,
889
+ source_uri: comp_id,
889
890
  reason: Punchblock::Event::Complete::Error.new
890
891
  end
891
892
 
@@ -47,7 +47,7 @@ module Punchblock
47
47
 
48
48
  let :expected_event do
49
49
  Punchblock::Event::Complete.new target_call_id: call.id,
50
- component_id: subject.id
50
+ component_id: subject.id, source_uri: subject.id
51
51
  end
52
52
 
53
53
  it "should send the event to the connection" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: punchblock
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Goecke
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-09-17 00:00:00.000000000 Z
13
+ date: 2013-10-17 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: nokogiri
@@ -168,16 +168,16 @@ dependencies:
168
168
  name: virtus
169
169
  requirement: !ruby/object:Gem::Requirement
170
170
  requirements:
171
- - - '>='
171
+ - - ~>
172
172
  - !ruby/object:Gem::Version
173
- version: '0'
173
+ version: '0.5'
174
174
  type: :runtime
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
- - - '>='
178
+ - - ~>
179
179
  - !ruby/object:Gem::Version
180
- version: '0'
180
+ version: '0.5'
181
181
  - !ruby/object:Gem::Dependency
182
182
  name: ruby_jid
183
183
  requirement: !ruby/object:Gem::Requirement