textgoeshere-daemon-kit 0.1.8rc3

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.
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 +124 -0
  5. data/Logging.txt +96 -0
  6. data/PostInstall.txt +6 -0
  7. data/README.rdoc +128 -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/abstract_logger.rb +249 -0
  15. data/lib/daemon_kit/amqp.rb +39 -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/configurable.rb +96 -0
  24. data/lib/daemon_kit/core_ext/string.rb +22 -0
  25. data/lib/daemon_kit/core_ext.rb +1 -0
  26. data/lib/daemon_kit/cron.rb +48 -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/em.rb +43 -0
  30. data/lib/daemon_kit/error_handlers/base.rb +32 -0
  31. data/lib/daemon_kit/error_handlers/hoptoad.rb +180 -0
  32. data/lib/daemon_kit/exceptions.rb +15 -0
  33. data/lib/daemon_kit/generators/base.rb +60 -0
  34. data/lib/daemon_kit/generators.rb +67 -0
  35. data/lib/daemon_kit/initializer.rb +453 -0
  36. data/lib/daemon_kit/jabber.rb +171 -0
  37. data/lib/daemon_kit/nanite/agent.rb +77 -0
  38. data/lib/daemon_kit/nanite.rb +7 -0
  39. data/lib/daemon_kit/pid_file.rb +61 -0
  40. data/lib/daemon_kit/ruote_participants.rb +125 -0
  41. data/lib/daemon_kit/ruote_pseudo_participant.rb +68 -0
  42. data/lib/daemon_kit/ruote_workitem.rb +187 -0
  43. data/lib/daemon_kit/safety.rb +84 -0
  44. data/lib/daemon_kit/tasks/environment.rake +10 -0
  45. data/lib/daemon_kit/tasks/framework.rake +123 -0
  46. data/lib/daemon_kit/tasks/god.rake +62 -0
  47. data/lib/daemon_kit/tasks/log.rake +8 -0
  48. data/lib/daemon_kit/tasks/monit.rake +29 -0
  49. data/lib/daemon_kit/tasks.rb +2 -0
  50. data/lib/daemon_kit/vendor/thor-0.13.6/CHANGELOG.rdoc +89 -0
  51. data/lib/daemon_kit/vendor/thor-0.13.6/LICENSE +20 -0
  52. data/lib/daemon_kit/vendor/thor-0.13.6/README.rdoc +297 -0
  53. data/lib/daemon_kit/vendor/thor-0.13.6/Thorfile +69 -0
  54. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/actions/create_file.rb +103 -0
  55. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/actions/directory.rb +91 -0
  56. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/actions/empty_directory.rb +134 -0
  57. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/actions/file_manipulation.rb +223 -0
  58. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/actions/inject_into_file.rb +104 -0
  59. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/actions.rb +296 -0
  60. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/base.rb +540 -0
  61. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/core_ext/file_binary_read.rb +9 -0
  62. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/core_ext/hash_with_indifferent_access.rb +75 -0
  63. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/core_ext/ordered_hash.rb +100 -0
  64. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/error.rb +30 -0
  65. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/group.rb +271 -0
  66. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/invocation.rb +180 -0
  67. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/parser/argument.rb +67 -0
  68. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/parser/arguments.rb +150 -0
  69. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/parser/option.rb +128 -0
  70. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/parser/options.rb +169 -0
  71. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/parser.rb +4 -0
  72. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/rake_compat.rb +66 -0
  73. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/runner.rb +314 -0
  74. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/shell/basic.rb +239 -0
  75. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/shell/color.rb +108 -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/task.rb +102 -0
  78. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/util.rb +224 -0
  79. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor/version.rb +3 -0
  80. data/lib/daemon_kit/vendor/thor-0.13.6/lib/thor.rb +244 -0
  81. data/lib/daemon_kit/xmpp.rb +100 -0
  82. data/lib/daemon_kit.rb +59 -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 +8 -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/logrotate.erb +13 -0
  111. data/lib/generators/daemon_kit/capistrano/templates/config/deploy/production.rb.tt +6 -0
  112. data/lib/generators/daemon_kit/capistrano/templates/config/deploy/staging.rb.tt +6 -0
  113. data/lib/generators/daemon_kit/capistrano/templates/config/deploy.rb.tt +67 -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 +43 -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 +19 -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 +21 -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 +325 -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,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,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,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