langrove-plugin-resque 0.0.9

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.
data/README.md ADDED
@@ -0,0 +1,78 @@
1
+ `Plugin::Resque`
2
+ =================
3
+
4
+ Intergates Resque support into LanGrove.</ br>
5
+
6
+
7
+ `gem install langrove-plugin-resque`
8
+
9
+ Implements
10
+ ----------
11
+
12
+ * `Adaptor::ResqueWorker`
13
+ * `Handler::ResqueJob`
14
+ * `Plugin::ResqueQue`
15
+
16
+
17
+ Supports
18
+ ---------
19
+
20
+ * `LanGrove::Adaptor`
21
+ * `LanGrove::Behaviour::Deferrable`
22
+
23
+
24
+ Examples
25
+ --------
26
+
27
+ ### Configure to post jobs onto a queue.
28
+
29
+ <pre>
30
+
31
+ ...
32
+
33
+ :plugins:
34
+ :a_job_queue:
35
+ :class: ResqueQue
36
+ :job: JobName
37
+ :queue: job_name
38
+
39
+ ...
40
+
41
+ :server:
42
+ :behavior:
43
+ :deferrable:
44
+ :plugin: :a_job_queue
45
+ :at:
46
+ :handler_after_receive: :defer_capsule
47
+ #
48
+ # will post the caspsule as payload
49
+ # onto the specified resque queue
50
+ # after the Handler.receive( data )
51
+ # method returns.
52
+ #
53
+
54
+ ...
55
+
56
+ </pre>
57
+
58
+ ### Configure to perform jobs on a queue.
59
+
60
+ <pre>
61
+
62
+ ...
63
+
64
+ :adaptor:
65
+ :class: ResqueAdaptor
66
+ :queue: job_name
67
+
68
+ ...
69
+
70
+ :handler:
71
+ :class: JobName
72
+ #
73
+ # Should extend Handler::ResqueJob
74
+ #
75
+
76
+ ...
77
+
78
+ </pre>
@@ -0,0 +1,95 @@
1
+ module Resque
2
+
3
+ class Worker
4
+
5
+ #
6
+ # Alias the shutdown! as called on the INT and TERM
7
+ # traps that Resque assigned,
8
+ #
9
+ # So that the surrounding Daemon can also receive the
10
+ # instruction to stop.
11
+ #
12
+ #
13
+ alias_method :resque_shutdown!, :shutdown!
14
+
15
+ def shutdown!
16
+
17
+ #
18
+ # Call the original Worker shutdown!
19
+ # And further raise the instruction to stop.
20
+ #
21
+
22
+ resque_shutdown!
23
+
24
+ raise LanGrove::DaemonStopException.new
25
+
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+
32
+ module Adaptor
33
+
34
+ class ResqueAdaptor < LanGrove::Adaptor::Base
35
+
36
+ def initialize( root, config, deamon_name )
37
+
38
+ super
39
+
40
+ @type = :resque_adaptor
41
+
42
+ raise config_exception(
43
+
44
+ "#{self.class} requires :queue:"
45
+
46
+ ) if (
47
+
48
+ config.nil? or
49
+
50
+ not config.has_key?( :queue ) or
51
+ not @queue = config[ :queue ] or
52
+ @queue == ''
53
+
54
+ )
55
+
56
+ end
57
+
58
+ def connector( params, &block )
59
+
60
+ #
61
+ # This yields Resque::Job(s),
62
+ # one at a time,
63
+ # into the caller.
64
+ #
65
+
66
+ wait_for_job( @queue, &block )
67
+
68
+ end
69
+
70
+ private
71
+
72
+ def wait_for_job( queue, &block )
73
+
74
+ worker = Resque::Worker.new( queue )
75
+
76
+ worker.work do |job_spec|
77
+
78
+ new_job = job_spec.payload_class.new
79
+
80
+ new_job.payload = job_spec.payload
81
+
82
+ #
83
+ # Job is yielded up the assignment pipeline to
84
+ # get access to all the local infrastructure.
85
+ #
86
+
87
+ yield new_job
88
+
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+
95
+ end
@@ -0,0 +1,102 @@
1
+ module Handler
2
+
3
+ class ResqueJob < LanGrove::Handler::Base
4
+
5
+ attr_accessor :payload
6
+
7
+ def start_handler
8
+
9
+ #
10
+ # Trigger the handler_start event
11
+ #
12
+ @root.trigger( self, :handler, :start )
13
+
14
+ #
15
+ # The job payload header may define an :action
16
+ # to perform,
17
+ #
18
+ unless payload['args'][0]['action'].nil?
19
+
20
+ unless self.respond_to?( payload['args'][0]['action'].to_sym )
21
+
22
+ #
23
+ # local handler does not define that action
24
+ # bring the house down
25
+ #
26
+ raise LanGrove::DaemonConfigException(
27
+
28
+ "#{self.class}.#{payload[0]['action']}() not defined. Required by payload header: #{payload[0].inspect} "
29
+
30
+ )
31
+
32
+ end
33
+
34
+ #
35
+ # Should the header :action return false,
36
+ #
37
+ unless self.send( payload['args'][0]['action'].to_sym )
38
+
39
+ #
40
+ # Then the job will be skipped.
41
+ #
42
+ @logger.debug "#{self.class} job SKIPPED"
43
+
44
+ return
45
+
46
+ end
47
+
48
+ end
49
+
50
+
51
+ #
52
+ # Call implementor overridable start
53
+ #
54
+ start
55
+
56
+ do_work
57
+
58
+
59
+ #
60
+ # Job was sent up the same assignment pipeline as
61
+ # socket handler,
62
+ #
63
+ # It has therefore been assigned into the server's
64
+ # @client collection
65
+ #
66
+ # It needs to be removed
67
+ #
68
+ I.notify( @logger, "need to disconnect from server here", [:vital] )
69
+ #
70
+ #
71
+ #
72
+
73
+ stop
74
+
75
+ end
76
+
77
+
78
+ def stop_handler
79
+
80
+ @root.trigger( self, :handler, :stop )
81
+
82
+ stop
83
+
84
+ end
85
+
86
+
87
+ def self.perform( *args )
88
+
89
+ #
90
+ # Does not do the job, serves only to collect
91
+ # the payload and yield into the local runtime
92
+ # via the ResqueAdaptor,
93
+ #
94
+ # Requeue jobs are marked as failed unless this
95
+ # is present.
96
+ #
97
+
98
+ end
99
+
100
+ end
101
+
102
+ end
@@ -0,0 +1,4 @@
1
+ require 'langrove' unless defined?( LanGrove )
2
+ require 'adaptor/resque_adaptor'
3
+ require 'plugin/resque_que'
4
+ require 'handler/resque_job'
@@ -0,0 +1,130 @@
1
+
2
+ #
3
+ # brew install redis
4
+ # - For the queue db
5
+ #
6
+ # bundler installed resque
7
+ # (per the Gemfile)
8
+ #
9
+ # resque-web
10
+ # - Starts a queue stats interface at http://localhost:5678/
11
+ #
12
+
13
+ module Plugin
14
+
15
+ class ResqueQue < LanGrove::Plugin::Deferrer
16
+
17
+ def validate_config
18
+
19
+ super
20
+
21
+ config_exception(
22
+
23
+ "#{self.class} requires :queue: defined"
24
+
25
+ ) if @config[:queue].nil? or @config[:queue] == ''
26
+
27
+ queue = @config[:queue]
28
+
29
+
30
+ #
31
+ # Dynamically define job class
32
+ #
33
+ # - Resque wants a class with @queue
34
+ # defined
35
+ # - Make one to give
36
+ #
37
+
38
+ @job_class = Object.const_set( @job,
39
+
40
+ Class.new do
41
+
42
+ self.instance_variable_set(
43
+
44
+ :@queue, queue
45
+
46
+ )
47
+
48
+ end
49
+
50
+ )
51
+
52
+ end
53
+
54
+
55
+ def defer_key( handler )
56
+
57
+ #
58
+ # Enqueue job with the handler.key
59
+ #
60
+
61
+ return enqueue(
62
+
63
+ queue_header( :get_capsule, handler ),
64
+
65
+ handler.key
66
+
67
+ )
68
+
69
+ end
70
+
71
+ def defer_capsule( handler )
72
+
73
+ #
74
+ # Enqueue job with the handler.capsule
75
+ #
76
+
77
+ return enqueue(
78
+
79
+ queue_header( :load_capsule, handler ),
80
+
81
+ handler.capsule
82
+
83
+ )
84
+
85
+ end
86
+
87
+ private
88
+
89
+ def enqueue( header, payload )
90
+
91
+ begin
92
+
93
+ Resque.enqueue(
94
+
95
+ @job_class,
96
+
97
+ header,
98
+
99
+ payload
100
+
101
+ )
102
+
103
+ @logger.debug(
104
+
105
+ "#{self.class}.enqueue():#{type} job:#{@job_class} parameter:#{payload.inspect}"
106
+
107
+ )
108
+
109
+ return true
110
+
111
+ rescue Exception => e
112
+
113
+ error =
114
+
115
+ "#{self.class} failed to enqueue: #{header},#{payload} as #{type}, Exception #{e}"
116
+
117
+ @logger.error( error )
118
+
119
+ #
120
+ # The daemon needs to fall over.
121
+ #
122
+ raise e
123
+
124
+ end
125
+
126
+ end
127
+
128
+ end
129
+
130
+ end
@@ -0,0 +1,152 @@
1
+ require 'langrove-plugin-resque'
2
+
3
+ describe Adaptor::ResqueAdaptor do
4
+
5
+ before :all do
6
+
7
+ class FakeJob < Handler::ResqueJob
8
+
9
+ end
10
+
11
+ ROOT = LanGrove::FakeRoot.new
12
+
13
+ end
14
+
15
+
16
+ before :each do
17
+
18
+ @queue_name = :queue_name
19
+
20
+ @config = {
21
+
22
+ :queue => @queue_name
23
+
24
+ }
25
+
26
+ @connect_spec = {
27
+
28
+ :handler => {
29
+
30
+ :class => Handler::ResqueJob,
31
+
32
+ :config => {}
33
+
34
+ }
35
+
36
+ }
37
+
38
+ end
39
+
40
+ subject {
41
+
42
+ Adaptor::ResqueAdaptor.new(
43
+
44
+ ROOT, @config , nil
45
+
46
+ )
47
+
48
+ }
49
+
50
+ it 'raises on missing queue name' do
51
+
52
+ expect {
53
+
54
+ Adaptor::ResqueAdaptor.new(
55
+
56
+ ROOT, { :queue => '' }, nil
57
+
58
+ )
59
+
60
+ }.to raise_error(
61
+
62
+ LanGrove::DaemonConfigException,
63
+
64
+ "Adaptor::ResqueAdaptor requires :queue:"
65
+
66
+ )
67
+
68
+ end
69
+
70
+ context 'uses requeue to' do
71
+
72
+ before :each do
73
+
74
+ @parameters = {
75
+
76
+ :handler => {
77
+
78
+ :class => 'FakeJob'
79
+
80
+ }
81
+
82
+ }
83
+
84
+ #
85
+ # Mock the resque infrastructure
86
+ #
87
+
88
+ @worker = mock( 'Resque::Worker' )
89
+
90
+ @job = mock( 'Job' )
91
+
92
+ @payload = {}
93
+
94
+ Resque::Worker.should_receive(
95
+
96
+ :new
97
+
98
+ ).and_return(
99
+
100
+ @worker
101
+
102
+ )
103
+
104
+ @worker.should_receive(
105
+
106
+ :work
107
+
108
+ ).and_yield(
109
+
110
+ @job
111
+
112
+ )
113
+
114
+ @job.should_receive(
115
+
116
+ :payload_class
117
+
118
+ ).and_return(
119
+
120
+ FakeJob
121
+
122
+ )
123
+
124
+ @job.should_receive(
125
+
126
+ :payload
127
+
128
+ ).and_return(
129
+
130
+ @payload
131
+
132
+ )
133
+
134
+ end
135
+
136
+ it 'yields jobs' do
137
+
138
+ job = nil
139
+
140
+ subject.connector( @parameters ) do |new_job|
141
+
142
+ job = new_job
143
+
144
+ end
145
+
146
+ job.should be_a( FakeJob )
147
+
148
+ end
149
+
150
+ end
151
+
152
+ end
@@ -0,0 +1,32 @@
1
+ require 'langrove-plugin-resque'
2
+
3
+ describe Handler::ResqueJob do
4
+
5
+ before :each do
6
+
7
+ @queue_name = :queue_name
8
+
9
+ @job_parameter = {
10
+
11
+ :the => 'originally',
12
+ :enqueued => 'payload'
13
+
14
+ }
15
+
16
+ end
17
+
18
+ subject {
19
+
20
+ worker = Handler::ResqueJob.new
21
+
22
+ worker.instance_variable_set(
23
+
24
+ :@root, ROOT
25
+
26
+ )
27
+
28
+ worker
29
+
30
+ }
31
+
32
+ end
@@ -0,0 +1,118 @@
1
+ require 'langrove-plugin-resque'
2
+
3
+ describe 'Plugin::ResqueQue' do
4
+
5
+ before :each do
6
+
7
+ ROOT = LanGrove::FakeRoot.new
8
+
9
+ RESQUE_DEFERRER = {
10
+
11
+ :class => 'ResqueQue',
12
+ :job => 'ResqueWorker',
13
+ :queue => :resque_queue
14
+
15
+ }
16
+
17
+ @capsule = { :stamp => 'STAMP', :data => '' }
18
+
19
+ end
20
+
21
+ subject {
22
+
23
+ LanGrove::ClassLoader.create( {
24
+
25
+ :module => 'Plugin',
26
+ :class => 'ResqueQue'
27
+
28
+ } ).new( ROOT, RESQUE_DEFERRER, nil )
29
+
30
+ }
31
+
32
+ it 'can enqueue the capsule key' do
33
+
34
+ subject.validate_config
35
+
36
+ handler = mock( 'handler' )
37
+
38
+ handler.should_receive(
39
+
40
+ :key
41
+
42
+ ).and_return(
43
+
44
+ 'THE_KEY'
45
+
46
+ )
47
+
48
+ handler.should_receive(
49
+
50
+ :capsule
51
+
52
+ ).and_return(
53
+
54
+ @capsule
55
+
56
+ )
57
+
58
+ Resque.should_receive(
59
+
60
+ :enqueue
61
+
62
+ ).with(
63
+
64
+ Object.const_get(
65
+
66
+ RESQUE_DEFERRER[:job]
67
+
68
+ ),
69
+
70
+ anything(),
71
+
72
+ "THE_KEY"
73
+
74
+ )
75
+
76
+ subject.defer_key( handler )
77
+
78
+ end
79
+
80
+ it 'can enqueue the capsule data' do
81
+
82
+ subject.validate_config
83
+
84
+ handler = mock( 'handler' )
85
+
86
+ handler.should_receive(
87
+
88
+ :capsule
89
+
90
+ ).twice.and_return(
91
+
92
+ @capsule
93
+
94
+ )
95
+
96
+ Resque.should_receive(
97
+
98
+ :enqueue
99
+
100
+ ).with(
101
+
102
+ Object.const_get(
103
+
104
+ RESQUE_DEFERRER[:job]
105
+
106
+ ),
107
+
108
+ anything(),
109
+
110
+ @capsule
111
+
112
+ )
113
+
114
+ subject.defer_capsule( handler )
115
+
116
+ end
117
+
118
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: langrove-plugin-resque
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.9
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Richard
9
+ - ''
10
+ - ''
11
+ - ''
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+ date: 2012-07-09 00:00:00.000000000 Z
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
18
+ name: langrove
19
+ requirement: !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ! '>='
23
+ - !ruby/object:Gem::Version
24
+ version: '0'
25
+ type: :runtime
26
+ prerelease: false
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: resque
35
+ requirement: !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ type: :runtime
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ description: ''
50
+ email: ops@clue.co.za
51
+ executables: []
52
+ extensions: []
53
+ extra_rdoc_files: []
54
+ files:
55
+ - lib/adaptor/resque_adaptor.rb
56
+ - lib/handler/resque_job.rb
57
+ - lib/plugin/resque_que.rb
58
+ - spec/adaptor/resque_adaptor_spec.rb
59
+ - spec/handler/resque_job_spec.rb
60
+ - spec/plugin/resque_que_spec.rb
61
+ - lib/langrove-plugin-resque.rb
62
+ - README.md
63
+ homepage: ''
64
+ licenses: []
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project:
83
+ rubygems_version: 1.8.24
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: Intergates Resque support into LanGrove
87
+ test_files: []