beanstalker 0.0.1 → 0.1.1

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 CHANGED
@@ -1,27 +1,6 @@
1
- This is Async Observer -- a Rails plugin that provides deep integration with
2
- Beanstalk.
1
+ This is Beanstalker -- a Rails gem that provides deep integration with
2
+ Beanstalk. (forked from async_observer)
3
3
 
4
- For more information, see http://async-observer.rubyforge.org/.
4
+ This version is rewritten using daemonizer.
5
5
 
6
- For more information on Beanstalk, see its home page at
7
- http://xph.us/software/beanstalkd/.
8
-
9
-
10
- Worker Options:
11
- -d : daemonize
12
- --pid [path to pidfile] : drop a pid file to a path
13
- -e [test,production,development] : set the rails environment
14
-
15
- Example Usage:
16
-
17
- start 3 workers
18
- ./vendor/plugins/async_observer/bin/worker -d --pid log/worker1.pid -e production
19
- ./vendor/plugins/async_observer/bin/worker -d --pid log/worker2.pid -e production
20
- ./vendor/plugins/async_observer/bin/worker -d --pid log/worker3.pid -e production
21
-
22
- kill one
23
- kill -s INT `cat log/worker1.pid`
24
-
25
- Remember kill a worker will cause it to go into a shutdown phase.
26
- Run the above again to kill immediately, but remember all jobs in
27
- the workers queue is lost at that point...
6
+ Documentation coming soon...
data/Rakefile CHANGED
@@ -6,12 +6,14 @@ begin
6
6
  Jeweler::Tasks.new do |gem|
7
7
  gem.name = "beanstalker"
8
8
  gem.summary = %Q{Beanstalker provides deep integration with Beanstalk. Fork from http://github.com/kristjan/async_observer}
9
- gem.description = %Q{Beanstalker provides deep integration with Beanstalk. Fork from http://github.com/kristjan/async_observer}
9
+ gem.description = %Q{Beanstalker is a tool for executing long tasks in background in our rails application.}
10
10
  gem.email = "glebpom@gmail.com"
11
11
  gem.homepage = "http://github.com/glebpom/beanstalker"
12
12
  gem.authors = ["Gleb Pomykalov"]
13
13
  # gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
- gem.add_dependency "daemonizer"
14
+ gem.add_dependency "daemonizer", "~>0.2.0"
15
+ gem.add_dependency "beanstalk-client"
16
+ gem.add_dependency "rails", ">= 2.2.0"
15
17
  end
16
18
  Jeweler::GemcutterTasks.new
17
19
  rescue LoadError
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.1.1
@@ -0,0 +1,56 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{glebpom-async_observer}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Gleb Pomykalov"]
12
+ s.date = %q{2010-07-14}
13
+ s.description = %q{async_observer provides deep integration with Beanstalk. Fork from http://github.com/kristjan/async_observer}
14
+ s.email = %q{glebpom@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "COPYING",
21
+ "README",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "glebpom-async_observer.gemspec",
25
+ "init.rb",
26
+ "lib/async_observer/daemonizer_handler.rb",
27
+ "lib/async_observer/extend.rb",
28
+ "lib/async_observer/queue.rb",
29
+ "lib/async_observer/worker.rb"
30
+ ]
31
+ s.homepage = %q{http://github.com/glebpom/async_observer}
32
+ s.rdoc_options = ["--charset=UTF-8"]
33
+ s.require_paths = ["lib"]
34
+ s.rubygems_version = %q{1.3.7}
35
+ s.summary = %q{async_observer provides deep integration with Beanstalk. Fork from http://github.com/kristjan/async_observer}
36
+
37
+ if s.respond_to? :specification_version then
38
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
39
+ s.specification_version = 3
40
+
41
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
42
+ s.add_runtime_dependency(%q<daemonizer>, ["~> 0.2.0"])
43
+ s.add_runtime_dependency(%q<beanstalk-client>, [">= 0"])
44
+ s.add_runtime_dependency(%q<rails>, [">= 2.2.0"])
45
+ else
46
+ s.add_dependency(%q<daemonizer>, ["~> 0.2.0"])
47
+ s.add_dependency(%q<beanstalk-client>, [">= 0"])
48
+ s.add_dependency(%q<rails>, [">= 2.2.0"])
49
+ end
50
+ else
51
+ s.add_dependency(%q<daemonizer>, ["~> 0.2.0"])
52
+ s.add_dependency(%q<beanstalk-client>, [">= 0"])
53
+ s.add_dependency(%q<rails>, [">= 2.2.0"])
54
+ end
55
+ end
56
+
@@ -0,0 +1,21 @@
1
+ module AsyncObserver
2
+ class DaemonizerHandler < Daemonizer::Handler
3
+ def prepare(block)
4
+ logger.info "Loading Rails"
5
+ require File.join(Daemonizer.root, '/config/environment')
6
+ require 'async_observer/worker'
7
+ logger.info "Rails loaded"
8
+ super
9
+ end
10
+
11
+ def start
12
+ logger.info "Starting cycle"
13
+ Worker.new(binding,
14
+ :tube => option(:tube),
15
+ :servers => option(:servers),
16
+ :worker_id => worker_id,
17
+ :workers_count => workers_count).run
18
+ logger.info "Ending cycle"
19
+ end
20
+ end
21
+ end
@@ -29,12 +29,39 @@ CLASSES_TO_EXTEND = [
29
29
  ]
30
30
 
31
31
  module AsyncObserver::Extensions
32
+ def self.included(receiver)
33
+ @@methods_async_options = {}
34
+ receiver.extend(ClassMethods)
35
+ end
36
+
37
+ module ClassMethods
38
+ def async_method(method, options = {})
39
+ methods_async_options = class_variable_get(:@@methods_async_options)
40
+ if options
41
+ class_variable_set(:@@methods_async_options, methods_async_options.merge(method.to_sym => options))
42
+ end
43
+ end
44
+ end
45
+
46
+ def interpolate_async_options(options, object)
47
+ result = {}
48
+ options.each do |k,v|
49
+ result[k] = if v.is_a?(Proc)
50
+ v.call(object)
51
+ else
52
+ v
53
+ end
54
+ end
55
+ result
56
+ end
57
+
32
58
  def async_send(selector, *args)
33
- async_send_opts(selector, {}, *args)
59
+ async_send_opts(selector, @@methods_async_options[selector.to_sym] || {}, *args)
34
60
  end
35
61
 
36
62
  def async_send_opts(selector, opts, *args)
37
- AsyncObserver::Queue.put_call!(self, selector, opts, args)
63
+ interpolated_options = interpolate_async_options(opts, self)
64
+ AsyncObserver::Queue.put_call!(self, selector, interpolated_options, args)
38
65
  end
39
66
  end
40
67
 
@@ -73,7 +100,7 @@ class Range
73
100
  fanout_opts = opts.merge(:fuzz => opts.fetch(:fanout_fuzz,
74
101
  DEFAULT_FANOUT_FUZZ))
75
102
  fanout_opts[:pri] = opts[:fanout_pri] || opts[:pri]
76
- fanout_opts = fanout_opts.reject_hash{|k,v| nil.equal?(v)}
103
+ fanout_opts = fanout_opts.reject{ |k,v| v.nil? }
77
104
  split_to(fanout_degree) do |subrange|
78
105
  subrange.async_send_opts(:async_each_opts, fanout_opts, rcv, selector,
79
106
  opts, *extra)
@@ -29,7 +29,7 @@ class << AsyncObserver::Queue
29
29
  DEFAULT_TTR = 120
30
30
  DEFAULT_TUBE = 'default'
31
31
 
32
- attr_accessor :queue, :app_version, :after_put
32
+ attr_accessor :queue, :after_put
33
33
 
34
34
  # This is a fake worker instance for running jobs synchronously.
35
35
  def sync_worker()
@@ -48,7 +48,7 @@ class << AsyncObserver::Queue
48
48
 
49
49
  def put!(obj, pri=DEFAULT_PRI, delay=DEFAULT_DELAY, ttr=DEFAULT_TTR,
50
50
  tube=DEFAULT_TUBE)
51
- return sync_run(obj) if (:direct.equal?(pri) or !queue)
51
+ return sync_run(obj) if pri == :direct || !queue
52
52
  queue.connect()
53
53
  queue.use(tube)
54
54
  info = [queue.yput(obj, pri, delay, ttr), queue.last_server]
@@ -64,14 +64,21 @@ class << AsyncObserver::Queue
64
64
  fuzz = opts.fetch(:fuzz, DEFAULT_FUZZ)
65
65
  delay = opts.fetch(:delay, DEFAULT_DELAY)
66
66
  ttr = opts.fetch(:ttr, DEFAULT_TTR)
67
- tube = opts.fetch(:tube, (app_version or DEFAULT_TUBE))
67
+ tube = opts.fetch(:tube, DEFAULT_TUBE)
68
68
  worker_opts = opts.reject{|k,v| SUBMIT_OPTS.include?(k)}
69
-
70
- pri = pri + rand(fuzz + 1) if !:direct.equal?(pri)
71
-
72
- code = gen(obj, sel, args)
73
- RAILS_DEFAULT_LOGGER.info("put #{pri} #{code}")
74
- put!(pkg(code, worker_opts), pri, delay, ttr, tube)
69
+ interpolator = opts.fetch(:interpolator, nil)
70
+
71
+ pri = pri + rand(fuzz + 1) if pri != :direct
72
+
73
+ if interpolator
74
+ code = packed = interpolator
75
+ else
76
+ code = gen(obj, sel, args)
77
+ packed = pkg(code, worker_opts)
78
+ end
79
+
80
+ RAILS_DEFAULT_LOGGER.info("put #{pri} #{code} to #{tube}")
81
+ put!(packed, pri, delay, ttr, tube)
75
82
  end
76
83
 
77
84
  def pkg(code, opts)
@@ -15,20 +15,11 @@
15
15
  # You should have received a copy of the GNU General Public License
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
 
18
-
19
- begin
20
- require 'mysql'
21
- rescue LoadError
22
- # Ignore case where we don't have mysql
23
- end
24
18
  require 'async_observer/queue'
25
- require 'async_observer/util'
26
19
 
27
20
  module AsyncObserver; end
28
21
 
29
22
  class AsyncObserver::Worker
30
- extend AsyncObserver::Util
31
- include AsyncObserver::Util
32
23
 
33
24
  SLEEP_TIME = 60 if !defined?(SLEEP_TIME) # rails loads this file twice
34
25
 
@@ -55,58 +46,50 @@ class AsyncObserver::Worker
55
46
  end
56
47
 
57
48
  def run_before_reserve
58
- before_reserves.each {|b| b.call()}
49
+ before_reserves.each {|b| b.call}
59
50
  end
60
51
  end
52
+
53
+ def logger
54
+ $logger or RAILS_DEFAULT_LOGGER
55
+ end
61
56
 
62
- def initialize(top_binding)
57
+ def initialize(top_binding, options = {})
63
58
  @top_binding = top_binding
64
59
  @stop = false
60
+ @options = options
61
+ if @options && @options[:servers]
62
+ AsyncObserver::Queue.queue = Beanstalk::Pool.new(@options[:servers])
63
+ end
65
64
  end
66
65
 
67
- def main_loop()
66
+ def main_loop
68
67
  trap('TERM') { @stop = true }
69
68
  loop do
70
69
  break if @stop
71
- safe_dispatch(get_job())
70
+ safe_dispatch(get_job)
72
71
  end
73
72
  end
74
73
 
75
- def startup()
76
- log_bracketed('worker-startup') do
77
- appver = AsyncObserver::Queue.app_version
78
- RAILS_DEFAULT_LOGGER.info "pid is #{$$}"
79
- RAILS_DEFAULT_LOGGER.info "app version is #{appver}"
80
- mark_db_socket_close_on_exec()
81
- if AsyncObserver::Queue.queue.nil?
82
- RAILS_DEFAULT_LOGGER.info 'no queue has been configured'
83
- exit(1)
84
- end
85
- AsyncObserver::Queue.queue.watch(appver) if appver
86
- end
74
+ def startup
75
+ tube = @options[:tube] || "default"
76
+ logger.info "Using tube #{tube}"
77
+ AsyncObserver::Queue.queue.watch(tube)
87
78
  flush_logger
88
79
  end
89
80
 
90
- # This prevents us from leaking fds when we exec. Only works for mysql.
91
- def mark_db_socket_close_on_exec()
92
- ActiveRecord::Base.active_connections.each(&:set_close_on_exec)
93
- rescue NoMethodError
94
- end
95
-
96
- def shutdown()
97
- log_bracketed('worker-shutdown') do
98
- do_all_work()
99
- end
81
+ def shutdown
82
+ do_all_work
100
83
  end
101
84
 
102
- def run()
103
- startup()
104
- main_loop()
85
+ def run
86
+ startup
87
+ main_loop
105
88
  rescue Interrupt
106
- shutdown()
89
+ shutdown
107
90
  end
108
91
 
109
- def q_hint()
92
+ def q_hint
110
93
  @q_hint || AsyncObserver::Queue.queue
111
94
  end
112
95
 
@@ -114,9 +97,9 @@ class AsyncObserver::Worker
114
97
  # if the connection returns a job right away, it probably has more available.
115
98
  # But if it takes time, then it's probably empty. So reuse the same
116
99
  # connection as long as it stays fast. Otherwise, have no preference.
117
- def reserve_and_set_hint()
100
+ def reserve_and_set_hint
118
101
  t1 = Time.now.utc
119
- return job = q_hint().reserve()
102
+ return job = q_hint.reserve
120
103
  ensure
121
104
  t2 = Time.now.utc
122
105
  @q_hint = if brief?(t1, t2) and job then job.conn else nil end
@@ -126,29 +109,27 @@ class AsyncObserver::Worker
126
109
  ((t2 - t1) * 100).to_i.abs < 10
127
110
  end
128
111
 
129
- def get_job()
130
- log_bracketed('worker-get-job') do
131
- loop do
132
- begin
133
- AsyncObserver::Queue.queue.connect()
134
- self.class.run_before_reserve
135
- return reserve_and_set_hint()
136
- rescue Interrupt => ex
137
- raise ex
138
- rescue SignalException => ex
139
- raise ex
140
- rescue Beanstalk::DeadlineSoonError
141
- # Do nothing; immediately try again, giving the user a chance to
142
- # clean up in the before_reserve hook.
143
- RAILS_DEFAULT_LOGGER.info 'Job deadline soon; you should clean up.'
144
- rescue Exception => ex
145
- @q_hint = nil # in case there's something wrong with this conn
146
- RAILS_DEFAULT_LOGGER.info(
147
- "#{ex.class}: #{ex}\n" + ex.backtrace.join("\n"))
148
- RAILS_DEFAULT_LOGGER.info 'something is wrong. We failed to get a job.'
149
- RAILS_DEFAULT_LOGGER.info "sleeping for #{SLEEP_TIME}s..."
150
- sleep(SLEEP_TIME)
151
- end
112
+ def get_job
113
+ loop do
114
+ begin
115
+ AsyncObserver::Queue.queue.connect
116
+ self.class.run_before_reserve
117
+ return reserve_and_set_hint
118
+ rescue Interrupt => ex
119
+ raise ex
120
+ rescue SignalException => ex
121
+ raise ex
122
+ rescue Beanstalk::DeadlineSoonError
123
+ # Do nothing; immediately try again, giving the user a chance to
124
+ # clean up in the before_reserve hook.
125
+ logger.info 'Job deadline soon; you should clean up.'
126
+ rescue Exception => ex
127
+ @q_hint = nil # in case there's something wrong with this conn
128
+ logger.info(
129
+ "#{ex.class}: #{ex}\n" + ex.backtrace.join("\n"))
130
+ logger.info 'something is wrong. We failed to get a job.'
131
+ logger.info "sleeping for #{SLEEP_TIME}s..."
132
+ sleep(SLEEP_TIME)
152
133
  end
153
134
  end
154
135
  end
@@ -160,30 +141,26 @@ class AsyncObserver::Worker
160
141
  end
161
142
 
162
143
  def safe_dispatch(job)
163
- log_bracketed('worker-dispatch') do
164
- RAILS_DEFAULT_LOGGER.info "got #{job.inspect}:\n" + job.body
165
- log_bracketed('job-stats') do
166
- job.stats.each do |k,v|
167
- RAILS_DEFAULT_LOGGER.info "#{k}=#{v}"
168
- end
169
- end
170
- begin
171
- return dispatch(job)
172
- rescue Interrupt => ex
173
- begin job.release() rescue :ok end
174
- raise ex
175
- rescue Exception => ex
176
- handle_error(job, ex)
177
- ensure
178
- flush_logger
179
- end
144
+ logger.info "got #{job.inspect}:\n" + job.body
145
+ job.stats.each do |k,v|
146
+ logger.info "#{k}=#{v}"
147
+ end
148
+ begin
149
+ return dispatch(job)
150
+ rescue Interrupt => ex
151
+ begin job.release rescue :ok end
152
+ raise ex
153
+ rescue Exception => ex
154
+ handle_error(job, ex)
155
+ ensure
156
+ flush_logger
180
157
  end
181
158
  end
182
159
 
183
160
  def flush_logger
184
- if defined?(RAILS_DEFAULT_LOGGER) &&
185
- RAILS_DEFAULT_LOGGER.respond_to?(:flush)
186
- RAILS_DEFAULT_LOGGER.flush
161
+ if defined?(logger) &&
162
+ logger.respond_to?(:flush)
163
+ logger.flush
187
164
  end
188
165
  end
189
166
 
@@ -196,25 +173,30 @@ class AsyncObserver::Worker
196
173
  end
197
174
 
198
175
  def self.default_handle_error(job, ex)
199
- RAILS_DEFAULT_LOGGER.info "Job failed: #{job.server}/#{job.id}"
200
- RAILS_DEFAULT_LOGGER.info("#{ex.class}: #{ex}\n" + ex.backtrace.join("\n"))
201
- job.decay()
176
+ logger.info "Job failed: #{job.server}/#{job.id}"
177
+ logger.info("#{ex.class}: #{ex}\n" + ex.backtrace.join("\n"))
178
+ if job.stats['releases'] > 10
179
+ job.bury
180
+ logger.info "BURY job due to many releases"
181
+ else
182
+ job.decay
183
+ end
202
184
  rescue Beanstalk::UnexpectedResponse
203
185
  end
204
186
 
205
187
  def run_ao_job(job)
206
- RAILS_DEFAULT_LOGGER.info 'running as async observer job'
188
+ logger.info 'running as async observer job'
207
189
  f = self.class.before_filter
208
190
  f.call(job) if f
209
191
  job.delete if job.ybody[:delete_first]
210
192
  run_code(job)
211
- job.delete() unless job.ybody[:delete_first]
193
+ job.delete unless job.ybody[:delete_first]
212
194
  rescue ActiveRecord::RecordNotFound => ex
213
195
  unless job.ybody[:delete_first]
214
196
  if job.age > 60
215
- job.delete() # it's old; this error is most likely permanent
197
+ job.delete # it's old; this error is most likely permanent
216
198
  else
217
- job.decay() # it could be replication delay so retry quietly
199
+ job.decay # it could be replication delay so retry quietly
218
200
  end
219
201
  end
220
202
  end
@@ -228,36 +210,14 @@ class AsyncObserver::Worker
228
210
  end
229
211
 
230
212
  def run_other(job)
231
- RAILS_DEFAULT_LOGGER.info 'trying custom handler'
213
+ logger.info 'trying custom handler'
232
214
  self.class.handle.call(job)
233
215
  end
234
216
 
235
- def do_all_work()
236
- RAILS_DEFAULT_LOGGER.info 'finishing all running jobs. interrupt again to kill them.'
217
+ def do_all_work
218
+ logger.info 'finishing all running jobs. interrupt again to kill them.'
237
219
  f = self.class.finish
238
- f.call() if f
220
+ f.call if f
239
221
  end
240
222
  end
241
223
 
242
- class ActiveRecord::ConnectionAdapters::MysqlAdapter < ActiveRecord::ConnectionAdapters::AbstractAdapter
243
- def set_close_on_exec()
244
- @connection.set_close_on_exec()
245
- end
246
- end
247
-
248
- class Mysql
249
- def set_close_on_exec()
250
- if @net
251
- @net.set_close_on_exec()
252
- else
253
- # we are in the c mysql binding
254
- RAILS_DEFAULT_LOGGER.info "Warning: we are using the C mysql binding, can't set close-on-exec"
255
- end
256
- end
257
- end
258
-
259
- class Mysql::Net
260
- def set_close_on_exec()
261
- @sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
262
- end
263
- end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beanstalker
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 0
9
8
  - 1
10
- version: 0.0.1
9
+ - 1
10
+ version: 0.1.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Gleb Pomykalov
@@ -15,13 +15,29 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-07-06 00:00:00 +04:00
19
- default_executable: worker
18
+ date: 2010-07-14 00:00:00 +04:00
19
+ default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: daemonizer
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 23
30
+ segments:
31
+ - 0
32
+ - 2
33
+ - 0
34
+ version: 0.2.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: beanstalk-client
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
25
41
  none: false
26
42
  requirements:
27
43
  - - ">="
@@ -31,11 +47,27 @@ dependencies:
31
47
  - 0
32
48
  version: "0"
33
49
  type: :runtime
34
- version_requirements: *id001
35
- description: Beanstalker provides deep integration with Beanstalk. Fork from http://github.com/kristjan/async_observer
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: rails
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 7
60
+ segments:
61
+ - 2
62
+ - 2
63
+ - 0
64
+ version: 2.2.0
65
+ type: :runtime
66
+ version_requirements: *id003
67
+ description: Beanstalker is a tool for executing long tasks in background in our rails application.
36
68
  email: glebpom@gmail.com
37
- executables:
38
- - worker
69
+ executables: []
70
+
39
71
  extensions: []
40
72
 
41
73
  extra_rdoc_files:
@@ -46,12 +78,11 @@ files:
46
78
  - README
47
79
  - Rakefile
48
80
  - VERSION
49
- - bin/worker
81
+ - glebpom-async_observer.gemspec
50
82
  - init.rb
51
- - lib/async_observer/daemonize.rb
83
+ - lib/async_observer/daemonizer_handler.rb
52
84
  - lib/async_observer/extend.rb
53
85
  - lib/async_observer/queue.rb
54
- - lib/async_observer/util.rb
55
86
  - lib/async_observer/worker.rb
56
87
  has_rdoc: true
57
88
  homepage: http://github.com/glebpom/beanstalker
data/bin/worker DELETED
@@ -1,70 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # async-observer - Rails plugin for asynchronous job execution
3
-
4
- # Copyright (C) 2007 Philotic Inc.
5
-
6
- # This program is free software: you can redistribute it and/or modify
7
- # it under the terms of the GNU General Public License as published by
8
- # the Free Software Foundation, either version 3 of the License, or
9
- # (at your option) any later version.
10
-
11
- # This program is distributed in the hope that it will be useful,
12
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- # GNU General Public License for more details.
15
-
16
- # You should have received a copy of the GNU General Public License
17
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
-
19
-
20
- # Use the same pointer (and therefore same buffer) for stdout and stderr.
21
- $VERBOSE = nil; STDERR = $stderr = STDOUT = $stdout; $VERBOSE = false
22
-
23
- require 'time'
24
-
25
- def load_rails_and_run
26
- # Rails initialization.
27
- # We do this here instead of using script/runner because script/runner
28
- # breaks __FILE__, which we use below.
29
- begin
30
- puts "#!load-rails!begin!#{Time.now.utc.xmlschema(6)}"
31
- require File.expand_path(File.dirname(__FILE__) + '/../../../../config/boot')
32
- puts "RAILS_ROOT=#{RAILS_ROOT.inspect}"
33
- require RAILS_ROOT + '/config/environment'
34
- ensure
35
- puts "#!load-rails!end!#{Time.now.utc.xmlschema(6)}"
36
- end
37
- require 'async_observer/worker'
38
- AsyncObserver::Worker.new(binding).run()
39
- end
40
-
41
- # set environment
42
- if ARGV.include?('-e') # check rails env
43
- env=nil
44
- ARGV.each_with_index{|arg,i| env = ARGV[i+1] if arg == '-e' }
45
- RAILS_ENV=env unless env.nil?
46
- end
47
-
48
- if ARGV.include?('-d')
49
- pidpath = 'log/worker.pid'
50
- if ARGV.include?('--pid') # look up the pid path
51
- ARGV.each_with_index{|arg,i| pidpath = ARGV[i+1] if arg == '--pid' }
52
- STDERR.puts "Missing pid file path!" and exit(1) if pidpath.nil?
53
- end
54
- unless File.writable?(File.dirname(pidpath))
55
- STDERR.puts "#{pidpath} not writable!"
56
- exit(1)
57
- end
58
-
59
- if File.exist?(pidpath)
60
- STDERR.puts "#{pidpath} exits! Make sure the worker isn't still running and try again after rm #{pidpath}"
61
- exit(1)
62
- end
63
-
64
- require File.dirname(__FILE__) + '/../lib/async_observer/daemonize'
65
- AsyncObserver::Daemonize.detach(pidpath) do
66
- load_rails_and_run
67
- end
68
- else
69
- load_rails_and_run
70
- end
@@ -1,35 +0,0 @@
1
- # async-observer - Rails plugin for asynchronous job execution
2
- # Copyright (C) 2009 Todd A. Fisher.
3
-
4
- # This program is free software: you can redistribute it and/or modify
5
- # it under the terms of the GNU General Public License as published by
6
- # the Free Software Foundation, either version 3 of the License, or
7
- # (at your option) any later version.
8
-
9
- # This program is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU General Public License for more details.
13
-
14
- # You should have received a copy of the GNU General Public License
15
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
- module AsyncObserver; end
17
-
18
- class AsyncObserver::Daemonize
19
- def self.detach(pidfile='log/worker.pid',&block)
20
- # daemonize, create a pipe to send status to the parent process, after the child has successfully started or failed
21
- fork do
22
- Process.setsid
23
- fork do
24
- Process.setsid
25
- File.open(pidfile, 'wb') {|f| f << Process.pid}
26
- at_exit { File.unlink(pidfile) }
27
- File.umask 0000
28
- STDIN.reopen "/dev/null"
29
- STDOUT.reopen "/dev/null", "a"
30
- STDERR.reopen STDOUT
31
- block.call
32
- end
33
- end
34
- end
35
- end
@@ -1,31 +0,0 @@
1
- # async-observer - Rails plugin for asynchronous job execution
2
-
3
- # Copyright (C) 2007 Philotic Inc.
4
-
5
- # This program is free software: you can redistribute it and/or modify
6
- # it under the terms of the GNU General Public License as published by
7
- # the Free Software Foundation, either version 3 of the License, or
8
- # (at your option) any later version.
9
-
10
- # This program is distributed in the hope that it will be useful,
11
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- # GNU General Public License for more details.
14
-
15
- # You should have received a copy of the GNU General Public License
16
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
-
18
-
19
- require 'open3'
20
-
21
- module AsyncObserver; end
22
- module AsyncObserver::Util
23
- def log_bracketed(name)
24
- begin
25
- RAILS_DEFAULT_LOGGER.info "#!#{name}!begin!#{Time.now.utc.xmlschema(6)}"
26
- yield()
27
- ensure
28
- RAILS_DEFAULT_LOGGER.info "#!#{name}!end!#{Time.now.utc.xmlschema(6)}"
29
- end
30
- end
31
- end