adhearsion 1.2.6 → 2.0.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -10
- data/CHANGELOG.md +273 -0
- data/Gemfile +1 -1
- data/Guardfile +17 -0
- data/README.markdown +61 -9
- data/Rakefile +16 -48
- data/adhearsion.gemspec +21 -7
- data/bin/ahn +3 -1
- data/cucumber.yml +4 -0
- data/features/app_generator.feature +42 -0
- data/features/cli.feature +108 -0
- data/features/step_definitions/app_generator_steps.rb +6 -0
- data/features/step_definitions/cli_steps.rb +74 -0
- data/features/support/aruba_helper.rb +22 -0
- data/features/support/env.rb +37 -0
- data/features/support/utils.rb +8 -0
- data/lib/adhearsion.rb +85 -41
- data/lib/adhearsion/call.rb +176 -0
- data/lib/adhearsion/call_controller.rb +134 -0
- data/lib/adhearsion/call_controller/dial.rb +70 -0
- data/lib/adhearsion/call_controller/input.rb +173 -0
- data/lib/adhearsion/call_controller/menu.rb +124 -0
- data/lib/adhearsion/call_controller/output.rb +267 -0
- data/lib/adhearsion/call_controller/record.rb +42 -0
- data/lib/adhearsion/call_controller/utility.rb +60 -0
- data/lib/adhearsion/calls.rb +81 -0
- data/lib/adhearsion/cli.rb +1 -3
- data/lib/adhearsion/cli_commands.rb +142 -0
- data/lib/adhearsion/configuration.rb +149 -0
- data/lib/adhearsion/console.rb +19 -8
- data/lib/adhearsion/dialplan_controller.rb +9 -0
- data/lib/adhearsion/events.rb +84 -0
- data/lib/adhearsion/foundation/all.rb +0 -7
- data/lib/adhearsion/foundation/custom_daemonizer.rb +4 -6
- data/lib/adhearsion/foundation/exception_handler.rb +9 -0
- data/lib/adhearsion/foundation/object.rb +26 -8
- data/lib/adhearsion/foundation/synchronized_hash.rb +3 -6
- data/lib/adhearsion/foundation/thread_safety.rb +17 -1
- data/lib/adhearsion/generators/app/app_generator.rb +4 -13
- data/lib/adhearsion/generators/app/templates/Gemfile +10 -5
- data/lib/adhearsion/generators/app/templates/Procfile +1 -0
- data/lib/adhearsion/generators/app/templates/README.md +28 -0
- data/lib/adhearsion/generators/app/templates/config/adhearsion.rb +41 -0
- data/lib/adhearsion/generators/app/templates/{components/simon_game → lib}/simon_game.rb +6 -18
- data/lib/adhearsion/generators/app/templates/script/ahn +2 -2
- data/lib/adhearsion/initializer.rb +151 -293
- data/lib/adhearsion/initializer/logging.rb +33 -0
- data/lib/adhearsion/logging.rb +65 -69
- data/lib/adhearsion/menu_dsl.rb +15 -0
- data/lib/adhearsion/menu_dsl/calculated_match.rb +39 -0
- data/lib/adhearsion/menu_dsl/calculated_match_collection.rb +41 -0
- data/lib/adhearsion/menu_dsl/fixnum_match_calculator.rb +18 -0
- data/lib/adhearsion/menu_dsl/match_calculator.rb +36 -0
- data/lib/adhearsion/{voip/menu_state_machine/menu_class.rb → menu_dsl/menu.rb} +38 -40
- data/lib/adhearsion/menu_dsl/menu_builder.rb +69 -0
- data/lib/adhearsion/menu_dsl/range_match_calculator.rb +55 -0
- data/lib/adhearsion/menu_dsl/string_match_calculator.rb +21 -0
- data/lib/adhearsion/outbound_call.rb +64 -0
- data/lib/adhearsion/plugin.rb +319 -0
- data/lib/adhearsion/plugin/collection.rb +19 -0
- data/lib/adhearsion/plugin/initializer.rb +37 -0
- data/lib/adhearsion/plugin/methods_container.rb +6 -0
- data/lib/adhearsion/process.rb +94 -0
- data/lib/adhearsion/punchblock_plugin.rb +29 -0
- data/lib/adhearsion/punchblock_plugin/initializer.rb +137 -0
- data/lib/adhearsion/router.rb +30 -0
- data/lib/adhearsion/router/route.rb +42 -0
- data/lib/adhearsion/script_ahn_loader.rb +2 -2
- data/lib/adhearsion/tasks.rb +14 -9
- data/lib/adhearsion/tasks/configuration.rb +26 -0
- data/lib/adhearsion/tasks/plugins.rb +17 -0
- data/lib/adhearsion/version.rb +8 -14
- data/spec/adhearsion/call_controller/dial_spec.rb +138 -0
- data/spec/adhearsion/call_controller/input_spec.rb +278 -0
- data/spec/adhearsion/call_controller/menu_spec.rb +120 -0
- data/spec/adhearsion/call_controller/output_spec.rb +466 -0
- data/spec/adhearsion/call_controller/record_spec.rb +125 -0
- data/spec/adhearsion/call_controller_spec.rb +395 -0
- data/spec/adhearsion/call_spec.rb +438 -0
- data/spec/adhearsion/calls_spec.rb +47 -0
- data/spec/adhearsion/configuration_spec.rb +308 -0
- data/spec/adhearsion/dialplan_controller_spec.rb +26 -0
- data/spec/adhearsion/events_spec.rb +112 -0
- data/spec/adhearsion/initializer/logging_spec.rb +58 -0
- data/spec/adhearsion/initializer_spec.rb +209 -122
- data/spec/adhearsion/logging_spec.rb +58 -47
- data/spec/adhearsion/menu_dsl/calculated_match_collection_spec.rb +56 -0
- data/spec/adhearsion/menu_dsl/calculated_match_spec.rb +57 -0
- data/spec/adhearsion/menu_dsl/fixnum_match_calculator_spec.rb +33 -0
- data/spec/adhearsion/menu_dsl/match_calculator_spec.rb +13 -0
- data/spec/adhearsion/menu_dsl/menu_builder_spec.rb +118 -0
- data/spec/adhearsion/menu_dsl/menu_spec.rb +210 -0
- data/spec/adhearsion/menu_dsl/range_match_calculator_spec.rb +28 -0
- data/spec/adhearsion/menu_dsl/string_match_calculator_spec.rb +36 -0
- data/spec/adhearsion/menu_dsl_spec.rb +12 -0
- data/spec/adhearsion/outbound_call_spec.rb +174 -0
- data/spec/adhearsion/plugin_spec.rb +489 -0
- data/spec/adhearsion/process_spec.rb +34 -0
- data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +294 -0
- data/spec/adhearsion/router/route_spec.rb +99 -0
- data/spec/adhearsion/router_spec.rb +106 -0
- data/spec/adhearsion_spec.rb +46 -0
- data/spec/spec_helper.rb +14 -14
- data/spec/support/call_controller_test_helpers.rb +48 -0
- data/spec/support/initializer_stubs.rb +8 -13
- data/spec/support/punchblock_mocks.rb +6 -0
- metadata +255 -253
- data/CHANGELOG +0 -174
- data/bin/ahnctl +0 -68
- data/bin/jahn +0 -43
- data/examples/asterisk_manager_interface/standalone.rb +0 -51
- data/lib/adhearsion/commands.rb +0 -302
- data/lib/adhearsion/component_manager.rb +0 -278
- data/lib/adhearsion/component_manager/component_tester.rb +0 -54
- data/lib/adhearsion/component_manager/spec_framework.rb +0 -18
- data/lib/adhearsion/events_support.rb +0 -65
- data/lib/adhearsion/foundation/blank_slate.rb +0 -3
- data/lib/adhearsion/foundation/event_socket.rb +0 -205
- data/lib/adhearsion/foundation/future_resource.rb +0 -36
- data/lib/adhearsion/foundation/metaprogramming.rb +0 -17
- data/lib/adhearsion/foundation/numeric.rb +0 -13
- data/lib/adhearsion/foundation/pseudo_guid.rb +0 -10
- data/lib/adhearsion/foundation/relationship_properties.rb +0 -42
- data/lib/adhearsion/foundation/string.rb +0 -26
- data/lib/adhearsion/generators/app/templates/.ahnrc +0 -34
- data/lib/adhearsion/generators/app/templates/README +0 -8
- data/lib/adhearsion/generators/app/templates/components/ami_remote/ami_remote.rb +0 -15
- data/lib/adhearsion/generators/app/templates/components/disabled/HOW_TO_ENABLE +0 -7
- data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/README.markdown +0 -47
- data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/stomp_gateway.rb +0 -34
- data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/stomp_gateway.yml +0 -12
- data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/README.markdown +0 -3
- data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/xmpp_gateway.rb +0 -11
- data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/xmpp_gateway.yml +0 -0
- data/lib/adhearsion/generators/app/templates/config/startup.rb +0 -81
- data/lib/adhearsion/generators/app/templates/dialplan.rb +0 -3
- data/lib/adhearsion/generators/app/templates/events.rb +0 -33
- data/lib/adhearsion/host_definitions.rb +0 -67
- data/lib/adhearsion/initializer/asterisk.rb +0 -86
- data/lib/adhearsion/initializer/configuration.rb +0 -324
- data/lib/adhearsion/initializer/database.rb +0 -60
- data/lib/adhearsion/initializer/drb.rb +0 -31
- data/lib/adhearsion/initializer/freeswitch.rb +0 -22
- data/lib/adhearsion/initializer/ldap.rb +0 -57
- data/lib/adhearsion/initializer/rails.rb +0 -41
- data/lib/adhearsion/initializer/xmpp.rb +0 -42
- data/lib/adhearsion/tasks/components.rb +0 -32
- data/lib/adhearsion/tasks/database.rb +0 -5
- data/lib/adhearsion/tasks/deprecations.rb +0 -59
- data/lib/adhearsion/tasks/generating.rb +0 -20
- data/lib/adhearsion/tasks/lint.rb +0 -4
- data/lib/adhearsion/voip/asterisk.rb +0 -4
- data/lib/adhearsion/voip/asterisk/agi_server.rb +0 -121
- data/lib/adhearsion/voip/asterisk/commands.rb +0 -1966
- data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +0 -140
- data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +0 -102
- data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +0 -250
- data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +0 -240
- data/lib/adhearsion/voip/asterisk/config_manager.rb +0 -64
- data/lib/adhearsion/voip/asterisk/manager_interface.rb +0 -697
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +0 -1681
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +0 -341
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +0 -78
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +0 -87
- data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +0 -80
- data/lib/adhearsion/voip/call.rb +0 -521
- data/lib/adhearsion/voip/call_routing.rb +0 -64
- data/lib/adhearsion/voip/commands.rb +0 -17
- data/lib/adhearsion/voip/constants.rb +0 -39
- data/lib/adhearsion/voip/conveniences.rb +0 -18
- data/lib/adhearsion/voip/dial_plan.rb +0 -252
- data/lib/adhearsion/voip/dsl/dialing_dsl.rb +0 -151
- data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +0 -37
- data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +0 -27
- data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +0 -124
- data/lib/adhearsion/voip/dsl/dialplan/parser.rb +0 -69
- data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +0 -16
- data/lib/adhearsion/voip/dsl/numerical_string.rb +0 -128
- data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +0 -48
- data/lib/adhearsion/voip/freeswitch/event_handler.rb +0 -58
- data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +0 -129
- data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +0 -38
- data/lib/adhearsion/voip/freeswitch/oes_server.rb +0 -195
- data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +0 -80
- data/lib/adhearsion/voip/menu_state_machine/matchers.rb +0 -123
- data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +0 -57
- data/lib/adhearsion/xmpp/connection.rb +0 -61
- data/lib/theatre.rb +0 -147
- data/lib/theatre/README.markdown +0 -64
- data/lib/theatre/callback_definition_loader.rb +0 -86
- data/lib/theatre/guid.rb +0 -23
- data/lib/theatre/invocation.rb +0 -131
- data/lib/theatre/namespace_manager.rb +0 -153
- data/lib/theatre/version.rb +0 -2
- data/spec/adhearsion/cli_spec.rb +0 -306
- data/spec/adhearsion/component_manager_spec.rb +0 -292
- data/spec/adhearsion/constants_spec.rb +0 -8
- data/spec/adhearsion/drb_spec.rb +0 -65
- data/spec/adhearsion/fixtures/dialplan.rb +0 -3
- data/spec/adhearsion/foundation/event_socket_spec.rb +0 -168
- data/spec/adhearsion/host_definitions_spec.rb +0 -79
- data/spec/adhearsion/initializer/configuration_spec.rb +0 -291
- data/spec/adhearsion/initializer/loading_spec.rb +0 -154
- data/spec/adhearsion/initializer/paths_spec.rb +0 -74
- data/spec/adhearsion/relationship_properties_spec.rb +0 -54
- data/spec/adhearsion/voip/asterisk/agi_server_spec.rb +0 -473
- data/spec/adhearsion/voip/asterisk/ami/ami_spec.rb +0 -550
- data/spec/adhearsion/voip/asterisk/ami/lexer/ami_fixtures.yml +0 -30
- data/spec/adhearsion/voip/asterisk/ami/lexer/lexer_story +0 -291
- data/spec/adhearsion/voip/asterisk/ami/lexer/lexer_story.rb +0 -241
- data/spec/adhearsion/voip/asterisk/ami/lexer/story_helper.rb +0 -124
- data/spec/adhearsion/voip/asterisk/commands_spec.rb +0 -3241
- data/spec/adhearsion/voip/asterisk/config_file_generators/agents_spec.rb +0 -251
- data/spec/adhearsion/voip/asterisk/config_file_generators/queues_spec.rb +0 -323
- data/spec/adhearsion/voip/asterisk/config_file_generators/voicemail_spec.rb +0 -306
- data/spec/adhearsion/voip/asterisk/config_manager_spec.rb +0 -127
- data/spec/adhearsion/voip/asterisk/menu_command/calculated_match_spec.rb +0 -109
- data/spec/adhearsion/voip/asterisk/menu_command/matchers_spec.rb +0 -97
- data/spec/adhearsion/voip/call_routing_spec.rb +0 -125
- data/spec/adhearsion/voip/dialplan_manager_spec.rb +0 -468
- data/spec/adhearsion/voip/dsl/dialing_dsl_spec.rb +0 -270
- data/spec/adhearsion/voip/dsl/dispatcher_spec.rb +0 -82
- data/spec/adhearsion/voip/dsl/dispatcher_spec_helper.rb +0 -45
- data/spec/adhearsion/voip/dsl/parser_spec.rb +0 -69
- data/spec/adhearsion/voip/freeswitch/basic_connection_manager_spec.rb +0 -39
- data/spec/adhearsion/voip/freeswitch/inbound_connection_manager_spec.rb +0 -39
- data/spec/adhearsion/voip/freeswitch/oes_server_spec.rb +0 -9
- data/spec/adhearsion/voip/numerical_string_spec.rb +0 -61
- data/spec/adhearsion/voip/phone_number_spec.rb +0 -45
- data/spec/support/the_following_code.rb +0 -3
- data/spec/theatre/dsl_examples/simple_before_call.rb +0 -7
- data/spec/theatre/dsl_spec.rb +0 -69
- data/spec/theatre/invocation_spec.rb +0 -182
- data/spec/theatre/namespace_spec.rb +0 -125
- data/spec/theatre/spec_helper_spec.rb +0 -28
- data/spec/theatre/theatre_class_spec.rb +0 -148
@@ -1,123 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'calculated_match')
|
2
|
-
|
3
|
-
module Adhearsion
|
4
|
-
module VoIP
|
5
|
-
class MatchCalculator
|
6
|
-
|
7
|
-
class << self
|
8
|
-
|
9
|
-
def build_with_pattern(pattern, match_payload, &block)
|
10
|
-
class_for_pattern_type(pattern.class.name).new(pattern, match_payload, &block)
|
11
|
-
end
|
12
|
-
|
13
|
-
def inherited(klass)
|
14
|
-
subclasses << klass
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def class_for_pattern_type(pattern_type)
|
20
|
-
sought_class_name = "Adhearsion::VoIP::#{pattern_type.camelize}MatchCalculator"
|
21
|
-
subclasses.find { |klass| klass.name == sought_class_name }
|
22
|
-
end
|
23
|
-
|
24
|
-
def subclasses
|
25
|
-
@@subclasses ||= []
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
attr_reader :pattern, :match_payload
|
31
|
-
def initialize(pattern, match_payload)
|
32
|
-
@pattern, @match_payload = pattern, match_payload
|
33
|
-
end
|
34
|
-
|
35
|
-
protected
|
36
|
-
|
37
|
-
def new_calculated_match(options)
|
38
|
-
CalculatedMatch.new({:pattern => pattern, :match_payload => match_payload}.merge(options))
|
39
|
-
end
|
40
|
-
|
41
|
-
def coerce_to_numeric(victim)
|
42
|
-
victim.kind_of?(Numeric) ? victim : (victim.to_s =~ /^\d+$/ ? victim.to_s.to_i : nil )
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
class RangeMatchCalculator < MatchCalculator
|
47
|
-
|
48
|
-
def initialize(pattern, match_payload)
|
49
|
-
raise unless pattern.first.kind_of?(Numeric) && pattern.last.kind_of?(Numeric)
|
50
|
-
super
|
51
|
-
end
|
52
|
-
|
53
|
-
def match(query)
|
54
|
-
numerical_query = coerce_to_numeric query
|
55
|
-
if numerical_query
|
56
|
-
exact_match = pattern.include?(numerical_query) ? query : nil
|
57
|
-
potential_matches = numbers_in_range_like numerical_query
|
58
|
-
potential_matches.reject! { |m| m.to_s == exact_match.to_s } if exact_match
|
59
|
-
|
60
|
-
new_calculated_match :query => query, :exact_matches => exact_match,
|
61
|
-
:potential_matches => potential_matches
|
62
|
-
else
|
63
|
-
CalculatedMatch.failed_match!(pattern, query, match_payload)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
# Returns all numbers in the range (@pattern) that +begin with+ the number given
|
70
|
-
# as the first argument.
|
71
|
-
#
|
72
|
-
# NOTE! If you're having trouble reading what this method is actually doing, it's
|
73
|
-
# effectively a much more efficient version of this:
|
74
|
-
#
|
75
|
-
# pattern.to_a.select { |x| x.to_s.starts_with? num.to_s }.flatten
|
76
|
-
#
|
77
|
-
# Huge thanks to Dave Troy (http://davetroy.blogspot.com) for this awesomely
|
78
|
-
# efficient code!
|
79
|
-
def numbers_in_range_like(num)
|
80
|
-
return (pattern === 0 ? [0] : nil) if num == 0
|
81
|
-
raise ArgumentError unless num.kind_of?(Numeric)
|
82
|
-
Array.new.tap do |matches|
|
83
|
-
first, last = pattern.first, pattern.last
|
84
|
-
power = 0
|
85
|
-
while num < last
|
86
|
-
ones_count = 10**power - 1
|
87
|
-
matches.concat((([num, first].max)..[(num+ones_count), last].min).to_a)
|
88
|
-
num *= 10
|
89
|
-
power += 1
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
class FixnumMatchCalculator < MatchCalculator
|
96
|
-
def match(query)
|
97
|
-
numeric_query = coerce_to_numeric query
|
98
|
-
exact_match, potential_match = nil
|
99
|
-
if pattern == numeric_query
|
100
|
-
exact_match = pattern
|
101
|
-
elsif pattern.to_s.starts_with? query.to_s
|
102
|
-
potential_match = pattern
|
103
|
-
end
|
104
|
-
new_calculated_match :query => query, :exact_matches => exact_match, :potential_matches => potential_match
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
class StringMatchCalculator < MatchCalculator
|
109
|
-
def match(query)
|
110
|
-
args = { :query => query, :exact_matches => nil,
|
111
|
-
:potential_matches => nil }
|
112
|
-
|
113
|
-
if pattern == query.to_s
|
114
|
-
args[:exact_matches] = [pattern]
|
115
|
-
elsif pattern.starts_with? query.to_s
|
116
|
-
args[:potential_matches] = [pattern]
|
117
|
-
end
|
118
|
-
|
119
|
-
new_calculated_match args
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'matchers.rb')
|
2
|
-
|
3
|
-
module Adhearsion
|
4
|
-
module VoIP
|
5
|
-
class MenuBuilder
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
@patterns = []
|
9
|
-
@menu_callbacks = {}
|
10
|
-
end
|
11
|
-
|
12
|
-
def method_missing(match_payload, *patterns, &block)
|
13
|
-
if patterns.any?
|
14
|
-
patterns.each do |pattern|
|
15
|
-
@patterns << MatchCalculator.build_with_pattern(pattern, match_payload)
|
16
|
-
end
|
17
|
-
else
|
18
|
-
raise ArgumentError, "You cannot call this method without patterns!"
|
19
|
-
end
|
20
|
-
nil
|
21
|
-
end
|
22
|
-
|
23
|
-
def weighted_match_calculators
|
24
|
-
@patterns
|
25
|
-
end
|
26
|
-
|
27
|
-
def execute_hook_for(symbol, input)
|
28
|
-
callback = @menu_callbacks[symbol]
|
29
|
-
callback.call input if callback
|
30
|
-
end
|
31
|
-
|
32
|
-
def on_invalid(&block)
|
33
|
-
raise LocalJumpError, "Must supply a block!" unless block_given?
|
34
|
-
@menu_callbacks[:invalid] = block
|
35
|
-
end
|
36
|
-
|
37
|
-
def on_premature_timeout(&block)
|
38
|
-
raise LocalJumpError, "Must supply a block!" unless block_given?
|
39
|
-
@menu_callbacks[:premature_timeout] = block
|
40
|
-
end
|
41
|
-
|
42
|
-
def on_failure(&block)
|
43
|
-
raise LocalJumpError, "Must supply a block!" unless block_given?
|
44
|
-
@menu_callbacks[:failure] = block
|
45
|
-
end
|
46
|
-
|
47
|
-
def calculate_matches_for(result)
|
48
|
-
CalculatedMatchCollection.new.tap do |collection|
|
49
|
-
weighted_match_calculators.each do |pattern|
|
50
|
-
collection << pattern.match(result)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,61 +0,0 @@
|
|
1
|
-
module Adhearsion
|
2
|
-
module XMPP
|
3
|
-
module Connection
|
4
|
-
|
5
|
-
mattr_accessor :client
|
6
|
-
class << self
|
7
|
-
|
8
|
-
# Open the XMPP connection
|
9
|
-
#
|
10
|
-
# @param [String] jid the client/component JID to connect to
|
11
|
-
# @param [String] password
|
12
|
-
# @param [String] server
|
13
|
-
# @param [Integer] port
|
14
|
-
def start(jid, password, server, port)
|
15
|
-
Blather.logger = ahn_log.xmpp
|
16
|
-
setup_client_object(jid, password, server, port)
|
17
|
-
register_event_namespaces
|
18
|
-
register_default_client_handlers
|
19
|
-
Events.register_callback(:after_initialized) do
|
20
|
-
connect
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
# Close the XMPP connection
|
25
|
-
def stop
|
26
|
-
shutdown
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def setup_client_object(jid, password, server, port)
|
32
|
-
self.client = Blather::Client.setup(jid, password, server, port)
|
33
|
-
end
|
34
|
-
|
35
|
-
def connect
|
36
|
-
EventMachine.run {client.connect}
|
37
|
-
end
|
38
|
-
|
39
|
-
def register_event_namespaces
|
40
|
-
Events.register_namespace_name "/xmpp"
|
41
|
-
end
|
42
|
-
|
43
|
-
def register_default_client_handlers
|
44
|
-
client.register_handler(:ready) do
|
45
|
-
ahn_log.xmpp.info "Connected to XMPP server! Send messages to #{client.jid.stripped}."
|
46
|
-
end
|
47
|
-
|
48
|
-
client.register_handler(:disconnected) do
|
49
|
-
if Adhearsion.status == :running
|
50
|
-
ahn_log.xmpp.warning "XMPP Disconnected. Reconnecting."
|
51
|
-
connect
|
52
|
-
end
|
53
|
-
# TODO: fix this to reconnect XMPP cleanly
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
data/lib/theatre.rb
DELETED
@@ -1,147 +0,0 @@
|
|
1
|
-
require 'thread'
|
2
|
-
require 'rubygems'
|
3
|
-
|
4
|
-
$: << File.expand_path(File.dirname(__FILE__))
|
5
|
-
|
6
|
-
require 'theatre/version'
|
7
|
-
require 'theatre/namespace_manager'
|
8
|
-
require 'theatre/invocation'
|
9
|
-
require 'theatre/callback_definition_loader'
|
10
|
-
|
11
|
-
module Theatre
|
12
|
-
|
13
|
-
class Theatre
|
14
|
-
|
15
|
-
attr_reader :namespace_manager
|
16
|
-
|
17
|
-
##
|
18
|
-
# Creates a new stopped Theatre. You must call start!() after you instantiate this for it to begin processing events.
|
19
|
-
#
|
20
|
-
# @param [Fixnum] thread_count Number of Threads to spawn when started.
|
21
|
-
#
|
22
|
-
def initialize(thread_count=6)
|
23
|
-
@thread_count = thread_count
|
24
|
-
@started = false
|
25
|
-
@namespace_manager = ActorNamespaceManager.new
|
26
|
-
@thread_group = ThreadGroup.new
|
27
|
-
@master_queue = Queue.new
|
28
|
-
@loader_mixins = []
|
29
|
-
end
|
30
|
-
|
31
|
-
##
|
32
|
-
# Send a message to this Theatre for asynchronous processing.
|
33
|
-
#
|
34
|
-
# @param [String] namespace The namespace to which the payload should be sent
|
35
|
-
# @param [Object] payload The actual content to be sent to the callback. Optional.
|
36
|
-
# @return [Array<Theatre::Invocation>] An Array of Invocation objects
|
37
|
-
# @raise Theatre::NamespaceNotFound Raised when told to enqueue an unrecognized namespace
|
38
|
-
#
|
39
|
-
def trigger(namespace, payload=:argument_undefined)
|
40
|
-
@namespace_manager.callbacks_for_namespaces(namespace).map do |callback|
|
41
|
-
invocation = if payload.equal?(:argument_undefined)
|
42
|
-
Invocation.new(namespace, callback)
|
43
|
-
else
|
44
|
-
Invocation.new(namespace, callback, payload)
|
45
|
-
end
|
46
|
-
invocation.queued
|
47
|
-
@master_queue << invocation
|
48
|
-
invocation
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
##
|
53
|
-
# Send a message to this Theatre for synchronous processing. The execution of this will not go through this Theatre's
|
54
|
-
# Thread pool. If an error occurred in any of callbacks, the Exception object will be placed in the returned Array
|
55
|
-
# instead for you to act upon.
|
56
|
-
#
|
57
|
-
# @param [String] namespace The namespace to which the payload should be sent
|
58
|
-
# @param [Object] payload The actual content to be sent to the callback. Optional.
|
59
|
-
# @return [Array] An Array containing each callback's return value (or Exception raised, if any) when given the payload
|
60
|
-
# @raise Theatre::NamespaceNotFound Raised when told to enqueue an unrecognized namespace
|
61
|
-
#
|
62
|
-
def trigger_immediately(namespace, payload=:argument_undefined)
|
63
|
-
@namespace_manager.callbacks_for_namespaces(namespace).map do |callback|
|
64
|
-
begin
|
65
|
-
invocation = if payload.equal?(:argument_undefined)
|
66
|
-
callback.call
|
67
|
-
else
|
68
|
-
callback.call payload
|
69
|
-
end
|
70
|
-
rescue => captured_error_to_be_returned
|
71
|
-
Adhearsion::Events.trigger '/exception', captured_error_to_be_returned
|
72
|
-
captured_error_to_be_returned
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def load_events_code(code, *args)
|
78
|
-
loader = CallbackDefinitionLoader.new(self, *args)
|
79
|
-
loader.load_events_code code
|
80
|
-
end
|
81
|
-
|
82
|
-
def load_events_file(file, *args)
|
83
|
-
loader = CallbackDefinitionLoader.new(self, *args)
|
84
|
-
loader.load_events_file file
|
85
|
-
end
|
86
|
-
|
87
|
-
def register_namespace_name(*args)
|
88
|
-
@namespace_manager.register_namespace_name(*args)
|
89
|
-
end
|
90
|
-
|
91
|
-
def register_callback_at_namespace(*args)
|
92
|
-
@namespace_manager.register_callback_at_namespace(*args)
|
93
|
-
end
|
94
|
-
|
95
|
-
def register_loader_mixin(mod)
|
96
|
-
@loader_mixins << mod
|
97
|
-
end
|
98
|
-
|
99
|
-
def join
|
100
|
-
@thread_group.list.each do |thread|
|
101
|
-
begin
|
102
|
-
thread.join
|
103
|
-
rescue
|
104
|
-
# Ignore any exceptions
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
##
|
110
|
-
# Starts this Theatre.
|
111
|
-
#
|
112
|
-
# When this method is called, the Threads are spawned and begin pulling messages off this Theatre's master queue.
|
113
|
-
#
|
114
|
-
def start!
|
115
|
-
return false if @thread_group.list.any? # Already started
|
116
|
-
@started_time = Time.now
|
117
|
-
@thread_count.times do
|
118
|
-
@thread_group.add Thread.new(&method(:thread_loop))
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
##
|
123
|
-
# Notifies all Threads for this Theatre to stop by sending them special messages. Any messages which were queued and
|
124
|
-
# untriggered when this method is received will still be processed. Note: you may start this Theatre again later once it
|
125
|
-
# has been stopped.
|
126
|
-
#
|
127
|
-
def graceful_stop!
|
128
|
-
@thread_count.times { @master_queue << :THEATRE_SHUTDOWN! }
|
129
|
-
@started_time = nil
|
130
|
-
end
|
131
|
-
|
132
|
-
protected
|
133
|
-
|
134
|
-
def thread_loop
|
135
|
-
loop do
|
136
|
-
begin
|
137
|
-
next_invocation = @master_queue.pop
|
138
|
-
return :stopped if next_invocation.equal? :THEATRE_SHUTDOWN!
|
139
|
-
next_invocation.start
|
140
|
-
rescue StandardError => error
|
141
|
-
Adhearsion::Events.trigger(['exception'], error)
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
end
|
147
|
-
end
|
data/lib/theatre/README.markdown
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
Theatre
|
2
|
-
=======
|
3
|
-
|
4
|
-
Present status: stable
|
5
|
-
|
6
|
-
A library for choreographing a dynamic pool of hierarchically organized actors. This was originally extracted from the [Adhearsion](http://adhearsion.com) framework by Jay Phillips.
|
7
|
-
|
8
|
-
In the Adhearsion framework, it was necessary to develop an internal message-passing system that could work either synchronously or asynchronously. This is used by the framework itself and for framework extensions (called _components_) to talk with each other. The source of the events is completely undefined -- events could originate from within the framework out outside the framework. For example, a Message Queue such as [Stomp](http://stomp.codehaus.org) can wire incoming events into Theatre and catch events going to a particular destination so it can proxy them out to the server.
|
9
|
-
|
10
|
-
Motivations and Design Decisions
|
11
|
-
--------------------------------
|
12
|
-
|
13
|
-
* Must maintain Ruby 1.8 and JRuby compatibility
|
14
|
-
* Must be Thread-safe
|
15
|
-
* Must provide some level of transparency into the events going through it
|
16
|
-
* Must be dynamic enough to reallocate the number of triggerrs based on load
|
17
|
-
* Must help facilitate test-driven development of Actor functionality
|
18
|
-
* Must allow external persistence in case of a crash
|
19
|
-
|
20
|
-
Example
|
21
|
-
-------
|
22
|
-
|
23
|
-
Below is an example taken from Adhearsion for executing framework-level callbacks. Note: the framework treats this callback synchronously.
|
24
|
-
|
25
|
-
events.framework.asterisk.before_call.each do |event|
|
26
|
-
# Pull headers from event and respond to it here.
|
27
|
-
end
|
28
|
-
|
29
|
-
Below is an example of integration with [Stomp](http://stomp.codehaus.org/), a simple yet robust open-protocol message queue.
|
30
|
-
|
31
|
-
events.stomp.new_call.each do |event|
|
32
|
-
# Handle all events from the Stomp MQ server whose name is "new_call" (the String)
|
33
|
-
end
|
34
|
-
|
35
|
-
This will filter all events whose name is "new_call" and yield the Stomp::Message to the block.
|
36
|
-
|
37
|
-
Framework terminology
|
38
|
-
--------------------
|
39
|
-
|
40
|
-
Below are definitions of terms I use in Theatre. See the respective links for more information.
|
41
|
-
|
42
|
-
* **callback**: This is the block given to the `each` method which triggers events coming in.
|
43
|
-
* **payload**: This is the "message" sent to the Theatre and is what will ultimately be yielded to the callback
|
44
|
-
* **[Actor](http://en.wikipedia.org/wiki/Actor_model)**: This refers to concurrent responders to events in a concurrent system.
|
45
|
-
|
46
|
-
Synchronous vs. Asynchronous
|
47
|
-
----------------------------
|
48
|
-
|
49
|
-
With Theatre, all events are asynchronous with the optional ability to synchronously block until the event is scheduled, triggered, and has returned. If you wish to synchronously trigger the event, simple call `wait` on an `Invocation` object returned from `trigger` and then check the `Invocation#current_state` property for `:success` or `:error`. Optionally the `Invocation#success?` and `Invocation#error?` methods also provide more intuitive access to the finished state. If the event finished with `:success`, you may retrieve the returned value of the event Proc by calling `Invocation#returned_value`. If the event finished with `:error`, you may get the Exception with `Invocation#error`.
|
50
|
-
|
51
|
-
Because many callbacks can be registered for a particular namespace, each needing its own Invocation object, the `Theatre#trigger` method returns an Array of Invocation objects.
|
52
|
-
|
53
|
-
# We'll assume only one callback is registered and call #first on the Array of Invocations returned by #trigger
|
54
|
-
invocation = my_theatre.trigger("your/namespace/here", YourSpecialClass.new("this can be anything")).first
|
55
|
-
invocation.wait
|
56
|
-
raise invocation.error if invocation.error?
|
57
|
-
log "Actor finished with return value #{invocation.returned_value}"
|
58
|
-
|
59
|
-
Ruby 1.8 vs. Ruby 1.9 vs. JRuby
|
60
|
-
-------------------------------
|
61
|
-
|
62
|
-
Theatre was created for Ruby 1.8 because no good Actor system existed on Ruby 1.8 that met Adhearsion's needs (e.g. hierarchal with synchronous and asynchronous modes. If you wish to achieve real processor-level concurrency, use JRuby.
|
63
|
-
|
64
|
-
Presently Ruby 1.9 compatibility is not a priority but patches for compatibility will be accepted, as long as they preserve compatibility with both MRI and JRuby.
|