belated 0.4.0 → 0.4.4
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 +15 -0
- data/Gemfile.lock +1 -1
- data/README.md +12 -14
- data/lib/belated.rb +13 -27
- data/lib/belated/client.rb +22 -3
- data/lib/belated/queue.rb +43 -1
- data/lib/belated/version.rb +1 -1
- data/lib/belated/worker.rb +9 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b946c5167a28af0cd73bad436d52c47ad19af699d88bd8a20c592b8fb2327ea1
|
4
|
+
data.tar.gz: da03cfda6b0c4ec8b9a9a7ef4cb52747294f3b582633ad023cc98aa5e88c697f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5add925bbaca101aef9a35c8d4ae6cc544b736ebbbcbae4e6603faf0e42a0a248bd04844b0af8fa6dceb32f021948c105bf18031fd0c97d12cfc85ac9d9cde3f
|
7
|
+
data.tar.gz: 13ac76b9f2b956e9b0b363d16ec3e615365ee39132fe788022c11c2ff90ed7fa9234c403903ac268efae0c63a51afbe6bc9893eb95cd8bbdf5d20b75e6a85aaf
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
|
4
|
+
## [0.4.4] - 2021-08-07
|
5
|
+
|
6
|
+
- Now if you pass something with a syntax error in it as a job, it should not bring down the whole app!
|
7
|
+
|
8
|
+
## [0.4.3] - 2021-08-06
|
9
|
+
|
10
|
+
- Client now starts the banker thread to execute jobs that were enqueued when there was no connection to Belated only if necessary.
|
11
|
+
## [0.4.2] - 2021-08-05
|
12
|
+
|
13
|
+
- Client also handles no connection, now it saves jobs to a bank and adds them to the queue once it has a connection.
|
14
|
+
## [0.4.1] - 2021-08-05
|
15
|
+
|
16
|
+
- Now handles saving future jobs too! So if you have a job enqueued for tomorrow, and restart Belated, it should still be enqueued.
|
17
|
+
|
3
18
|
## [0.4.0] - 2021-08-03
|
4
19
|
|
5
20
|
- Now you can enqueue jobs to be done at a later time. Just pass an `at:` keyword param to the client.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -2,33 +2,28 @@
|
|
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
|
+
|
7
|
+
Belated uses the Ruby Queue class, so it's First In, First Out (FIFO).
|
6
8
|
|
7
9
|
Note that Belated used to be called HardWorker. That name was already in use in Sidekiq documentation and a bit too generic anyway.
|
8
10
|
|
9
11
|
It uses dRuby to do the communication! Which is absolute great. No need for Redis or PostgreSQL, just Ruby standard libraries.
|
10
12
|
|
13
|
+
Can be used with or without Rails.
|
14
|
+
|
11
15
|
TODO LIST:
|
12
16
|
|
13
|
-
-
|
14
|
-
|
15
|
-
- Don't crash on errors (Partially done)
|
16
|
-
- Save jobs enqueued at a future date too when quitting (now it only saves the jobs in the queue)
|
17
|
+
- Add retries for jobs
|
18
|
+
- Add some checks to the client for proper jobs.
|
17
19
|
- Have multiple queues?
|
18
20
|
- Maybe support ActiveJob?
|
19
21
|
- Have a web UI
|
20
22
|
- Do some performance testing
|
23
|
+
- Deploy a Rails app to production that is using Belated
|
24
|
+
and mention it in the readme. (Capistrano support?)
|
21
25
|
- Add a section telling people to use Sidekiq if they can
|
22
26
|
|
23
|
-
DONE
|
24
|
-
|
25
|
-
- ~~Make it possible to schedule jobs~~
|
26
|
-
- ~~Marshal the job queue into a file so you don't lose all progress~~
|
27
|
-
(Ended up using YAML)
|
28
|
-
- ~~Add a logger~~
|
29
|
-
- ~~Support Rails~~ (Supported!)
|
30
|
-
- ~~Parse options from command line, eg. `--workers 10`~~(Done!)
|
31
|
-
|
32
27
|
## Installation
|
33
28
|
|
34
29
|
Add this line to your application's Gemfile:
|
@@ -95,6 +90,7 @@ and you can use the client!
|
|
95
90
|
Call
|
96
91
|
|
97
92
|
```ruby
|
93
|
+
job = proc { 2 / 1 }
|
98
94
|
client.perform_belated(job)
|
99
95
|
```
|
100
96
|
|
@@ -106,6 +102,8 @@ If you don't want the job to run right away, you can also pass it a keyword para
|
|
106
102
|
client.perform_belated(job, Time.now + 1.month)
|
107
103
|
```
|
108
104
|
|
105
|
+
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`)
|
106
|
+
|
109
107
|
# Settings
|
110
108
|
|
111
109
|
Configuring Belated:
|
data/lib/belated.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
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/queue'
|
6
8
|
require 'drb'
|
7
|
-
require 'yaml'
|
8
|
-
require 'singleton'
|
9
9
|
require 'dry-configurable'
|
10
|
-
require 'belated/client'
|
11
10
|
require 'logger'
|
12
|
-
require '
|
11
|
+
require 'singleton'
|
12
|
+
require 'yaml'
|
13
13
|
|
14
14
|
# Belated is a pure Ruby job backend.
|
15
15
|
# It has limited functionality, as it only accepts
|
@@ -22,7 +22,6 @@ class Belated
|
|
22
22
|
include Logging
|
23
23
|
include Singleton unless $TESTING
|
24
24
|
URI = 'druby://localhost:8788'
|
25
|
-
FILE_NAME = 'belated_dump'
|
26
25
|
@@queue = Belated::Queue.new
|
27
26
|
|
28
27
|
setting :rails, true
|
@@ -37,7 +36,7 @@ class Belated
|
|
37
36
|
# Aliased for testing purposes.
|
38
37
|
# This is only run from the bin file.
|
39
38
|
def start
|
40
|
-
boot_app && load_jobs
|
39
|
+
boot_app && @@queue.load_jobs
|
41
40
|
@worker_list = []
|
42
41
|
Belated.config.workers.times do |i|
|
43
42
|
@worker_list << Thread.new { Worker.new(number: i.next) }
|
@@ -65,7 +64,11 @@ class Belated
|
|
65
64
|
@@queue.push(:shutdown)
|
66
65
|
end
|
67
66
|
Thread.new { stop_workers }
|
68
|
-
|
67
|
+
# Max 30 seconds to shutdown
|
68
|
+
timeout = 0
|
69
|
+
until (timeout += 0.1) >= 30 || @@queue.empty? || $TESTING
|
70
|
+
sleep 0.1
|
71
|
+
end
|
69
72
|
exit
|
70
73
|
end
|
71
74
|
end
|
@@ -97,20 +100,9 @@ class Belated
|
|
97
100
|
end
|
98
101
|
end
|
99
102
|
|
100
|
-
def load_jobs
|
101
|
-
log "reloading... if file exists #{File.exist?(Belated::FILE_NAME)}"
|
102
|
-
return unless File.exist?(Belated::FILE_NAME)
|
103
|
-
|
104
|
-
jobs = YAML.load(File.binread(FILE_NAME))
|
105
|
-
jobs.each do |job|
|
106
|
-
@@queue.push(job)
|
107
|
-
end
|
108
|
-
File.delete(Belated::FILE_NAME)
|
109
|
-
end
|
110
|
-
|
111
103
|
def reload
|
112
104
|
log 'reloading...'
|
113
|
-
load_jobs
|
105
|
+
@@queue.load_jobs
|
114
106
|
end
|
115
107
|
|
116
108
|
def stop_workers
|
@@ -118,13 +110,7 @@ class Belated
|
|
118
110
|
sleep 0.1 if worker.alive?
|
119
111
|
Thread.kill(worker)
|
120
112
|
end
|
121
|
-
|
122
|
-
@@queue.length.times do |_i|
|
123
|
-
unless (klass = @@queue.pop).instance_of?(Proc) || klass == :shutdown
|
124
|
-
class_array << klass
|
125
|
-
end
|
126
|
-
end
|
127
|
-
pp File.open(FILE_NAME, 'wb') { |f| f.write(YAML.dump(class_array)) }
|
113
|
+
@@queue.save_jobs
|
128
114
|
exit unless $TESTING
|
129
115
|
end
|
130
116
|
|
data/lib/belated/client.rb
CHANGED
@@ -1,29 +1,48 @@
|
|
1
1
|
class Belated
|
2
2
|
# The client class is responsible for managing the connection to the
|
3
|
-
# DRb server.
|
3
|
+
# DRb server. If it has no connection, it adds the jobs to a bank queue.
|
4
4
|
# You can enqueue jobs to be processed by the server.
|
5
5
|
# Example:
|
6
6
|
# client = Belated::Client.new
|
7
7
|
# client.enqueue(JubJub.new, at: Time.now + 5.seconds)
|
8
8
|
class Client
|
9
|
-
attr_accessor :queue
|
9
|
+
attr_accessor :queue, :bank, :banker_thread
|
10
10
|
|
11
11
|
# Starts up the client.
|
12
12
|
# Connects to the queue through DRb.
|
13
13
|
# @return [void]
|
14
14
|
def initialize
|
15
15
|
server_uri = Belated::URI
|
16
|
-
# @bank =
|
17
16
|
DRb.start_service
|
17
|
+
self.bank = Thread::Queue.new
|
18
18
|
self.queue = DRbObject.new_with_uri(server_uri)
|
19
19
|
end
|
20
20
|
|
21
|
+
# Thread in charge of handling the bank queue.
|
22
|
+
# You probably want to memoize the client in order to avoid
|
23
|
+
# having many threads in the sleep state.
|
24
|
+
# @return [void]
|
25
|
+
def start_banker_thread
|
26
|
+
self.banker_thread = Thread.new do
|
27
|
+
loop do
|
28
|
+
job, at = bank.pop
|
29
|
+
|
30
|
+
perform(job, at: at)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
21
35
|
# The method that pushes the jobs to the queue.
|
36
|
+
# If there is no connection, it pushes the job to the bank.
|
22
37
|
# @param job [Object] - The the job to be pushed.
|
23
38
|
# @param at [Date] - The time at which the job should be executed.
|
24
39
|
# @return [Object] - The job that was pushed.
|
25
40
|
def perform(job, at: nil)
|
26
41
|
queue.push(job, at: at)
|
42
|
+
rescue DRb::DRbConnError
|
43
|
+
bank.push([job, at])
|
44
|
+
start_banker_thread if banker_thread.nil?
|
45
|
+
# banker_thread.wakeup if banker_thread.status == 'sleep'
|
27
46
|
end
|
28
47
|
alias perform_belated perform
|
29
48
|
alias perform_later perform
|
data/lib/belated/queue.rb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'belated/job'
|
4
|
+
require 'belated/logging'
|
3
5
|
class Belated
|
4
6
|
class Queue
|
7
|
+
include Logging
|
5
8
|
attr_accessor :future_jobs
|
6
9
|
|
10
|
+
FILE_NAME = 'belated_dump'
|
11
|
+
|
7
12
|
def initialize(queue: Thread::Queue.new, future_jobs: [])
|
8
13
|
@queue = queue
|
9
14
|
self.future_jobs = future_jobs
|
@@ -33,5 +38,42 @@ class Belated
|
|
33
38
|
def length
|
34
39
|
@queue.length
|
35
40
|
end
|
41
|
+
|
42
|
+
def load_jobs
|
43
|
+
log "reloading... if file exists #{File.exist?(FILE_NAME)}"
|
44
|
+
return unless File.exist?(FILE_NAME)
|
45
|
+
|
46
|
+
jobs = YAML.load(File.binread(FILE_NAME))
|
47
|
+
jobs.each do |job|
|
48
|
+
if job.is_a?(Job)
|
49
|
+
future_jobs.push(job)
|
50
|
+
else
|
51
|
+
@queue.push(job)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
File.delete(FILE_NAME)
|
55
|
+
end
|
56
|
+
|
57
|
+
def save_jobs
|
58
|
+
class_array = []
|
59
|
+
@queue.length.times do |_i|
|
60
|
+
unless proc_or_shutdown?(klass = @queue.pop)
|
61
|
+
class_array << klass
|
62
|
+
end
|
63
|
+
end
|
64
|
+
future_jobs.each do |_job|
|
65
|
+
unless proc_or_shutdown?(klass = future_jobs.pop)
|
66
|
+
class_array << klass
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
pp File.open(FILE_NAME, 'wb') { |f| f.write(YAML.dump(class_array)) }
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def proc_or_shutdown?(job)
|
76
|
+
job.instance_of?(Proc) || job == :shutdown
|
77
|
+
end
|
36
78
|
end
|
37
79
|
end
|
data/lib/belated/version.rb
CHANGED
data/lib/belated/worker.rb
CHANGED
@@ -22,14 +22,21 @@ class Belated
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
# rubocop:disable Lint/RescueException
|
25
26
|
def call_job(job)
|
26
27
|
if job.respond_to?(:call)
|
27
28
|
job.call
|
28
29
|
else
|
29
30
|
job.perform
|
30
31
|
end
|
31
|
-
rescue
|
32
|
-
e.
|
32
|
+
rescue Exception => e
|
33
|
+
case e.class
|
34
|
+
when Interrupt, SignalException
|
35
|
+
raise e
|
36
|
+
else
|
37
|
+
e.inspect
|
38
|
+
end
|
33
39
|
end
|
40
|
+
# rubocop:enable Lint/RescueException
|
34
41
|
end
|
35
42
|
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
|
+
version: 0.4.4
|
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-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: drb
|