steve 2.0.3 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 39ac8bc8cd9c5647e61a09673bcc96fed956fb57
4
- data.tar.gz: 552ae88ed5ed4968234701ddc338f4d08bdc9be2
3
+ metadata.gz: ff4ed0070df9be5041ccf923f6241cd8c484fbd1
4
+ data.tar.gz: fe44158d942b5ef3bd69f7acafd276bd36d07f42
5
5
  SHA512:
6
- metadata.gz: 7e7f58a6af65971bd4d64a061617d32925931cf8db09d3ee432ce77711d6cecc17f01dbc8a8061b08ff2ca43b87af31d4e3150629a11772cc4079294777d6c7c
7
- data.tar.gz: 2725c97343de78b411c98b4703c1aad5d64dcece8da36c74543e74722b20e70390c19a89e32fcdcc6842157519fba354947c62ec20283838a13e7bab4a300a6f
6
+ metadata.gz: 4db62a04d2c0c42669cbabeb60716adf504b3943dbc3a8fe36dc6e6e587b06b299c08f5487fb244705e594b9f4f7f06fdcdbd6980c1c901faada4fe331eb8a5b
7
+ data.tar.gz: 25d9f7681af9ec48b87035baa2a3df3ede024ca806d1f2193197bea1bf22027885cb15c4b5ae6538fef5a9de9583eb96ecccfc5fad5c193c2ba117789149e870
@@ -20,4 +20,4 @@ module ActiveJob
20
20
 
21
21
  end
22
22
  end
23
- end
23
+ end
@@ -1,58 +1,58 @@
1
1
  module Steve
2
-
2
+
3
3
  class << self
4
-
4
+
5
5
  ## The default queue for new jobs
6
6
  attr_accessor :default_job_queue
7
-
7
+
8
8
  ## The default priority for new jobs
9
- attr_accessor :default_job_priority
10
-
9
+ attr_accessor :default_job_priority
10
+
11
11
  ## The name of the table where jobs are stored (default 'jobs')
12
12
  attr_accessor :jobs_table_name
13
13
 
14
14
  ## The name of the table where completed jobs are stored
15
15
  attr_accessor :archived_jobs_table_name
16
-
16
+
17
17
  ## The period of time to wait before looking for new jobs
18
18
  attr_accessor :worker_sleep_time
19
-
19
+
20
20
  ## The logger object for all output from steve
21
21
  attr_accessor :logger
22
-
22
+
23
23
  ## The maximum number of times to retry a job
24
24
  attr_accessor :max_job_retries
25
-
25
+
26
26
  ## Whether or not jobs should be queued or run in the background
27
27
  attr_accessor :run_jobs_in_foreground
28
-
28
+
29
29
  ## Proc to run after forking
30
30
  attr_accessor :after_job_fork
31
-
31
+
32
32
  ## Allow parent process name to be kept
33
33
  attr_accessor :keep_parent_process_name
34
34
 
35
35
  ## Delete jobs after successful completion
36
36
  attr_accessor :delete_successful_jobs
37
-
37
+
38
38
  ## Return the worker name for this current process/host
39
39
  def worker_name
40
40
  "host:#{Socket.gethostname} pid:#{Process.pid}" rescue "pid:#{Process.pid}"
41
41
  end
42
-
42
+
43
43
  ## Set/return the logger object
44
44
  def logger
45
45
  @logger ||= Logger.new(File.join(Rails.root, 'log', 'jobs.log'))
46
46
  end
47
-
47
+
48
48
  ## Log a new message
49
49
  def log(message)
50
50
  message.gsub!(/(\[\d+\])/) { "\e[33m#{$1}\e[0m" }
51
51
  logger.info "\e[37m#{Time.now.utc.to_s(:db)}\e[0m #{message}"
52
52
  end
53
-
53
+
54
54
  end
55
-
55
+
56
56
  end
57
57
 
58
58
  require 'steve/job'
@@ -1,21 +1,17 @@
1
- require 'haml'
2
- require 'will_paginate/view_helpers'
3
- require 'will_paginate/view_helpers/link_renderer'
1
+ # require 'haml'
4
2
 
5
3
  module Steve
6
4
  class Interface
7
- include WillPaginate::ViewHelpers
8
-
9
5
  def call(env)
10
6
  @req = Rack::Request.new(env)
11
7
  case env['PATH_INFO'].to_s
12
8
  when '/', ''
13
9
  [200, {'Content-type' => 'text/html'}, [haml(:index)]]
14
10
  when /failed/
15
- @jobs = Steve::ArchivedJob.failed.asc.paginate(:page => @req.params['page'], :per_page => 50)
11
+ @jobs = paginate(Steve::ArchivedJob.failed.asc, :page => @req.params['page'], :per_page => 50)
16
12
  [200, {'Content-type' => 'text/html'}, [haml(:failed)]]
17
13
  when /completed/
18
- @jobs = Steve::ArchivedJob.completed.asc.paginate(:page => @req.params['page'], :per_page => 50)
14
+ @jobs = paginate(Steve::ArchivedJob.completed.asc, :page => @req.params['page'], :per_page => 50)
19
15
  [200, {'Content-type' => 'text/html'}, [haml(:completed)]]
20
16
  when /archived\/object/
21
17
  @jobs = Steve::ArchivedJob.where(:associated_object_type => @req.params['type'], :associated_object_id => @req.params['id']).order('created_at desc').limit(25)
@@ -44,23 +40,30 @@ module Steve
44
40
  else
45
41
  [404, {'Content-type' => 'text/plain'}, ["Not found"]]
46
42
  end
47
-
43
+
48
44
  end
49
45
  end
50
-
46
+
51
47
  private
52
-
48
+
49
+ def paginate(collection, options = {})
50
+ options[:per_page] ||= 50
51
+ options[:page] ||= 1
52
+
53
+ collection.limit(options[:per_page]).offset((options[:page].to_i - 1) * options[:per_page])
54
+ end
55
+
53
56
  def haml(view_name)
54
57
  Haml::Engine.new(File.read(view_path(view_name))).render(self)
55
58
  end
56
-
59
+
57
60
  def view_path(name)
58
61
  File.expand_path(File.join('..', 'interface', 'views', name.to_s + '.haml'), __FILE__)
59
62
  end
60
-
63
+
61
64
  def static_path(name)
62
65
  File.expand_path(File.join('..', 'interface', 'public', name.to_s), __FILE__).gsub(/\.\./, '')
63
66
  end
64
-
67
+
65
68
  end
66
69
  end
@@ -39,7 +39,5 @@
39
39
  %tr
40
40
  %td.none{:colspan => 7} There are no jobs recently completed
41
41
 
42
- .pagination-details
43
- = page_entries_info @jobs
44
42
  %p
45
43
  %a{:href => "/jobs"} Back to overview
@@ -12,7 +12,7 @@
12
12
  %p
13
13
  The jobs listed below have failed to execute recently. You can clear all the jobs using the button below, this will
14
14
  remove them from the database and you will not be able to retry once removed.
15
-
15
+
16
16
  %table.data
17
17
  %thead
18
18
  %tr
@@ -37,13 +37,10 @@
37
37
  %code{:style => 'font-size:90%', :title => job.error}= ERB::Util.html_escape(job.error.to_s.split("\n").first)\
38
38
  %td
39
39
  %form{:action => "/jobs/retry?id=#{job.id}", :method => :post}
40
- %input{:type => 'submit', :value => 'Retry'}
40
+ %input{:type => 'submit', :value => 'Retry'}
41
41
  - if @jobs.empty?
42
42
  %tr
43
43
  %td.none{:colspan => 6} There are no jobs currently running
44
-
45
- .pagination-details
46
- = page_entries_info @jobs
47
44
 
48
45
  %p
49
46
  %a{:href => "/jobs"} Back to overview
@@ -3,19 +3,19 @@
3
3
 
4
4
  module Steve
5
5
  class Job
6
-
6
+
7
7
  class Delay < StandardError; end
8
8
  class Error < StandardError; end
9
9
  class Aborted < StandardError; end
10
-
10
+
11
11
  attr_reader :job
12
12
  attr_reader :params
13
-
13
+
14
14
  def initialize(job, params = {})
15
15
  @job = job
16
16
  @params = job.params
17
17
  end
18
-
18
+
19
19
  ## Queue the job
20
20
  def self.queue(params = {}, &block)
21
21
  if Steve.run_jobs_in_foreground
@@ -27,22 +27,22 @@ module Steve
27
27
  QueuedJob.queue(self, params, &block)
28
28
  end
29
29
  end
30
-
30
+
31
31
  ## Live run a job after passing the params
32
32
  def self.run(params = {})
33
33
  self.new(FakeQueuedJob.new(params)).perform
34
34
  end
35
-
35
+
36
36
  class FakeQueuedJob
37
37
  attr_reader :params
38
38
  def initialize(params)
39
39
  @params = params
40
40
  end
41
-
41
+
42
42
  def method_missing(*_)
43
43
  true
44
44
  end
45
45
  end
46
-
46
+
47
47
  end
48
48
  end
@@ -2,20 +2,20 @@ require 'stringio'
2
2
 
3
3
  module Steve
4
4
  class QueuedJob < ActiveRecord::Base
5
-
5
+
6
6
  ## Set the table name - a migration should be created for this
7
7
  self.table_name = Steve.jobs_table_name || 'jobs'
8
-
8
+
9
9
  ## Serialize the options
10
10
  serialize :params
11
-
11
+
12
12
  ## Can belong to another active record object?
13
13
  belongs_to :associated_object, :polymorphic => true
14
-
14
+
15
15
  ## Scopes
16
16
  scope :pending, lambda { where(:status => ['pending', 'delayed']) }
17
17
  scope :running, lambda { where(:status => 'running') }
18
-
18
+
19
19
  ## Automatically set defaults for new jobs
20
20
  before_create do
21
21
  self.priority ||= (Steve.default_job_priority || 10)
@@ -23,7 +23,7 @@ module Steve
23
23
  self.status ||= 'pending'
24
24
  self.run_at ||= Time.now.utc
25
25
  end
26
-
26
+
27
27
  after_save do
28
28
  Steve::ArchivedJob.archive_job(self) if self.archive_job?
29
29
  true
@@ -40,8 +40,8 @@ module Steve
40
40
  block.call(job) if block_given?
41
41
  job.save
42
42
  end
43
-
44
- ## Execute a new job from the queue. Returns true if a job was executed, or false if a
43
+
44
+ ## Execute a new job from the queue. Returns true if a job was executed, or false if a
45
45
  ## job was not found or we couldn't obtain locks for them.
46
46
  def self.execute_jobs(queue = '*', limit = 5)
47
47
  jobs = self.where(:status => ['pending', 'delayed'], :worker => nil).where(["run_at <= ?", Time.now.utc]).order("priority asc").limit(5)
@@ -51,7 +51,7 @@ module Steve
51
51
  jobs_executed = Array.new
52
52
  for job in pending_jobs.sort_by { rand() }
53
53
  Steve.log "[#{job.id}] Attempt to aquire lock"
54
- if job.lock
54
+ if job.lock
55
55
  Steve.log "[#{job.id}] Lock acquired"
56
56
  if @child = fork
57
57
  rand
@@ -63,7 +63,7 @@ module Steve
63
63
  $0 = "sj: executing job ##{job.id} since #{Time.now.utc.to_s(:db)}"
64
64
  Steve.after_job_fork.call if Steve.after_job_fork.is_a?(Proc)
65
65
  job.execute
66
- exit
66
+ exit!
67
67
  end
68
68
  jobs_executed << job
69
69
  else
@@ -72,7 +72,7 @@ module Steve
72
72
  end
73
73
  jobs_executed
74
74
  end
75
-
75
+
76
76
  ## Execute this job, catching any errors if they occur and ensuring the
77
77
  ## job is started & finished as appropriate.
78
78
  def execute
@@ -92,17 +92,37 @@ module Steve
92
92
  else
93
93
  self.error = e.message
94
94
  delay!
95
- Steve.log "[#{self.id}] Delayed ('#{e.message}')"
95
+ Steve.log "[#{self.id}] Delayed ('#{e.message}')"
96
96
  end
97
97
  rescue Timeout::Error
98
+ reconnect_database!
98
99
  fail!('Timed out')
99
100
  Steve.log "[#{self.id}] Timed out: #{e.to_s}"
100
101
  rescue => e
101
102
  if e.is_a?(Steve::Job::Error)
102
103
  fail!(e.message)
103
104
  else
105
+ fail!([e.to_s, e.backtrace].join("\n"))
104
106
  if defined?(Airbrake)
105
- Airbrake.notify(e, :component => self.job.to_s, :action => self.id.to_s, :parameters => self.params)
107
+ begin
108
+ Timeout.timeout(5) do
109
+ Airbrake.notify(e, :component => self.job.to_s, :action => self.id.to_s, :parameters => self.params)
110
+ end
111
+ rescue Timeout::Error
112
+ reconnect_database!
113
+ Steve.log "[#{self.id}] Timed out sending exception to Airbrake"
114
+ end
115
+ end
116
+ if defined?(Raven)
117
+ Raven.capture_exception(e, :tags => {:component => 'worker'}, :extra => {:steve => {
118
+ :id => self.id,
119
+ :priority => self.priority,
120
+ :attempts => self.retries,
121
+ :run_at => self.run_at,
122
+ :queue => self.queue,
123
+ :created_at => self.created_at,
124
+ :params => self.params
125
+ }})
106
126
  end
107
127
  fail!([e.to_s, e.backtrace].join("\n"))
108
128
  end
@@ -114,12 +134,11 @@ module Steve
114
134
  return false
115
135
  end
116
136
  ensure
117
- STDOUT.flush && STDERR.flush
118
- if File.exist?(output_file)
119
- self.output = File.read(output_file)
120
- FileUtils.rm(output_file)
121
- end
122
137
  self.save(:validate => false)
138
+ STDOUT.flush
139
+ STDERR.flush
140
+
141
+ FileUtils.rm(output_file) if File.exist?(output_file)
123
142
  end
124
143
 
125
144
  ## Get the output of a job, even if the job is in progress,
@@ -129,10 +148,10 @@ module Steve
129
148
  if read_attribute(:output)
130
149
  read_attribute(:output)
131
150
  elsif File.exist?(output_file)
132
- File.read(output_file)
151
+ File.read(output_file)
133
152
  end
134
153
  end
135
-
154
+
136
155
  ## Get a lock on this job. Returns true if the lock was successful
137
156
  ## otherwise it returns false.
138
157
  def lock
@@ -144,25 +163,25 @@ module Steve
144
163
  return false
145
164
  end
146
165
  end
147
-
166
+
148
167
  ## Mark this job as succeeded successfully.
149
168
  def success!
150
169
  self.status = 'completed'
151
170
  finish!
152
171
  end
153
-
172
+
154
173
  ## Mark this job as failed.
155
174
  def fail!(message)
156
175
  self.error = message
157
176
  self.status = 'failed'
158
177
  finish!
159
178
  end
160
-
179
+
161
180
  ## Mark this job as finished
162
181
  def finish!
163
182
  self.finished_at = Time.now.utc
164
183
  end
165
-
184
+
166
185
  ## Mark this job as started
167
186
  def start!
168
187
  self.error = nil
@@ -172,7 +191,7 @@ module Steve
172
191
  self.job_pid = Process.pid
173
192
  self.save(:validate => false)
174
193
  end
175
-
194
+
176
195
  ## Delay this job by the time specified
177
196
  def delay!(delay_time = 30.seconds)
178
197
  self.status = 'delayed'
@@ -182,13 +201,13 @@ module Steve
182
201
  self.retries += 1
183
202
  self.save(:validate => false)
184
203
  end
185
-
204
+
186
205
  ## Associate this job with the pased active record object
187
206
  def associate_with(object)
188
207
  self.associated_object = object
189
208
  self.save(:validate => false)
190
209
  end
191
-
210
+
192
211
  ## In a state appropriate to be archived?
193
212
  def archive_job?
194
213
  ['failed', 'completed'].include?(self.status)
@@ -202,6 +221,10 @@ module Steve
202
221
  def self.cleanup(age = 5.days.ago)
203
222
  self.delete_all(["status = 'completed' and run_at < ?", age])
204
223
  end
205
-
224
+
225
+ def reconnect_database!
226
+ self.class.connection.reconnect!
227
+ end
228
+
206
229
  end
207
230
  end
@@ -1,20 +1,20 @@
1
1
  module Steve
2
2
  class Worker
3
-
3
+
4
4
  def initialize(queue)
5
5
  @queue = queue
6
6
  end
7
-
7
+
8
8
  def start
9
9
  Steve.log "*** Starting job worker #{Steve.worker_name} (queue: #{@queue})"
10
-
10
+
11
11
  trap("TERM") { Steve.log("*** Exiting..."); $exit = true }
12
12
  trap("INT") { Steve.log("*** Exiting..."); $exit = true }
13
-
13
+
14
14
  loop do
15
15
  jobs = Steve::QueuedJob.execute_jobs(@queue)
16
16
  count = jobs.size
17
-
17
+
18
18
  unless count == 0
19
19
  Steve.log "*** #{count} jobs processed"
20
20
  else
@@ -22,10 +22,10 @@ module Steve
22
22
  $0 = "sj: waiting for jobs on #{@queue}"
23
23
  sleep(Steve.worker_sleep_time || 5)
24
24
  end
25
-
25
+
26
26
  break if $exit
27
27
  end
28
-
28
+
29
29
  end
30
30
  end
31
31
  end
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: steve
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.3
4
+ version: 2.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - aTech Media
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-21 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: will_paginate
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: 3.0.0
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: 3.0.0
11
+ date: 2019-09-30 00:00:00.000000000 Z
12
+ dependencies: []
27
13
  description:
28
14
  email: support@atechmedia.com
29
15
  executables: []
@@ -62,7 +48,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
62
48
  version: '0'
63
49
  requirements: []
64
50
  rubyforge_project:
65
- rubygems_version: 2.2.2
51
+ rubygems_version: 2.6.14.3
66
52
  signing_key:
67
53
  specification_version: 4
68
54
  summary: Steve Jobs background job runner