belated 0.4.3 → 0.5.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/Gemfile.lock +2 -2
- data/README.md +20 -20
- data/bin/belated +0 -1
- data/lib/belated.rb +20 -11
- data/lib/belated/client.rb +15 -7
- data/lib/belated/job_wrapper.rb +44 -0
- data/lib/belated/queue.rb +7 -5
- data/lib/belated/version.rb +1 -1
- data/lib/belated/worker.rb +1 -10
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ad4adbecffc63b1e63591503cb333182b4f06238d88caa1dbb64972ca7ab3c3
|
4
|
+
data.tar.gz: 1a358d4ab8a37f77fcfb5a963b289631e67286d720096ca29c0925760a6b61a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61b201e5a85b59ba2da90183c8d5f547b1098f1600692285addfab5c656bb396ed4ab5edb798e5f73860b05c071fbb77c9644dca02695c3072c19001c372a3f2
|
7
|
+
data.tar.gz: 73735b1e25f3e51e26420e9d9294af135b46d8644d6a765213250a7c533f4f549f9332fb258b9615bbaeb3857db3e6c75dd193dafbf5c443d7cf63b5fee90b79
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.5.1] - 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.
|
15
|
+
|
16
|
+
## [0.4.4] - 2021-08-07
|
17
|
+
|
18
|
+
- Now if you pass something with a syntax error in it as a job, it should not bring down the whole app!
|
19
|
+
|
3
20
|
## [0.4.3] - 2021-08-06
|
4
21
|
|
5
22
|
- Client now starts the banker thread to execute jobs that were enqueued when there was no connection to Belated only if necessary.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
[](https://www.codefactor.io/repository/github/sampokuokkanen/belated) [](https://badge.fury.io/rb/belated)
|
4
4
|
|
5
|
-
This is Belated, a new Ruby backend job library! It supports running procs and classes in the background. To deal with restarts, it uses YAML to load the queue into a file, which it then calls at startup to find the previous jobs.
|
5
|
+
This is Belated, a new Ruby backend job library! It supports running procs, lambdas and classes in the background. To deal with restarts, it uses YAML to load the queue into a file, which it then calls at startup to find the previous jobs. There is no way in Ruby to save procs or lambdas to a file, so they are discarded when the process restarts.
|
6
6
|
|
7
7
|
Belated uses the Ruby Queue class, so it's First In, First Out (FIFO).
|
8
8
|
|
@@ -10,18 +10,23 @@ 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
|
|
19
|
+
- Don't use class instance variables.
|
20
|
+
- Make port configurable.
|
21
|
+
- Don't hardcode timezone.
|
17
22
|
- Add some checks to the client for proper jobs.
|
18
|
-
- Don't crash on errors (Partially done)
|
19
23
|
- Have multiple queues?
|
20
24
|
- Maybe support ActiveJob?
|
21
|
-
- Have a web UI
|
22
|
-
-
|
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
|
-
and mention it in the readme.
|
29
|
+
and mention it in the readme. (Capistrano support?)
|
25
30
|
- Add a section telling people to use Sidekiq if they can
|
26
31
|
|
27
32
|
## Installation
|
@@ -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
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
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.
|
@@ -90,6 +89,7 @@ and you can use the client!
|
|
90
89
|
Call
|
91
90
|
|
92
91
|
```ruby
|
92
|
+
job = proc { 2 / 1 }
|
93
93
|
client.perform_belated(job)
|
94
94
|
```
|
95
95
|
|
@@ -101,7 +101,7 @@ If you don't want the job to run right away, you can also pass it a keyword para
|
|
101
101
|
client.perform_belated(job, Time.now + 1.month)
|
102
102
|
```
|
103
103
|
|
104
|
-
Note that you probably want to memoize the client, as it always creates a 'banker thread' now if you have no connection. Maybe even use it as a global!(`$client`)
|
104
|
+
Note that you probably want to memoize the client, as it always creates a 'banker thread' now if you have no connection and there is the overhead of connecting to dRuby. Maybe even use it as a global!(`$client`)
|
105
105
|
|
106
106
|
# Settings
|
107
107
|
|
data/bin/belated
CHANGED
data/lib/belated.rb
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'belated/logging'
|
3
4
|
require_relative 'belated/version'
|
4
5
|
require_relative 'belated/worker'
|
5
|
-
|
6
|
+
require 'belated/client'
|
7
|
+
require 'belated/job_wrapper'
|
8
|
+
require 'belated/queue'
|
6
9
|
require 'drb'
|
7
|
-
require 'yaml'
|
8
|
-
require 'singleton'
|
9
10
|
require 'dry-configurable'
|
10
|
-
require 'belated/client'
|
11
11
|
require 'logger'
|
12
|
-
require '
|
12
|
+
require 'singleton'
|
13
|
+
require 'yaml'
|
13
14
|
|
14
15
|
# Belated is a pure Ruby job backend.
|
15
16
|
# It has limited functionality, as it only accepts
|
@@ -64,7 +65,11 @@ class Belated
|
|
64
65
|
@@queue.push(:shutdown)
|
65
66
|
end
|
66
67
|
Thread.new { stop_workers }
|
67
|
-
|
68
|
+
# Max 30 seconds to shutdown
|
69
|
+
timeout = 0
|
70
|
+
until (timeout += 0.1) >= 30 || @@queue.empty? || $TESTING
|
71
|
+
sleep 0.1
|
72
|
+
end
|
68
73
|
exit
|
69
74
|
end
|
70
75
|
end
|
@@ -87,9 +92,9 @@ class Belated
|
|
87
92
|
log 'starting future jobs thread'
|
88
93
|
loop do
|
89
94
|
@@queue.future_jobs.each_with_index do |job, i|
|
90
|
-
if job
|
91
|
-
log @@queue.future_jobs.delete_at(i)
|
92
|
-
@@queue.push(job
|
95
|
+
if job.at <= Time.now.utc
|
96
|
+
log "Deleting #{@@queue.future_jobs.delete_at(i)} from future jobs"
|
97
|
+
@@queue.push(job)
|
93
98
|
end
|
94
99
|
end
|
95
100
|
sleep 0.01
|
@@ -151,12 +156,16 @@ class Belated
|
|
151
156
|
@@queue.clear
|
152
157
|
end
|
153
158
|
|
159
|
+
def self.fetch_job
|
160
|
+
@@queue.pop
|
161
|
+
end
|
162
|
+
|
154
163
|
def job_list
|
155
164
|
@@queue
|
156
165
|
end
|
157
166
|
|
158
|
-
def self.
|
159
|
-
@@queue
|
167
|
+
def self.job_list
|
168
|
+
@@queue
|
160
169
|
end
|
161
170
|
|
162
171
|
class Error < StandardError; end
|
data/lib/belated/client.rb
CHANGED
@@ -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
|
29
|
+
job = bank.pop
|
29
30
|
|
30
|
-
perform(job
|
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
|
-
# @
|
40
|
-
|
41
|
-
|
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(
|
51
|
+
bank.push(job_wrapper)
|
44
52
|
start_banker_thread if banker_thread.nil?
|
45
|
-
|
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
|
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 <<
|
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.
|
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
|
data/lib/belated/version.rb
CHANGED
data/lib/belated/worker.rb
CHANGED
@@ -18,18 +18,9 @@ class Belated
|
|
18
18
|
|
19
19
|
break if job == :shutdown
|
20
20
|
|
21
|
-
log
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def call_job(job)
|
26
|
-
if job.respond_to?(:call)
|
27
|
-
job.call
|
28
|
-
else
|
21
|
+
log "Worker #{@number} got job: #{job.inspect}"
|
29
22
|
job.perform
|
30
23
|
end
|
31
|
-
rescue StandardError => e
|
32
|
-
e.inspect
|
33
24
|
end
|
34
25
|
end
|
35
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
|
+
version: 0.5.2
|
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-
|
11
|
+
date: 2021-08-12 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.
|
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!
|