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.
Files changed (236) hide show
  1. data/.gitignore +17 -10
  2. data/CHANGELOG.md +273 -0
  3. data/Gemfile +1 -1
  4. data/Guardfile +17 -0
  5. data/README.markdown +61 -9
  6. data/Rakefile +16 -48
  7. data/adhearsion.gemspec +21 -7
  8. data/bin/ahn +3 -1
  9. data/cucumber.yml +4 -0
  10. data/features/app_generator.feature +42 -0
  11. data/features/cli.feature +108 -0
  12. data/features/step_definitions/app_generator_steps.rb +6 -0
  13. data/features/step_definitions/cli_steps.rb +74 -0
  14. data/features/support/aruba_helper.rb +22 -0
  15. data/features/support/env.rb +37 -0
  16. data/features/support/utils.rb +8 -0
  17. data/lib/adhearsion.rb +85 -41
  18. data/lib/adhearsion/call.rb +176 -0
  19. data/lib/adhearsion/call_controller.rb +134 -0
  20. data/lib/adhearsion/call_controller/dial.rb +70 -0
  21. data/lib/adhearsion/call_controller/input.rb +173 -0
  22. data/lib/adhearsion/call_controller/menu.rb +124 -0
  23. data/lib/adhearsion/call_controller/output.rb +267 -0
  24. data/lib/adhearsion/call_controller/record.rb +42 -0
  25. data/lib/adhearsion/call_controller/utility.rb +60 -0
  26. data/lib/adhearsion/calls.rb +81 -0
  27. data/lib/adhearsion/cli.rb +1 -3
  28. data/lib/adhearsion/cli_commands.rb +142 -0
  29. data/lib/adhearsion/configuration.rb +149 -0
  30. data/lib/adhearsion/console.rb +19 -8
  31. data/lib/adhearsion/dialplan_controller.rb +9 -0
  32. data/lib/adhearsion/events.rb +84 -0
  33. data/lib/adhearsion/foundation/all.rb +0 -7
  34. data/lib/adhearsion/foundation/custom_daemonizer.rb +4 -6
  35. data/lib/adhearsion/foundation/exception_handler.rb +9 -0
  36. data/lib/adhearsion/foundation/object.rb +26 -8
  37. data/lib/adhearsion/foundation/synchronized_hash.rb +3 -6
  38. data/lib/adhearsion/foundation/thread_safety.rb +17 -1
  39. data/lib/adhearsion/generators/app/app_generator.rb +4 -13
  40. data/lib/adhearsion/generators/app/templates/Gemfile +10 -5
  41. data/lib/adhearsion/generators/app/templates/Procfile +1 -0
  42. data/lib/adhearsion/generators/app/templates/README.md +28 -0
  43. data/lib/adhearsion/generators/app/templates/config/adhearsion.rb +41 -0
  44. data/lib/adhearsion/generators/app/templates/{components/simon_game → lib}/simon_game.rb +6 -18
  45. data/lib/adhearsion/generators/app/templates/script/ahn +2 -2
  46. data/lib/adhearsion/initializer.rb +151 -293
  47. data/lib/adhearsion/initializer/logging.rb +33 -0
  48. data/lib/adhearsion/logging.rb +65 -69
  49. data/lib/adhearsion/menu_dsl.rb +15 -0
  50. data/lib/adhearsion/menu_dsl/calculated_match.rb +39 -0
  51. data/lib/adhearsion/menu_dsl/calculated_match_collection.rb +41 -0
  52. data/lib/adhearsion/menu_dsl/fixnum_match_calculator.rb +18 -0
  53. data/lib/adhearsion/menu_dsl/match_calculator.rb +36 -0
  54. data/lib/adhearsion/{voip/menu_state_machine/menu_class.rb → menu_dsl/menu.rb} +38 -40
  55. data/lib/adhearsion/menu_dsl/menu_builder.rb +69 -0
  56. data/lib/adhearsion/menu_dsl/range_match_calculator.rb +55 -0
  57. data/lib/adhearsion/menu_dsl/string_match_calculator.rb +21 -0
  58. data/lib/adhearsion/outbound_call.rb +64 -0
  59. data/lib/adhearsion/plugin.rb +319 -0
  60. data/lib/adhearsion/plugin/collection.rb +19 -0
  61. data/lib/adhearsion/plugin/initializer.rb +37 -0
  62. data/lib/adhearsion/plugin/methods_container.rb +6 -0
  63. data/lib/adhearsion/process.rb +94 -0
  64. data/lib/adhearsion/punchblock_plugin.rb +29 -0
  65. data/lib/adhearsion/punchblock_plugin/initializer.rb +137 -0
  66. data/lib/adhearsion/router.rb +30 -0
  67. data/lib/adhearsion/router/route.rb +42 -0
  68. data/lib/adhearsion/script_ahn_loader.rb +2 -2
  69. data/lib/adhearsion/tasks.rb +14 -9
  70. data/lib/adhearsion/tasks/configuration.rb +26 -0
  71. data/lib/adhearsion/tasks/plugins.rb +17 -0
  72. data/lib/adhearsion/version.rb +8 -14
  73. data/spec/adhearsion/call_controller/dial_spec.rb +138 -0
  74. data/spec/adhearsion/call_controller/input_spec.rb +278 -0
  75. data/spec/adhearsion/call_controller/menu_spec.rb +120 -0
  76. data/spec/adhearsion/call_controller/output_spec.rb +466 -0
  77. data/spec/adhearsion/call_controller/record_spec.rb +125 -0
  78. data/spec/adhearsion/call_controller_spec.rb +395 -0
  79. data/spec/adhearsion/call_spec.rb +438 -0
  80. data/spec/adhearsion/calls_spec.rb +47 -0
  81. data/spec/adhearsion/configuration_spec.rb +308 -0
  82. data/spec/adhearsion/dialplan_controller_spec.rb +26 -0
  83. data/spec/adhearsion/events_spec.rb +112 -0
  84. data/spec/adhearsion/initializer/logging_spec.rb +58 -0
  85. data/spec/adhearsion/initializer_spec.rb +209 -122
  86. data/spec/adhearsion/logging_spec.rb +58 -47
  87. data/spec/adhearsion/menu_dsl/calculated_match_collection_spec.rb +56 -0
  88. data/spec/adhearsion/menu_dsl/calculated_match_spec.rb +57 -0
  89. data/spec/adhearsion/menu_dsl/fixnum_match_calculator_spec.rb +33 -0
  90. data/spec/adhearsion/menu_dsl/match_calculator_spec.rb +13 -0
  91. data/spec/adhearsion/menu_dsl/menu_builder_spec.rb +118 -0
  92. data/spec/adhearsion/menu_dsl/menu_spec.rb +210 -0
  93. data/spec/adhearsion/menu_dsl/range_match_calculator_spec.rb +28 -0
  94. data/spec/adhearsion/menu_dsl/string_match_calculator_spec.rb +36 -0
  95. data/spec/adhearsion/menu_dsl_spec.rb +12 -0
  96. data/spec/adhearsion/outbound_call_spec.rb +174 -0
  97. data/spec/adhearsion/plugin_spec.rb +489 -0
  98. data/spec/adhearsion/process_spec.rb +34 -0
  99. data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +294 -0
  100. data/spec/adhearsion/router/route_spec.rb +99 -0
  101. data/spec/adhearsion/router_spec.rb +106 -0
  102. data/spec/adhearsion_spec.rb +46 -0
  103. data/spec/spec_helper.rb +14 -14
  104. data/spec/support/call_controller_test_helpers.rb +48 -0
  105. data/spec/support/initializer_stubs.rb +8 -13
  106. data/spec/support/punchblock_mocks.rb +6 -0
  107. metadata +255 -253
  108. data/CHANGELOG +0 -174
  109. data/bin/ahnctl +0 -68
  110. data/bin/jahn +0 -43
  111. data/examples/asterisk_manager_interface/standalone.rb +0 -51
  112. data/lib/adhearsion/commands.rb +0 -302
  113. data/lib/adhearsion/component_manager.rb +0 -278
  114. data/lib/adhearsion/component_manager/component_tester.rb +0 -54
  115. data/lib/adhearsion/component_manager/spec_framework.rb +0 -18
  116. data/lib/adhearsion/events_support.rb +0 -65
  117. data/lib/adhearsion/foundation/blank_slate.rb +0 -3
  118. data/lib/adhearsion/foundation/event_socket.rb +0 -205
  119. data/lib/adhearsion/foundation/future_resource.rb +0 -36
  120. data/lib/adhearsion/foundation/metaprogramming.rb +0 -17
  121. data/lib/adhearsion/foundation/numeric.rb +0 -13
  122. data/lib/adhearsion/foundation/pseudo_guid.rb +0 -10
  123. data/lib/adhearsion/foundation/relationship_properties.rb +0 -42
  124. data/lib/adhearsion/foundation/string.rb +0 -26
  125. data/lib/adhearsion/generators/app/templates/.ahnrc +0 -34
  126. data/lib/adhearsion/generators/app/templates/README +0 -8
  127. data/lib/adhearsion/generators/app/templates/components/ami_remote/ami_remote.rb +0 -15
  128. data/lib/adhearsion/generators/app/templates/components/disabled/HOW_TO_ENABLE +0 -7
  129. data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/README.markdown +0 -47
  130. data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/stomp_gateway.rb +0 -34
  131. data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/stomp_gateway.yml +0 -12
  132. data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/README.markdown +0 -3
  133. data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/xmpp_gateway.rb +0 -11
  134. data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/xmpp_gateway.yml +0 -0
  135. data/lib/adhearsion/generators/app/templates/config/startup.rb +0 -81
  136. data/lib/adhearsion/generators/app/templates/dialplan.rb +0 -3
  137. data/lib/adhearsion/generators/app/templates/events.rb +0 -33
  138. data/lib/adhearsion/host_definitions.rb +0 -67
  139. data/lib/adhearsion/initializer/asterisk.rb +0 -86
  140. data/lib/adhearsion/initializer/configuration.rb +0 -324
  141. data/lib/adhearsion/initializer/database.rb +0 -60
  142. data/lib/adhearsion/initializer/drb.rb +0 -31
  143. data/lib/adhearsion/initializer/freeswitch.rb +0 -22
  144. data/lib/adhearsion/initializer/ldap.rb +0 -57
  145. data/lib/adhearsion/initializer/rails.rb +0 -41
  146. data/lib/adhearsion/initializer/xmpp.rb +0 -42
  147. data/lib/adhearsion/tasks/components.rb +0 -32
  148. data/lib/adhearsion/tasks/database.rb +0 -5
  149. data/lib/adhearsion/tasks/deprecations.rb +0 -59
  150. data/lib/adhearsion/tasks/generating.rb +0 -20
  151. data/lib/adhearsion/tasks/lint.rb +0 -4
  152. data/lib/adhearsion/voip/asterisk.rb +0 -4
  153. data/lib/adhearsion/voip/asterisk/agi_server.rb +0 -121
  154. data/lib/adhearsion/voip/asterisk/commands.rb +0 -1966
  155. data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +0 -140
  156. data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +0 -102
  157. data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +0 -250
  158. data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +0 -240
  159. data/lib/adhearsion/voip/asterisk/config_manager.rb +0 -64
  160. data/lib/adhearsion/voip/asterisk/manager_interface.rb +0 -697
  161. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +0 -1681
  162. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +0 -341
  163. data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +0 -78
  164. data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +0 -87
  165. data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +0 -80
  166. data/lib/adhearsion/voip/call.rb +0 -521
  167. data/lib/adhearsion/voip/call_routing.rb +0 -64
  168. data/lib/adhearsion/voip/commands.rb +0 -17
  169. data/lib/adhearsion/voip/constants.rb +0 -39
  170. data/lib/adhearsion/voip/conveniences.rb +0 -18
  171. data/lib/adhearsion/voip/dial_plan.rb +0 -252
  172. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +0 -151
  173. data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +0 -37
  174. data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +0 -27
  175. data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +0 -124
  176. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +0 -69
  177. data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +0 -16
  178. data/lib/adhearsion/voip/dsl/numerical_string.rb +0 -128
  179. data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +0 -48
  180. data/lib/adhearsion/voip/freeswitch/event_handler.rb +0 -58
  181. data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +0 -129
  182. data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +0 -38
  183. data/lib/adhearsion/voip/freeswitch/oes_server.rb +0 -195
  184. data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +0 -80
  185. data/lib/adhearsion/voip/menu_state_machine/matchers.rb +0 -123
  186. data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +0 -57
  187. data/lib/adhearsion/xmpp/connection.rb +0 -61
  188. data/lib/theatre.rb +0 -147
  189. data/lib/theatre/README.markdown +0 -64
  190. data/lib/theatre/callback_definition_loader.rb +0 -86
  191. data/lib/theatre/guid.rb +0 -23
  192. data/lib/theatre/invocation.rb +0 -131
  193. data/lib/theatre/namespace_manager.rb +0 -153
  194. data/lib/theatre/version.rb +0 -2
  195. data/spec/adhearsion/cli_spec.rb +0 -306
  196. data/spec/adhearsion/component_manager_spec.rb +0 -292
  197. data/spec/adhearsion/constants_spec.rb +0 -8
  198. data/spec/adhearsion/drb_spec.rb +0 -65
  199. data/spec/adhearsion/fixtures/dialplan.rb +0 -3
  200. data/spec/adhearsion/foundation/event_socket_spec.rb +0 -168
  201. data/spec/adhearsion/host_definitions_spec.rb +0 -79
  202. data/spec/adhearsion/initializer/configuration_spec.rb +0 -291
  203. data/spec/adhearsion/initializer/loading_spec.rb +0 -154
  204. data/spec/adhearsion/initializer/paths_spec.rb +0 -74
  205. data/spec/adhearsion/relationship_properties_spec.rb +0 -54
  206. data/spec/adhearsion/voip/asterisk/agi_server_spec.rb +0 -473
  207. data/spec/adhearsion/voip/asterisk/ami/ami_spec.rb +0 -550
  208. data/spec/adhearsion/voip/asterisk/ami/lexer/ami_fixtures.yml +0 -30
  209. data/spec/adhearsion/voip/asterisk/ami/lexer/lexer_story +0 -291
  210. data/spec/adhearsion/voip/asterisk/ami/lexer/lexer_story.rb +0 -241
  211. data/spec/adhearsion/voip/asterisk/ami/lexer/story_helper.rb +0 -124
  212. data/spec/adhearsion/voip/asterisk/commands_spec.rb +0 -3241
  213. data/spec/adhearsion/voip/asterisk/config_file_generators/agents_spec.rb +0 -251
  214. data/spec/adhearsion/voip/asterisk/config_file_generators/queues_spec.rb +0 -323
  215. data/spec/adhearsion/voip/asterisk/config_file_generators/voicemail_spec.rb +0 -306
  216. data/spec/adhearsion/voip/asterisk/config_manager_spec.rb +0 -127
  217. data/spec/adhearsion/voip/asterisk/menu_command/calculated_match_spec.rb +0 -109
  218. data/spec/adhearsion/voip/asterisk/menu_command/matchers_spec.rb +0 -97
  219. data/spec/adhearsion/voip/call_routing_spec.rb +0 -125
  220. data/spec/adhearsion/voip/dialplan_manager_spec.rb +0 -468
  221. data/spec/adhearsion/voip/dsl/dialing_dsl_spec.rb +0 -270
  222. data/spec/adhearsion/voip/dsl/dispatcher_spec.rb +0 -82
  223. data/spec/adhearsion/voip/dsl/dispatcher_spec_helper.rb +0 -45
  224. data/spec/adhearsion/voip/dsl/parser_spec.rb +0 -69
  225. data/spec/adhearsion/voip/freeswitch/basic_connection_manager_spec.rb +0 -39
  226. data/spec/adhearsion/voip/freeswitch/inbound_connection_manager_spec.rb +0 -39
  227. data/spec/adhearsion/voip/freeswitch/oes_server_spec.rb +0 -9
  228. data/spec/adhearsion/voip/numerical_string_spec.rb +0 -61
  229. data/spec/adhearsion/voip/phone_number_spec.rb +0 -45
  230. data/spec/support/the_following_code.rb +0 -3
  231. data/spec/theatre/dsl_examples/simple_before_call.rb +0 -7
  232. data/spec/theatre/dsl_spec.rb +0 -69
  233. data/spec/theatre/invocation_spec.rb +0 -182
  234. data/spec/theatre/namespace_spec.rb +0 -125
  235. data/spec/theatre/spec_helper_spec.rb +0 -28
  236. 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
@@ -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
@@ -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.