amqp-daemon-kit 0.1.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (185) hide show
  1. data/.gitignore +5 -0
  2. data/Configuration.txt +110 -0
  3. data/Deployment.txt +113 -0
  4. data/History.txt +131 -0
  5. data/Logging.txt +96 -0
  6. data/PostInstall.txt +6 -0
  7. data/README.rdoc +132 -0
  8. data/Rakefile +29 -0
  9. data/RuoteParticipants.txt +113 -0
  10. data/TODO.txt +27 -0
  11. data/bin/daemon-kit +18 -0
  12. data/config/website.yml +2 -0
  13. data/daemon-kit.gemspec +265 -0
  14. data/lib/daemon_kit.rb +60 -0
  15. data/lib/daemon_kit/abstract_logger.rb +249 -0
  16. data/lib/daemon_kit/application.rb +230 -0
  17. data/lib/daemon_kit/arguments.rb +165 -0
  18. data/lib/daemon_kit/commands/console.rb +38 -0
  19. data/lib/daemon_kit/commands/destroy.rb +10 -0
  20. data/lib/daemon_kit/commands/generate.rb +10 -0
  21. data/lib/daemon_kit/config.rb +113 -0
  22. data/lib/daemon_kit/console_daemon.rb +2 -0
  23. data/lib/daemon_kit/core_ext.rb +1 -0
  24. data/lib/daemon_kit/core_ext/configurable.rb +96 -0
  25. data/lib/daemon_kit/core_ext/string.rb +22 -0
  26. data/lib/daemon_kit/cron.rb +67 -0
  27. data/lib/daemon_kit/cucumber/world.rb +38 -0
  28. data/lib/daemon_kit/deployment/capistrano.rb +516 -0
  29. data/lib/daemon_kit/dk_amqp.rb +39 -0
  30. data/lib/daemon_kit/em.rb +43 -0
  31. data/lib/daemon_kit/error_handlers/base.rb +32 -0
  32. data/lib/daemon_kit/error_handlers/hoptoad.rb +180 -0
  33. data/lib/daemon_kit/exceptions.rb +15 -0
  34. data/lib/daemon_kit/generators.rb +67 -0
  35. data/lib/daemon_kit/generators/base.rb +60 -0
  36. data/lib/daemon_kit/initializer.rb +449 -0
  37. data/lib/daemon_kit/jabber.rb +171 -0
  38. data/lib/daemon_kit/nanite.rb +7 -0
  39. data/lib/daemon_kit/nanite/agent.rb +77 -0
  40. data/lib/daemon_kit/pid_file.rb +61 -0
  41. data/lib/daemon_kit/ruote_participants.rb +125 -0
  42. data/lib/daemon_kit/ruote_pseudo_participant.rb +68 -0
  43. data/lib/daemon_kit/ruote_workitem.rb +187 -0
  44. data/lib/daemon_kit/safety.rb +84 -0
  45. data/lib/daemon_kit/tasks.rb +2 -0
  46. data/lib/daemon_kit/tasks/environment.rake +11 -0
  47. data/lib/daemon_kit/tasks/framework.rake +123 -0
  48. data/lib/daemon_kit/tasks/god.rake +62 -0
  49. data/lib/daemon_kit/tasks/log.rake +8 -0
  50. data/lib/daemon_kit/tasks/monit.rake +29 -0
  51. data/lib/daemon_kit/vendor/thor-0.13.6/CHANGELOG.rdoc +89 -0
  52. data/lib/daemon_kit/vendor/thor-0.13.6/LICENSE +20 -0
  53. data/lib/daemon_kit/vendor/thor-0.13.6/README.rdoc +297 -0
  54. data/lib/daemon_kit/vendor/thor-0.13.6/Thorfile +69 -0
  55. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor.rb +244 -0
  56. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/actions.rb +296 -0
  57. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/actions/create_file.rb +103 -0
  58. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/actions/directory.rb +91 -0
  59. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/actions/empty_directory.rb +134 -0
  60. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/actions/file_manipulation.rb +223 -0
  61. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/actions/inject_into_file.rb +104 -0
  62. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/base.rb +540 -0
  63. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/core_ext/file_binary_read.rb +9 -0
  64. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/core_ext/hash_with_indifferent_access.rb +75 -0
  65. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/core_ext/ordered_hash.rb +100 -0
  66. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/error.rb +30 -0
  67. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/group.rb +271 -0
  68. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/invocation.rb +180 -0
  69. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/parser.rb +4 -0
  70. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/parser/argument.rb +67 -0
  71. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/parser/arguments.rb +150 -0
  72. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/parser/option.rb +128 -0
  73. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/parser/options.rb +169 -0
  74. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/rake_compat.rb +66 -0
  75. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/runner.rb +314 -0
  76. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/shell.rb +83 -0
  77. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/shell/basic.rb +239 -0
  78. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/shell/color.rb +108 -0
  79. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/task.rb +102 -0
  80. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/util.rb +224 -0
  81. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/version.rb +3 -0
  82. data/lib/daemon_kit/xmpp.rb +100 -0
  83. data/lib/generators/daemon_kit/amqp/USAGE +5 -0
  84. data/lib/generators/daemon_kit/amqp/amqp_generator.rb +24 -0
  85. data/lib/generators/daemon_kit/amqp/templates/config/amqp.yml +28 -0
  86. data/lib/generators/daemon_kit/amqp/templates/config/pre-daemonize/amqp.rb +7 -0
  87. data/lib/generators/daemon_kit/amqp/templates/libexec/%app_name%-daemon.rb +37 -0
  88. data/lib/generators/daemon_kit/app/USAGE +7 -0
  89. data/lib/generators/daemon_kit/app/app_generator.rb +140 -0
  90. data/lib/generators/daemon_kit/app/templates/Gemfile +12 -0
  91. data/lib/generators/daemon_kit/app/templates/README.tt +58 -0
  92. data/lib/generators/daemon_kit/app/templates/Rakefile +6 -0
  93. data/lib/generators/daemon_kit/app/templates/bin/daemon.tt +7 -0
  94. data/lib/generators/daemon_kit/app/templates/config/arguments.rb +12 -0
  95. data/lib/generators/daemon_kit/app/templates/config/boot.rb +70 -0
  96. data/lib/generators/daemon_kit/app/templates/config/environment.rb.tt +26 -0
  97. data/lib/generators/daemon_kit/app/templates/config/environments/development.rb +2 -0
  98. data/lib/generators/daemon_kit/app/templates/config/environments/production.rb +5 -0
  99. data/lib/generators/daemon_kit/app/templates/config/environments/test.rb +2 -0
  100. data/lib/generators/daemon_kit/app/templates/config/post-daemonize/readme +5 -0
  101. data/lib/generators/daemon_kit/app/templates/config/pre-daemonize/readme +12 -0
  102. data/lib/generators/daemon_kit/app/templates/lib/%app_name%.rb +2 -0
  103. data/lib/generators/daemon_kit/app/templates/libexec/%app_name%-daemon.rb +18 -0
  104. data/lib/generators/daemon_kit/app/templates/script/console +3 -0
  105. data/lib/generators/daemon_kit/app/templates/script/destroy +3 -0
  106. data/lib/generators/daemon_kit/app/templates/script/generate +3 -0
  107. data/lib/generators/daemon_kit/capistrano/capistrano_generator.rb +26 -0
  108. data/lib/generators/daemon_kit/capistrano/templates/Capfile +10 -0
  109. data/lib/generators/daemon_kit/capistrano/templates/USAGE +10 -0
  110. data/lib/generators/daemon_kit/capistrano/templates/config/deploy.rb.tt +67 -0
  111. data/lib/generators/daemon_kit/capistrano/templates/config/deploy/logrotate.erb +13 -0
  112. data/lib/generators/daemon_kit/capistrano/templates/config/deploy/production.rb.tt +6 -0
  113. data/lib/generators/daemon_kit/capistrano/templates/config/deploy/staging.rb.tt +6 -0
  114. data/lib/generators/daemon_kit/capistrano/templates/config/environments/staging.rb +0 -0
  115. data/lib/generators/daemon_kit/cron/USAGE +5 -0
  116. data/lib/generators/daemon_kit/cron/cron_generator.rb +24 -0
  117. data/lib/generators/daemon_kit/cron/templates/config/pre-daemonize/cron.rb +11 -0
  118. data/lib/generators/daemon_kit/cron/templates/libexec/%app_name%-daemon.rb +48 -0
  119. data/lib/generators/daemon_kit/cucumber/USAGE +11 -0
  120. data/lib/generators/daemon_kit/cucumber/cucumber_generator.rb +45 -0
  121. data/lib/generators/daemon_kit/cucumber/templates/config/environments/cucumber.rb +2 -0
  122. data/lib/generators/daemon_kit/cucumber/templates/features/step_definitions/.empty_directory +0 -0
  123. data/lib/generators/daemon_kit/cucumber/templates/features/support/env.rb +7 -0
  124. data/lib/generators/daemon_kit/cucumber/templates/script/cucumber +7 -0
  125. data/lib/generators/daemon_kit/cucumber/templates/tasks/cucumber.rake +13 -0
  126. data/lib/generators/daemon_kit/nanite_agent/USAGE +5 -0
  127. data/lib/generators/daemon_kit/nanite_agent/nanite_agent_generator.rb +29 -0
  128. data/lib/generators/daemon_kit/nanite_agent/templates/config/nanite.yml +35 -0
  129. data/lib/generators/daemon_kit/nanite_agent/templates/config/pre-daemonize/nanite_agent.rb +6 -0
  130. data/lib/generators/daemon_kit/nanite_agent/templates/lib/actors/sample.rb +11 -0
  131. data/lib/generators/daemon_kit/nanite_agent/templates/libexec/%app_name%-daemon.rb +31 -0
  132. data/lib/generators/daemon_kit/rspec/USAGE +5 -0
  133. data/lib/generators/daemon_kit/rspec/rspec_generator.rb +20 -0
  134. data/lib/generators/daemon_kit/rspec/templates/spec/%app_name%_spec.rb +11 -0
  135. data/lib/generators/daemon_kit/rspec/templates/spec/spec.opts +1 -0
  136. data/lib/generators/daemon_kit/rspec/templates/spec/spec_helper.rb +23 -0
  137. data/lib/generators/daemon_kit/rspec/templates/tasks/rspec.rake +21 -0
  138. data/lib/generators/daemon_kit/ruote/USAGE +5 -0
  139. data/lib/generators/daemon_kit/ruote/ruote_generator.rb +29 -0
  140. data/lib/generators/daemon_kit/ruote/templates/config/amqp.yml +30 -0
  141. data/lib/generators/daemon_kit/ruote/templates/config/pre-daemonize/ruote.rb +13 -0
  142. data/lib/generators/daemon_kit/ruote/templates/config/ruote.yml +23 -0
  143. data/lib/generators/daemon_kit/ruote/templates/lib/%app_name%.rb +4 -0
  144. data/lib/generators/daemon_kit/ruote/templates/lib/sample.rb +26 -0
  145. data/lib/generators/daemon_kit/ruote/templates/libexec/%app_name%-daemon.rb +33 -0
  146. data/lib/generators/daemon_kit/test_unit/USAGE +5 -0
  147. data/lib/generators/daemon_kit/test_unit/templates/tasks/test_unit.rake +7 -0
  148. data/lib/generators/daemon_kit/test_unit/templates/test/%app_name%_test.rb.tt +9 -0
  149. data/lib/generators/daemon_kit/test_unit/templates/test/test_helper.rb +6 -0
  150. data/lib/generators/daemon_kit/test_unit/test_unit_generator.rb +20 -0
  151. data/lib/generators/daemon_kit/xmpp/templates/config/pre-daemonize/xmpp.rb +6 -0
  152. data/lib/generators/daemon_kit/xmpp/templates/config/xmpp.yml +29 -0
  153. data/lib/generators/daemon_kit/xmpp/templates/libexec/%app_name%-daemon.rb +27 -0
  154. data/lib/generators/daemon_kit/xmpp/xmpp_generator.rb +24 -0
  155. data/script/console +10 -0
  156. data/script/destroy +14 -0
  157. data/script/generate +14 -0
  158. data/script/txt2html +71 -0
  159. data/spec/abstract_logger_spec.rb +126 -0
  160. data/spec/argument_spec.rb +70 -0
  161. data/spec/config_spec.rb +83 -0
  162. data/spec/configurable_spec.rb +56 -0
  163. data/spec/daemon_kit_spec.rb +7 -0
  164. data/spec/error_handlers_spec.rb +23 -0
  165. data/spec/fixtures/env.yml +15 -0
  166. data/spec/fixtures/noenv.yml +4 -0
  167. data/spec/initializer_spec.rb +26 -0
  168. data/spec/spec.opts +1 -0
  169. data/spec/spec_helper.rb +27 -0
  170. data/tasks/cucumber.rake +13 -0
  171. data/tasks/rspec.rake +20 -0
  172. data/tasks/tests.rake +6 -0
  173. data/templates/god/god.erb +69 -0
  174. data/templates/monit/monit.erb +14 -0
  175. data/test/test_amqp_generator.rb +48 -0
  176. data/test/test_cron_generator.rb +45 -0
  177. data/test/test_daemon-kit_generator.rb +84 -0
  178. data/test/test_daemon_kit_config.rb +28 -0
  179. data/test/test_deploy_capistrano_generator.rb +48 -0
  180. data/test/test_generator_helper.rb +29 -0
  181. data/test/test_helper.rb +7 -0
  182. data/test/test_nanite_agent_generator.rb +49 -0
  183. data/test/test_ruote_generator.rb +51 -0
  184. data/test/test_test_unit_generator.rb +46 -0
  185. metadata +302 -0
@@ -0,0 +1,171 @@
1
+ require 'yaml'
2
+
3
+ module DaemonKit
4
+ # Thin wrapper around xmpp4r-simple, specifically designed to ease
5
+ # configuration of a jabber daemon and provide some added simplicity.
6
+ class Jabber
7
+
8
+ # Jabber connection
9
+ attr_reader :connection
10
+
11
+ @@instance = nil
12
+ @@message_handler = nil
13
+ @@presence_handler = nil
14
+ @@subscription_handler = nil
15
+
16
+ class << self
17
+
18
+ # Deliver a message to the specified jid.
19
+ def deliver( jid, message )
20
+ instance.connection.deliver( jid, message )
21
+ end
22
+
23
+ # Use this instead of initializing, keeps it singleton
24
+ def instance
25
+ @instance ||= new
26
+ @instance.startup!
27
+ end
28
+ private :new
29
+
30
+ def run
31
+ DaemonKit.logger.warn "Please use the new XMPP daemons, this class is deprecated"
32
+ DaemonKit.logger.info "Starting jabber loop"
33
+
34
+ loop do
35
+ process_messages
36
+ process_updates
37
+ process_subscriptions
38
+
39
+ begin
40
+ sleep 1
41
+ rescue Interrupt
42
+ DaemonKit.logger.warn "Jabber loop interrupted"
43
+ break
44
+ end
45
+ end
46
+ end
47
+
48
+ def process_messages
49
+ @message_handler ||= Proc.new { |m| DaemonKit.logger.info "Received message from #{m.from}: #{m.body}" }
50
+
51
+ instance.valid_messages { |m| @message_handler.call(m) }
52
+ end
53
+
54
+ def process_updates
55
+ @presence_handler ||= Proc.new { |friend, old_presence, new_presence|
56
+ DaemonKit.logger.debug "Received presence update: #{friend} went from #{old_presence} to #{new_presence}"
57
+ }
58
+
59
+ instance.connection.presence_updates { |friend, old_presence, new_presence|
60
+ @presence_handler.call(friend, old_presence, new_presence)
61
+ }
62
+
63
+ end
64
+
65
+ def process_subscriptions
66
+ @subscription_handler ||= Proc.new { |friend,presence| DaemonKit.logger.debug "Received presence update from #{friend}: #{presence}" }
67
+
68
+ instance.connection.subscription_requests { |friend,presence| @subscription_handler.call(friend,presence) }
69
+ end
70
+
71
+ def received_messages(&block)
72
+ @message_handler = block
73
+ end
74
+
75
+ def presence_updates(&block)
76
+ @presence_handler = block
77
+ end
78
+
79
+ def subscription_requests(&block)
80
+ @subscription_handler = block
81
+ end
82
+
83
+ end
84
+
85
+ def initialize
86
+ options = DaemonKit::Config.load( 'jabber' )
87
+
88
+ @jabber_id = options.delete("jabber_id")
89
+ @password = options.delete("password")
90
+ @resource = options.delete("resource") || 'daemon_kit'
91
+ @masters = options.delete("masters") || []
92
+ @supporters = options.delete("supporters") || []
93
+
94
+ raise ArgumentError if [ @jabber_id, @password ].any? { |a| a.nil? }
95
+ end
96
+
97
+ def startup!
98
+ return self if @booted
99
+
100
+ connect!
101
+ setup_roster!
102
+
103
+ DaemonKit.trap( 'INT', Proc.new { self.shutdown! } )
104
+ DaemonKit.trap( 'TERM', Proc.new { self.shutdown! } )
105
+
106
+ @booted = true
107
+
108
+ self
109
+ end
110
+
111
+ def shutdown!
112
+ DaemonKit.logger.warn "Disconnecting jabber connection"
113
+ self.connection.disconnect
114
+ end
115
+
116
+ def contacts
117
+ @masters + @supporters
118
+ end
119
+
120
+ def valid_messages(&block)
121
+ self.connection.received_messages.each do |message|
122
+ next unless valid_master?( message.from )
123
+
124
+ busy do
125
+ block.call message
126
+ end
127
+ end
128
+ end
129
+
130
+ def valid_master?( jid )
131
+ @masters.include?( jid.strip.to_s )
132
+ end
133
+
134
+ def busy(&block)
135
+ self.connection.status(:dnd, "Working...")
136
+ yield
137
+ self.connection.status(:chat, self.status_line )
138
+ end
139
+
140
+ def status_line
141
+ "#{DaemonKit.configuration.daemon_name} ready for instructions"
142
+ end
143
+
144
+ private
145
+
146
+ def connect!
147
+ jid = @jabber_id + '/' + @resource
148
+
149
+ @connection = ::Jabber::Simple.new( jid, @password, nil, self.status_line )
150
+ end
151
+
152
+ def setup_roster!
153
+ # cleanup the roster
154
+ self.connection.roster.items.each_pair do |jid, roster_item|
155
+ jid = jid.strip.to_s
156
+ unless self.contacts.include?( jid )
157
+ self.connection.remove( jid )
158
+ end
159
+ end
160
+
161
+ # add missing contacts
162
+ self.contacts.each do |jid|
163
+ unless self.connection.subscribed_to?( jid )
164
+ self.connection.add( jid )
165
+ #self.connection.accept_subscription( jid )
166
+ end
167
+ end
168
+ end
169
+
170
+ end
171
+ end
@@ -0,0 +1,7 @@
1
+ module DaemonKit
2
+ # For building daemons that integrate with nanite, either as mappers
3
+ # or agents. See #DaemonKit::Nanite::Agent so far
4
+ module Nanite
5
+ autoload :Agent, "daemon_kit/nanite/agent"
6
+ end
7
+ end
@@ -0,0 +1,77 @@
1
+ module Nanite
2
+ class Agent
3
+
4
+ attr_accessor :init_block
5
+
6
+ def load_actors_with_daemon_kit_changes( &block )
7
+ actors = @options[:actors]
8
+ Dir["#{DaemonKit.root}/lib/actors/*.rb"].each do |actor|
9
+ next if actors && !actors.include?( File.basename(actor, '.rb') )
10
+ Nanite::Log.info( "[setup] loading #{actor}" )
11
+ require actor
12
+ end
13
+
14
+ self.init_block.call( self )
15
+ end
16
+
17
+ alias_method :load_actors_without_daemon_kit_changes, :load_actors
18
+ alias_method :load_actors, :load_actors_with_daemon_kit_changes
19
+ end
20
+ end
21
+
22
+ module DaemonKit
23
+ module Nanite
24
+ # Pull support into a daemon for being a nanite agent.
25
+ class Agent
26
+
27
+ @@instance = nil
28
+
29
+ class << self
30
+
31
+ def instance
32
+ @instance ||= new
33
+ end
34
+
35
+ private :new
36
+
37
+ def run(&block)
38
+ instance.run(&block)
39
+ end
40
+
41
+ end
42
+
43
+ def initialize
44
+ @config = DaemonKit::Config.load( 'nanite' ).to_h( true )
45
+
46
+ config_agent
47
+ end
48
+
49
+ def run(&block)
50
+ # Ensure graceful shutdown of the connection to the broker
51
+ DaemonKit.trap('INT') { ::EM.stop }
52
+ DaemonKit.trap('TERM') { ::EM.stop }
53
+ ::Nanite::Log.logger = DaemonKit.logger
54
+
55
+ # Start our mapper
56
+ mapper_thread = Thread.new do
57
+ EM.run do
58
+ agent = ::Nanite::Agent.new( @config )
59
+ agent.init_block = block
60
+ agent.run
61
+ end
62
+ end
63
+
64
+ mapper_thread.join
65
+ end
66
+
67
+ private
68
+
69
+ # Make sure to fine tune the agent config to be DK friendly
70
+ def config_agent
71
+ @config[:root] = DAEMON_ROOT
72
+ @config[:daemonize] = false
73
+ @config[:actors_dir] = File.join(DAEMON_ROOT, 'lib', 'actors')
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,61 @@
1
+ module DaemonKit
2
+
3
+ # Simple pidfile handling for daemon processes
4
+ class PidFile
5
+
6
+ def initialize( path )
7
+ @path = path.to_absolute_path
8
+ end
9
+
10
+ def exists?
11
+ File.exists?( @path )
12
+ end
13
+
14
+ # Returns true if the process is running
15
+ def running?
16
+ return false unless self.exists?
17
+
18
+ # Check if process is in existence
19
+ # The simplest way to do this is to send signal '0'
20
+ # (which is a single system call) that doesn't actually
21
+ # send a signal
22
+ begin
23
+ Process.kill(0, self.pid)
24
+ return true
25
+ rescue Errno::ESRCH
26
+ return false
27
+ rescue ::Exception # for example on EPERM (process exists but does not belong to us)
28
+ return true
29
+ #rescue Errno::EPERM
30
+ # return false
31
+ end
32
+ end
33
+
34
+ # Return the pid contained in the pidfile, or nil
35
+ def pid
36
+ return nil unless self.exists?
37
+
38
+ File.open( @path ) { |f|
39
+ return f.gets.to_i
40
+ }
41
+ end
42
+
43
+ def ensure_stopped!
44
+ if self.running?
45
+ puts "Process already running with id #{self.pid}"
46
+ exit 1
47
+ end
48
+ end
49
+
50
+ def cleanup
51
+ File.delete( @path ) rescue Errno::ENOENT
52
+ end
53
+ alias zap cleanup
54
+
55
+ def write!
56
+ File.open( @path, 'w' ) { |f|
57
+ f.puts Process.pid
58
+ }
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,125 @@
1
+ module DaemonKit
2
+ # Class that cleanly abstracts away the different remote participants in
3
+ # ruote and allows daemon writers to just worry about processing workitems
4
+ # without worrying over the transport mechanism or anything else...
5
+ class RuoteParticipants
6
+
7
+ class << self
8
+
9
+ # Configure this daemon as a remote participant to ruote.
10
+ def configure(&block)
11
+ instance.configure(&block)
12
+ end
13
+
14
+ # Activate and run the remote participant code, calling the optional
15
+ # block for additional daemon logic.
16
+ def run(&block)
17
+ instance.run(&block)
18
+ end
19
+
20
+ private :new
21
+
22
+ def instance
23
+ @instance ||= new
24
+ end
25
+
26
+ private
27
+
28
+ def instance=( obj )
29
+ @instance = obj
30
+ end
31
+ end
32
+
33
+ attr_reader :participants
34
+
35
+ def initialize
36
+ @transports = []
37
+ @participants = {}
38
+ @runtime_queues = []
39
+
40
+ @configuration = Config.load('ruote')
41
+ end
42
+
43
+ # Yields +self+ and configures the remote participants
44
+ def configure(&block)
45
+ block.call( self )
46
+
47
+ @transports.freeze
48
+ @participants.freeze
49
+ end
50
+
51
+ # Enable the use of a specific transport for workitems. Can be :amqp to use
52
+ # the AMQPParticipant/AMQPListener pair in ruote.
53
+ def use( transport )
54
+ @transports << transport
55
+ end
56
+
57
+ # Register classes as pseudo-participants. Two styles of registration are
58
+ # supported:
59
+ #
60
+ # register( Foo )
61
+ # register( 'short', ShortParticipant )
62
+ #
63
+ # The first format uses the class name (downcased and underscored) as the
64
+ # key for identifying the pseudo-participant, the second uses the the
65
+ # provided key.
66
+ #
67
+ # Pseudo-participant classes are instantiated when registered, and the
68
+ # instances are re-used.
69
+ def register( *args )
70
+ key, klass = if args.size == 1
71
+ [ underscore( args.first.to_s ), args.first ]
72
+ else
73
+ [ args[0].to_s, args[1] ]
74
+ end
75
+
76
+ @participants[ key ] = klass.new
77
+ end
78
+
79
+ # Run the participants
80
+ def run(&block)
81
+ run_amqp! if @transports.include?( :amqp )
82
+ end
83
+
84
+ # Subscribe to additional queues not specified in ruote.yml
85
+ def subscribe_to( queue )
86
+ @runtime_queues << queue
87
+ end
88
+
89
+ private
90
+
91
+ def run_amqp!
92
+ AMQP.run do
93
+ mq = ::MQ.new
94
+ queues = @configuration['amqp']['queues'].to_a | @runtime_queues
95
+
96
+ queues.each do |q|
97
+ DaemonKit.logger.debug("Subscribing to #{q} for workitems")
98
+
99
+ cmdq = mq.queue( q, :durable => true )
100
+ cmdq.subscribe( :ack => true ) do |header, message|
101
+ safely do
102
+ DaemonKit.logger.debug("Received workitem: #{message.inspect}")
103
+
104
+ RuoteWorkitem.process( :amqp, message )
105
+
106
+ DaemonKit.logger.debug("Processed workitem.")
107
+
108
+ header.ack
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ # Shamelessly lifted from the ActiveSupport inflector
116
+ def underscore(camel_cased_word)
117
+ camel_cased_word.to_s.gsub(/::/, '/').
118
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
119
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
120
+ tr("-", "_").
121
+ downcase
122
+ end
123
+ end
124
+
125
+ end
@@ -0,0 +1,68 @@
1
+ module DaemonKit
2
+ # Common convenience methods for making ruote pseudo-participants more DRY
3
+ # and unified
4
+ class RuotePseudoParticipant
5
+
6
+ class << self
7
+
8
+ attr_reader :exception_handler_method, :exception_handler_block,
9
+ :on_complete_handler_method, :on_complete_handler_block
10
+
11
+ # Register a callback method or block that gets called when an exception
12
+ # occurs during the processing of an action. +handler+ can be a symbol or
13
+ # string with a method name, or a block. Both will get the exception as
14
+ # the first parameter, and the block handler will receive the participant
15
+ # instance as the second parameter
16
+ def on_exception( handler = nil, &block )
17
+ @exception_handler_method = handler
18
+ @exception_handler_block = block
19
+ end
20
+
21
+ # Register a callback method or block that gets called when the action
22
+ # was successfully completed. Block callbacks get the workitem as
23
+ # parameter.
24
+ def on_complete( handler = nil, &block )
25
+ @on_complete_handler_method = handler
26
+ @on_complete_handler_block = block
27
+ end
28
+ end
29
+
30
+ # Current workitem
31
+ attr_reader :workitem
32
+
33
+ # Current action
34
+ attr_reader :action
35
+
36
+ # Perform the specified action with the provided workitem
37
+ def perform( action, workitem )
38
+ @action, @workitem = action, workitem
39
+
40
+ begin
41
+ send( action )
42
+ run_callbacks
43
+ rescue => e
44
+ handle_exception( e )
45
+ end
46
+ end
47
+
48
+ def handle_exception( e )
49
+ raise e if self.class.exception_handler_method.nil? && self.class.exception_handler_block.nil?
50
+
51
+ if self.class.exception_handler_method
52
+ send( self.class.exception_handler_method, e )
53
+ else
54
+ self.class.exception_handler_block.call( e, self )
55
+ end
56
+ end
57
+
58
+ def run_callbacks
59
+ return if self.class.on_complete_handler_block.nil? && self.class.on_complete_handler_method.nil?
60
+
61
+ if self.class.on_complete_handler_method
62
+ send( self.class.on_complete_handler_method )
63
+ else
64
+ self.class.on_complete_handler_block.call( workitem )
65
+ end
66
+ end
67
+ end
68
+ end