belated 0.4.4 → 0.5.3

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
  SHA256:
3
- metadata.gz: b946c5167a28af0cd73bad436d52c47ad19af699d88bd8a20c592b8fb2327ea1
4
- data.tar.gz: da03cfda6b0c4ec8b9a9a7ef4cb52747294f3b582633ad023cc98aa5e88c697f
3
+ metadata.gz: 2e16dfb18af8fa012bede8622dba2328f725884870aa921f1759350350e50382
4
+ data.tar.gz: 522d6992077f9fcc93c250ccc3dd20d818d60633a3dcf9874d0cc469d225c283
5
5
  SHA512:
6
- metadata.gz: 5add925bbaca101aef9a35c8d4ae6cc544b736ebbbcbae4e6603faf0e42a0a248bd04844b0af8fa6dceb32f021948c105bf18031fd0c97d12cfc85ac9d9cde3f
7
- data.tar.gz: 13ac76b9f2b956e9b0b363d16ec3e615365ee39132fe788022c11c2ff90ed7fa9234c403903ac268efae0c63a51afbe6bc9893eb95cd8bbdf5d20b75e6a85aaf
6
+ metadata.gz: 28cc95841c797852585a165fabf2a9bab8d27da36d204e92daa7a3ec03db142a990d0e90647fef928d14e7520ad03499872187a6adfa10df8b1e55a15e1b0c88
7
+ data.tar.gz: 41b757722ecffe023764820b9992e3e0f007cd6bbe41ce473f8398aaf65d50a8d4e8e609acd61c79e0c6e58f3fdc8be57cc20424c1bf6bd11753be9cb95a5217
data/.rubocop.yml CHANGED
@@ -1,3 +1,4 @@
1
+ require: rubocop-performance
1
2
  AllCops:
2
3
  TargetRubyVersion: 2.7
3
4
  NewCops: enable
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.5.2] - 2021-08-13
4
+
5
+ - An error with shutdown handling was fixed.
6
+
7
+ ## [0.5.1] - 2021-08-12
8
+
9
+ - Requiring byebug in bin file. 😮
10
+
11
+ ## [0.5.0] - 2021-08-011
12
+
13
+ - Job retries! The jobs now have ids, so you can follow the job and it's retries from the log.
14
+ - Quite a lot has changed internally, so if you were not using the Belated::Queue class to enqueue your jobs, you will need to update your code.
3
15
 
4
16
  ## [0.4.4] - 2021-08-07
5
17
 
data/Gemfile CHANGED
@@ -9,10 +9,10 @@ gem 'rake', '~> 13.0'
9
9
 
10
10
  gem 'rspec', '~> 3.0'
11
11
 
12
- gem 'rubocop', '~> 1.7'
13
-
14
12
  gem 'database_cleaner-active_record'
15
13
  gem 'rails', '>= 6.1.3'
16
14
  gem 'rspec-rails'
15
+ gem 'rubocop', '~> 1.7'
16
+ gem 'rubocop-performance', require: false
17
17
  gem 'sqlite3'
18
18
  gem 'stackprof'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- belated (0.4.4)
4
+ belated (0.5.3)
5
5
  drb
6
6
  dry-configurable
7
7
 
@@ -169,6 +169,9 @@ GEM
169
169
  unicode-display_width (>= 1.4.0, < 3.0)
170
170
  rubocop-ast (1.7.0)
171
171
  parser (>= 3.0.1.1)
172
+ rubocop-performance (1.11.4)
173
+ rubocop (>= 1.7.0, < 2.0)
174
+ rubocop-ast (>= 0.4.0)
172
175
  ruby-progressbar (1.11.0)
173
176
  sprockets (4.0.2)
174
177
  concurrent-ruby (~> 1.0)
@@ -200,8 +203,9 @@ DEPENDENCIES
200
203
  rspec (~> 3.0)
201
204
  rspec-rails
202
205
  rubocop (~> 1.7)
206
+ rubocop-performance
203
207
  sqlite3
204
208
  stackprof
205
209
 
206
210
  BUNDLED WITH
207
- 2.2.17
211
+ 2.2.22
data/README.md CHANGED
@@ -10,16 +10,21 @@ Note that Belated used to be called HardWorker. That name was already in use in
10
10
 
11
11
  It uses dRuby to do the communication! Which is absolute great. No need for Redis or PostgreSQL, just Ruby standard libraries.
12
12
 
13
+ Note that currently the timezone is hardcoded to UTC.
14
+
13
15
  Can be used with or without Rails.
14
16
 
15
17
  TODO LIST:
16
18
 
17
- - Add retries for jobs
19
+ - Don't use class instance variables.
20
+ - Make port configurable.
21
+ - Don't hardcode timezone.
18
22
  - Add some checks to the client for proper jobs.
19
23
  - Have multiple queues?
20
24
  - Maybe support ActiveJob?
21
- - Have a web UI
22
- - Do some performance testing
25
+ - Have a web UI.
26
+ - Have a job history
27
+ - Do some performance testing.
23
28
  - Deploy a Rails app to production that is using Belated
24
29
  and mention it in the readme. (Capistrano support?)
25
30
  - Add a section telling people to use Sidekiq if they can
@@ -50,15 +55,6 @@ Then, in another program, connect to Belated and give it a job to do.
50
55
  Sample below:
51
56
 
52
57
  ```ruby
53
- class DummyWorker
54
- attr_accessor :queue
55
-
56
- def initialize
57
- server_uri = Belated::URI
58
- self.queue = DRbObject.new_with_uri(server_uri)
59
- end
60
- end
61
-
62
58
  class DumDum
63
59
  # classes need to have a perform method
64
60
  def perform
@@ -66,11 +62,14 @@ class DumDum
66
62
  end
67
63
  end
68
64
 
69
- # Need to start dRuby on the client side
70
- DRb.start_service
71
- dummy = DummyWorker.new
72
- dummy.queue.push(proc { 2 / 1 })
73
- dummy.queue.push(DumDum.new)
65
+ client = Belated::Client.new
66
+ client.perform_belated(proc { 2 / 1 })
67
+ client.perform_belated(DumDum.new)
68
+ # client.perform, client.perform_later are also good
69
+ # if you want to do something later:
70
+ client.perform_belated(DumDum.new, at: Time.now + 5 * 60)
71
+ # max retries:
72
+ client.perform_belated(DumDum.new, max_retries: 3) # default 5
74
73
  ```
75
74
 
76
75
  Belated runs on localhost, port 8788.
@@ -137,9 +136,15 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
137
136
 
138
137
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
139
138
 
139
+
140
+ # Possible problems
141
+
142
+ If you have the port 8788 already in use, you can check the ports in use in Linux with the following command:
143
+
144
+ $ sudo lsof -i -P -n | grep LISTEN
140
145
  ## Contributing
141
146
 
142
- Bug reports and pull requests are welcome on GitHub at https://github.com/sampokuokkanen/belated. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/sampokuokkanen/belated/blob/master/CODE_OF_CONDUCT.md).
147
+ Bug reports, questions and pull requests are welcome on GitHub at https://github.com/sampokuokkanen/belated. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/sampokuokkanen/belated/blob/master/CODE_OF_CONDUCT.md).
143
148
 
144
149
  ## License
145
150
 
data/bin/belated CHANGED
@@ -5,7 +5,6 @@ $TESTING = false
5
5
  $LOAD_PATH.unshift File.expand_path("#{File.dirname(__FILE__)}/../lib")
6
6
  require 'belated'
7
7
  require 'optparse'
8
- require 'byebug'
9
8
 
10
9
  OptionParser.new { |opts|
11
10
  opts.banner = 'Usage: belated [options]'
data/lib/belated.rb CHANGED
@@ -4,6 +4,7 @@ require_relative 'belated/logging'
4
4
  require_relative 'belated/version'
5
5
  require_relative 'belated/worker'
6
6
  require 'belated/client'
7
+ require 'belated/job_wrapper'
7
8
  require 'belated/queue'
8
9
  require 'drb'
9
10
  require 'dry-configurable'
@@ -90,13 +91,17 @@ class Belated
90
91
  def enqueue_future_jobs
91
92
  log 'starting future jobs thread'
92
93
  loop do
94
+ sleep 0.1
95
+ if @@queue.future_jobs.empty?
96
+ sleep 1
97
+ next
98
+ end
93
99
  @@queue.future_jobs.each_with_index do |job, i|
94
- if job[:at] <= Time.now.utc
95
- log @@queue.future_jobs.delete_at(i)
96
- @@queue.push(job[:klass])
100
+ if job.at <= Time.now.utc
101
+ log "Deleting #{@@queue.future_jobs.delete_at(i)} from future jobs"
102
+ @@queue.push(job)
97
103
  end
98
104
  end
99
- sleep 0.01
100
105
  end
101
106
  end
102
107
 
@@ -155,12 +160,16 @@ class Belated
155
160
  @@queue.clear
156
161
  end
157
162
 
163
+ def self.fetch_job
164
+ @@queue.pop
165
+ end
166
+
158
167
  def job_list
159
168
  @@queue
160
169
  end
161
170
 
162
- def self.fetch_job
163
- @@queue.pop
171
+ def self.job_list
172
+ @@queue
164
173
  end
165
174
 
166
175
  class Error < StandardError; end
@@ -1,3 +1,4 @@
1
+ require 'belated/job_wrapper'
1
2
  class Belated
2
3
  # The client class is responsible for managing the connection to the
3
4
  # DRb server. If it has no connection, it adds the jobs to a bank queue.
@@ -25,9 +26,9 @@ class Belated
25
26
  def start_banker_thread
26
27
  self.banker_thread = Thread.new do
27
28
  loop do
28
- job, at = bank.pop
29
+ job = bank.pop
29
30
 
30
- perform(job, at: at)
31
+ perform(job)
31
32
  end
32
33
  end
33
34
  end
@@ -36,13 +37,20 @@ class Belated
36
37
  # If there is no connection, it pushes the job to the bank.
37
38
  # @param job [Object] - The the job to be pushed.
38
39
  # @param at [Date] - The time at which the job should be executed.
39
- # @return [Object] - The job that was pushed.
40
- def perform(job, at: nil)
41
- queue.push(job, at: at)
40
+ # @param max_retries [Integer] - Times the job should be retried if it fails.
41
+ # @return [JobWrapper] - The job wrapper for the queue.
42
+ def perform(job, at: nil, max_retries: 5)
43
+ job_wrapper = if job.is_a?(JobWrapper)
44
+ job
45
+ else
46
+ JobWrapper.new(job: job, at: at, max_retries: max_retries)
47
+ end
48
+ pp queue.push(job_wrapper)
49
+ job_wrapper
42
50
  rescue DRb::DRbConnError
43
- bank.push([job, at])
51
+ bank.push(job_wrapper)
44
52
  start_banker_thread if banker_thread.nil?
45
- # banker_thread.wakeup if banker_thread.status == 'sleep'
53
+ banker_thread.wakeup if banker_thread.status == 'sleep'
46
54
  end
47
55
  alias perform_belated perform
48
56
  alias perform_later perform
@@ -0,0 +1,44 @@
1
+ require 'securerandom'
2
+ require_relative 'logging'
3
+
4
+ class Belated
5
+ class JobWrapper
6
+ include Logging
7
+ attr_accessor :retries, :max_retries, :id, :job, :at
8
+
9
+ def initialize(job:, max_retries: 5, at: nil)
10
+ self.retries = 0
11
+ self.max_retries = max_retries
12
+ self.id = SecureRandom.uuid
13
+ self.job = job
14
+ self.at = at
15
+ end
16
+
17
+ # rubocop:disable Lint/RescueException
18
+ def perform
19
+ if job.respond_to?(:call)
20
+ job.call
21
+ else
22
+ job.perform
23
+ end
24
+ rescue Exception => e
25
+ case e.class
26
+ when Interrupt, SignalException
27
+ raise e
28
+ else
29
+ retry_job
30
+ "Error while executing job, #{e.inspect}. Retry #{retries} of #{max_retries}"
31
+ end
32
+ end
33
+ # rubocop:enable Lint/RescueException
34
+
35
+ def retry_job
36
+ self.retries += 1
37
+ return if retries > max_retries
38
+
39
+ self.at = Time.now.utc + (retries.next**4)
40
+ log "Job #{id} failed, retrying at #{at}"
41
+ Belated.job_list.push(self)
42
+ end
43
+ end
44
+ end
data/lib/belated/queue.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'belated/job'
4
4
  require 'belated/logging'
5
+ require 'belated/job_wrapper'
5
6
  class Belated
6
7
  class Queue
7
8
  include Logging
@@ -14,11 +15,12 @@ class Belated
14
15
  self.future_jobs = future_jobs
15
16
  end
16
17
 
17
- def push(job, at: nil)
18
- if at.nil?
18
+ def push(job)
19
+ if job == :shutdown || job.at.nil? ||
20
+ job.at <= Time.now.utc
19
21
  @queue.push(job)
20
22
  else
21
- @future_jobs << Job.new(job, at)
23
+ @future_jobs << job
22
24
  end
23
25
  end
24
26
 
@@ -45,7 +47,7 @@ class Belated
45
47
 
46
48
  jobs = YAML.load(File.binread(FILE_NAME))
47
49
  jobs.each do |job|
48
- if job.is_a?(Job)
50
+ if job.at && job.at > Time.now.utc
49
51
  future_jobs.push(job)
50
52
  else
51
53
  @queue.push(job)
@@ -73,7 +75,7 @@ class Belated
73
75
  private
74
76
 
75
77
  def proc_or_shutdown?(job)
76
- job.instance_of?(Proc) || job == :shutdown
78
+ job.job.instance_of?(Proc) || job == :shutdown
77
79
  end
78
80
  end
79
81
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Belated
4
- VERSION = '0.4.4'
4
+ VERSION = '0.5.3'
5
5
  end
@@ -18,25 +18,9 @@ class Belated
18
18
 
19
19
  break if job == :shutdown
20
20
 
21
- log call_job(job)
22
- end
23
- end
24
-
25
- # rubocop:disable Lint/RescueException
26
- def call_job(job)
27
- if job.respond_to?(:call)
28
- job.call
29
- else
21
+ log "Worker #{@number} got job: #{job.inspect}"
30
22
  job.perform
31
23
  end
32
- rescue Exception => e
33
- case e.class
34
- when Interrupt, SignalException
35
- raise e
36
- else
37
- e.inspect
38
- end
39
24
  end
40
- # rubocop:enable Lint/RescueException
41
25
  end
42
26
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: belated
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sampo Kuokkanen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-07 00:00:00.000000000 Z
11
+ date: 2021-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: drb
@@ -81,6 +81,7 @@ files:
81
81
  - lib/belated.rb
82
82
  - lib/belated/client.rb
83
83
  - lib/belated/job.rb
84
+ - lib/belated/job_wrapper.rb
84
85
  - lib/belated/logging.rb
85
86
  - lib/belated/queue.rb
86
87
  - lib/belated/rails.rb
@@ -108,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
109
  - !ruby/object:Gem::Version
109
110
  version: '0'
110
111
  requirements: []
111
- rubygems_version: 3.2.15
112
+ rubygems_version: 3.2.22
112
113
  signing_key:
113
114
  specification_version: 4
114
115
  summary: Run background jobs with Belated and dRuby!