punchblock 2.0.1 → 2.0.2

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.
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