kennethkalmer-daemon-kit 0.1.7.9 → 0.1.7.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,169 @@
1
+ module DaemonKit
2
+
3
+ # Dual purpose class that is a) responsible for parsing incoming workitems and
4
+ # delegating to the correct RuotePseudoParticipant, and b) wrapping the
5
+ # workitem hash into something a bit more digestable.
6
+ class RuoteWorkitem
7
+
8
+ class << self
9
+
10
+ # = Process incoming commands via an AMQP queue
11
+ #
12
+ # Expects a JSON workitem from ruote that has these fields set in
13
+ # attributes key:
14
+ #
15
+ # {
16
+ # 'reply_queue' => 'queue to send replies to',
17
+ # 'params' => {
18
+ # 'command' => '/actor/method'
19
+ # }
20
+ # }
21
+ #
22
+ # == Notes on the command key:
23
+ #
24
+ # It looks like a resource, and will be treated as such. Is should
25
+ # be in the format of +/class/method+, and it will be passed the
26
+ # complete workitem as a hash.
27
+ #
28
+ # == Notes on replies
29
+ #
30
+ # Replies are sent back to the queue specified in the +reply_queue+ key.
31
+ #
32
+ # == Notes on errors
33
+ #
34
+ # Where daemon-kit detects errors in attempting to parse and delegate the
35
+ # workitems, it will reply to the engine and set the following field with
36
+ # the error information:
37
+ #
38
+ # daemon_kit.error
39
+ def process( transport, workitem )
40
+ # keep it singleton
41
+ @instance ||= new
42
+
43
+ work = parse( workitem )
44
+
45
+ DaemonKit.logger.warn "Processing workitem that has timed out!" if work.timed_out?
46
+
47
+ target, method = parse_command( work )
48
+
49
+ if target.nil? || method.nil?
50
+ msg = "Missing target/method in command parameter, or command parameter missing"
51
+ DaemonKit.logger.error( msg )
52
+ work["daemon_kit"] = { "error" => msg }
53
+
54
+ elsif target.public_methods.include?( method )
55
+ target.perform( method, work )
56
+
57
+ else
58
+ msg = "Workitem cannot be processes: #{method} not exposed by #{target.inspect}"
59
+ DaemonKit.logger.error( msg )
60
+ work["daemon_kit"] = { "error" => msg }
61
+ end
62
+
63
+ reply_to_engine( transport, work )
64
+ end
65
+
66
+ # Extract the class and method name from the workitem, then pick the matching
67
+ # class from the registered list of participants
68
+ def parse_command( work )
69
+ return nil if work['params']['command'].nil?
70
+
71
+ _, klass, method = work['params']['command'].split('/')
72
+
73
+ instance = RuoteParticipants.instance.participants[ klass ]
74
+
75
+ if instance.nil?
76
+ msg = "No instance registered for #{klass}"
77
+ DaemonKit.logger.error( msg )
78
+ raise DaemonKit::MissingParticipant, msg
79
+ end
80
+
81
+ return instance, method
82
+ end
83
+
84
+ def reply_to_engine( transport, response )
85
+ send( "reply_via_#{transport}", response )
86
+ end
87
+
88
+ def reply_via_amqp( response )
89
+ DaemonKit.logger.debug("Replying to engine via AMQP with #{response.inspect}")
90
+
91
+ ::MQ.queue( response['reply_queue'] ).publish( response.to_json )
92
+
93
+ response
94
+ end
95
+
96
+ def parse( workitem )
97
+ new( JSON.parse( workitem ) )
98
+ end
99
+ end
100
+
101
+ def initialize( workitem = {} )
102
+ @workitem = workitem
103
+ end
104
+
105
+ def fei
106
+ @workitem['flow_expression_id']
107
+ end
108
+
109
+ def short_fei
110
+ @short_fei ||=
111
+ '(' + [
112
+ 'fei', self.fei['owfe_version'], self.fei['engine_id'],
113
+ self.fei['workflow_definition_url'], self.fei['workflow_definition_name'],
114
+ self.fei['workflow_definition_revision'], self.fei['workflow_instance_id'],
115
+ self.fei['expression_name'], self.fei['expression_id']
116
+ ].join(' ') + ')'
117
+ end
118
+
119
+ def dispatch_time
120
+ @dispath_time ||= Time.parse( @workitem['dispatch_time'] )
121
+ end
122
+
123
+ def last_modified
124
+ @last_modified ||= Time.parse( @workitem['last_modified'] )
125
+ end
126
+
127
+ def participant_name
128
+ @workitem['participant_name']
129
+ end
130
+
131
+ def attributes
132
+ @workitem['attributes']
133
+ end
134
+
135
+ def []( key )
136
+ self.attributes[ key ]
137
+ end
138
+
139
+ def []=( key, value )
140
+ self.attributes[ key ] = value
141
+ end
142
+
143
+ def to_json
144
+ @workitem.to_json
145
+ end
146
+
147
+ # Look at the workitem payload and attempt to determine if this workitem
148
+ # has timed out or not. This method will only ever work if you used the
149
+ # +:timeout: parameter was set for the expression.
150
+ def timed_out?
151
+ key = fei['workflow_instance_id'] + '__' + fei['expression_id']
152
+
153
+ if self.attributes["__timeouts__"] && timeout = self.attributes["__timeouts__"][ key ]
154
+ return Time.at( timeout.last ) < Time.now
155
+ end
156
+
157
+ return false
158
+ end
159
+
160
+ def method_missing( method_name, *args )
161
+ if self.attributes.keys.include?( method_name.to_s )
162
+ return self.attributes[ method_name.to_s ]
163
+ end
164
+
165
+ super
166
+ end
167
+
168
+ end
169
+ end
@@ -47,5 +47,24 @@ describe DaemonKit::Arguments do
47
47
 
48
48
  res.last.should == [ '-h' ]
49
49
  end
50
+
51
+ it "should handle different ordered configurations easily" do
52
+ argv = [ '--pid', '/tmp/piddy', '--log', '/tmp/loggy' ]
53
+ res = DaemonKit::Arguments.configuration( argv )
54
+
55
+ # No additional args
56
+ res.last.should be_empty
57
+
58
+ res.first[0].should == "pid_file=/tmp/piddy"
59
+ res.first[1].should == "log_path=/tmp/loggy"
60
+ end
61
+
62
+ it "should handle mixed configurations easily" do
63
+ argv = [ '--rest', 'yes', '-l', '/tmp/loggy', '-f', 'bar' ]
64
+ res = DaemonKit::Arguments.configuration( argv )
65
+
66
+ res.first.should == [ 'log_path=/tmp/loggy' ]
67
+ res.last.should == [ '--rest', 'yes', '-f', 'bar' ]
68
+ end
50
69
  end
51
70
  end
data/spec/config_spec.rb CHANGED
@@ -4,7 +4,7 @@ describe DaemonKit::Config do
4
4
 
5
5
  describe "working with config data" do
6
6
  before(:each) do
7
- @config = DaemonKit::Config.new('foo' => 'bar')
7
+ @config = DaemonKit::Config.new('foo' => 'bar', 'nes' => { 'ted' => 'value' })
8
8
  end
9
9
 
10
10
  it "should have string key access to values" do
@@ -19,15 +19,17 @@ describe DaemonKit::Config do
19
19
  @config.foo.should == 'bar'
20
20
  end
21
21
 
22
- it "should return the config as a has" do
23
- @config.to_h.should == { 'foo' => 'bar' }
22
+ it "should have nested instance accessors to values" do
23
+ @config.nes.ted.should == 'value'
24
24
  end
25
25
 
26
- it "should be able to symbolize keys in returned hash" do
27
- @config.to_h(true).should == { :foo => 'bar' }
26
+ it "should return the config as a hash" do
27
+ @config.to_h.should == { 'foo' => 'bar', 'nes' => { 'ted' => 'value' } }
28
28
  end
29
29
 
30
- it "should symbolize keys in a nested fashion"
30
+ it "should be able to symbolize keys in returned hash" do
31
+ @config.to_h(true).should == { :foo => 'bar', :nes => { :ted => 'value' } }
32
+ end
31
33
  end
32
34
 
33
35
  describe "parsing files" do
@@ -18,15 +18,9 @@ describe DaemonKit::Configuration do
18
18
  @configuration.log_level.should_not be_nil
19
19
  end
20
20
 
21
- end
22
-
23
-
24
- describe DaemonKit::Initializer do
25
-
26
- it "should setup a logger" do
27
- pending
28
- DaemonKit::Initializer.run(:initialize_logger)
29
- DaemonKit.logger.should_not be_nil
21
+ it "should set a default umask" do
22
+ File.umask.should_not be(0)
23
+ File.umask.should be(18)
30
24
  end
31
25
 
32
26
  end
@@ -0,0 +1,45 @@
1
+ require File.join(File.dirname(__FILE__), "test_generator_helper.rb")
2
+
3
+
4
+ class TestRuoteGenerator < Test::Unit::TestCase
5
+ include RubiGen::GeneratorTestHelper
6
+
7
+ def setup
8
+ bare_setup
9
+ end
10
+
11
+ def teardown
12
+ bare_teardown
13
+ end
14
+
15
+ # Some generator-related assertions:
16
+ # assert_generated_file(name, &block) # block passed the file contents
17
+ # assert_directory_exists(name)
18
+ # assert_generated_class(name, &block)
19
+ # assert_generated_module(name, &block)
20
+ # assert_generated_test_for(name, &block)
21
+ # The assert_generated_(class|module|test_for) &block is passed the body of the class/module within the file
22
+ # assert_has_method(body, *methods) # check that the body has a list of methods (methods with parentheses not supported yet)
23
+ #
24
+ # Other helper methods are:
25
+ # app_root_files - put this in teardown to show files generated by the test method (e.g. p app_root_files)
26
+ # bare_setup - place this in setup method to create the APP_ROOT folder for each test
27
+ # bare_teardown - place this in teardown method to destroy the TMP_ROOT or APP_ROOT folder after each test
28
+
29
+ def test_generator_without_options
30
+ name = "myapp"
31
+ run_generator('ruote', [name], sources)
32
+ assert_directory_exists "some/directory"
33
+ assert_generated_file "some_file"
34
+ end
35
+
36
+ private
37
+ def sources
38
+ [RubiGen::PathSource.new(:test, File.join(File.dirname(__FILE__),"..", generator_path))
39
+ ]
40
+ end
41
+
42
+ def generator_path
43
+ "daemon_generators"
44
+ end
45
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kennethkalmer-daemon-kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7.9
4
+ version: 0.1.7.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenneth Kalmer
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-22 00:00:00 -07:00
12
+ date: 2009-08-12 00:00:00 -07:00
13
13
  default_executable: daemon_kit
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -40,7 +40,7 @@ dependencies:
40
40
  requirements:
41
41
  - - ">="
42
42
  - !ruby/object:Gem::Version
43
- version: 1.4.1
43
+ version: 1.5.1
44
44
  version:
45
45
  - !ruby/object:Gem::Dependency
46
46
  name: hoe
@@ -50,9 +50,9 @@ dependencies:
50
50
  requirements:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: 1.8.0
53
+ version: 2.3.2
54
54
  version:
55
- description: "Daemon Kit aims to simplify creating Ruby daemons by providing a sound application skeleton (through a generator), task specific generators (jabber bot, etc) and robust environment management code. Using simple built-in generators it is easy to created evented and non-evented daemons that perform a multitude of different tasks. Supported generators: * Evented and non-evented Jabber Bot (coming next) * Evented and non-evented loops (coming soon) * Queue poller (SQS, AMQP, etc) (coming soon)"
55
+ description: "Daemon Kit aims to simplify creating Ruby daemons by providing a sound application skeleton (through a generator), task specific generators (jabber bot, etc) and robust environment management code. Using simple built-in generators it is easy to created evented and non-evented daemons that perform a multitude of different tasks. Supported generators: * XMPP bot (non-evented) * AMQP consumer (evented) * Nanite agent * Cron-style daemon * ruote remote participants"
56
56
  email:
57
57
  - kenneth.kalmer@gmail.com
58
58
  executables:
@@ -66,7 +66,7 @@ extra_rdoc_files:
66
66
  - Logging.txt
67
67
  - Manifest.txt
68
68
  - PostInstall.txt
69
- - README.rdoc
69
+ - RuoteParticipants.txt
70
70
  - TODO.txt
71
71
  files:
72
72
  - Configuration.txt
@@ -77,6 +77,7 @@ files:
77
77
  - PostInstall.txt
78
78
  - README.rdoc
79
79
  - Rakefile
80
+ - RuoteParticipants.txt
80
81
  - TODO.txt
81
82
  - app_generators/daemon_kit/USAGE
82
83
  - app_generators/daemon_kit/daemon_kit_generator.rb
@@ -136,6 +137,14 @@ files:
136
137
  - daemon_generators/rspec/templates/spec/spec.opts
137
138
  - daemon_generators/rspec/templates/spec/spec_helper.rb
138
139
  - daemon_generators/rspec/templates/tasks/rspec.rake
140
+ - daemon_generators/ruote/USAGE
141
+ - daemon_generators/ruote/ruote_generator.rb
142
+ - daemon_generators/ruote/templates/config/amqp.yml
143
+ - daemon_generators/ruote/templates/config/initializers/ruote.rb
144
+ - daemon_generators/ruote/templates/config/ruote.yml
145
+ - daemon_generators/ruote/templates/lib/daemon.rb
146
+ - daemon_generators/ruote/templates/lib/sample.rb
147
+ - daemon_generators/ruote/templates/libexec/daemon.rb
139
148
  - lib/daemon_kit.rb
140
149
  - lib/daemon_kit/abstract_logger.rb
141
150
  - lib/daemon_kit/amqp.rb
@@ -154,11 +163,15 @@ files:
154
163
  - lib/daemon_kit/error_handlers/base.rb
155
164
  - lib/daemon_kit/error_handlers/hoptoad.rb
156
165
  - lib/daemon_kit/error_handlers/mail.rb
166
+ - lib/daemon_kit/exceptions.rb
157
167
  - lib/daemon_kit/initializer.rb
158
168
  - lib/daemon_kit/jabber.rb
159
169
  - lib/daemon_kit/nanite.rb
160
170
  - lib/daemon_kit/nanite/agent.rb
161
171
  - lib/daemon_kit/pid_file.rb
172
+ - lib/daemon_kit/ruote_participants.rb
173
+ - lib/daemon_kit/ruote_pseudo_participant.rb
174
+ - lib/daemon_kit/ruote_workitem.rb
162
175
  - lib/daemon_kit/safety.rb
163
176
  - lib/daemon_kit/tasks.rb
164
177
  - lib/daemon_kit/tasks/environment.rake
@@ -193,6 +206,7 @@ files:
193
206
  - test/test_helper.rb
194
207
  - test/test_jabber_generator.rb
195
208
  - test/test_nanite_agent_generator.rb
209
+ - test/test_ruote_generator.rb
196
210
  - vendor/tmail-1.2.3/tmail.rb
197
211
  - vendor/tmail-1.2.3/tmail/address.rb
198
212
  - vendor/tmail-1.2.3/tmail/attachments.rb
@@ -221,8 +235,9 @@ files:
221
235
  - vendor/tmail-1.2.3/tmail/utils.rb
222
236
  - vendor/tmail-1.2.3/tmail/version.rb
223
237
  - vendor/tmail.rb
224
- has_rdoc: true
238
+ has_rdoc: false
225
239
  homepage: http://kit.rubyforge.org/daemon-kit/rdoc/
240
+ licenses:
226
241
  post_install_message: |+
227
242
 
228
243
  For more information on daemon-kit, see http://kit.rubyforge.org/daemon-kit
@@ -250,17 +265,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
250
265
  requirements: []
251
266
 
252
267
  rubyforge_project: kit
253
- rubygems_version: 1.2.0
268
+ rubygems_version: 1.3.5
254
269
  signing_key:
255
- specification_version: 2
270
+ specification_version: 3
256
271
  summary: Daemon Kit aims to simplify creating Ruby daemons by providing a sound application skeleton (through a generator), task specific generators (jabber bot, etc) and robust environment management code.
257
272
  test_files:
258
273
  - test/test_generator_helper.rb
259
- - test/test_cron_generator.rb
260
- - test/test_nanite_agent_generator.rb
261
- - test/test_daemon_kit_config.rb
262
- - test/test_helper.rb
263
274
  - test/test_amqp_generator.rb
275
+ - test/test_cron_generator.rb
264
276
  - test/test_daemon-kit_generator.rb
277
+ - test/test_daemon_kit_config.rb
265
278
  - test/test_deploy_capistrano_generator.rb
279
+ - test/test_helper.rb
266
280
  - test/test_jabber_generator.rb
281
+ - test/test_nanite_agent_generator.rb
282
+ - test/test_ruote_generator.rb