belated 0.3.2 → 0.4.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/.gitignore +1 -0
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +17 -1
- data/README.md +15 -14
- data/lib/belated.rb +20 -24
- data/lib/belated/client.rb +28 -3
- data/lib/belated/job.rb +1 -0
- data/lib/belated/queue.rb +79 -0
- data/lib/belated/version.rb +1 -1
- data/lib/belated/worker.rb +5 -3
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 33b9abbd449108f850f65e0afaa92929c780b03856e9e151efb6cc33b84021d5
|
4
|
+
data.tar.gz: eb9a7142602bae2572454c227d057adf9f38397c1638dcc6f66f2cd16019b766
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c50c1dfe80dceee431785ec150a0a5b6a7c220e18fc8c6a05069637d474d848719c5bfd05f0c0f4125e379348296ebb92823e71b985e76cccffe9e3080349822
|
7
|
+
data.tar.gz: 357053481de792ea44b832eade91895d5257074e3381333ddb58aaa48c20d08b6d02d6e84b57664218108ae2927d8247db7229f1a1fa91483a745a3202031a0d
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,20 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.4.2] - 2021-08-05
|
3
4
|
|
5
|
+
- Client also handles no connection, now it saves jobs to a bank and adds them to the queue once it has a connection.
|
6
|
+
## [0.4.1] - 2021-08-05
|
7
|
+
|
8
|
+
- Now handles saving future jobs too! So if you have a job enqueued for tomorrow, and restart Belated, it should still be enqueued.
|
9
|
+
|
10
|
+
## [0.4.0] - 2021-08-03
|
11
|
+
|
12
|
+
- Now you can enqueue jobs to be done at a later time. Just pass an `at:` keyword param to the client.
|
13
|
+
- Does not save the jobs when you quit.
|
14
|
+
|
15
|
+
## [0.3.3] - 2021-08-01
|
16
|
+
|
17
|
+
- Shutdown trapped signal thread, make sure :shutdown is not recorded as a job.
|
4
18
|
|
5
19
|
## [0.3.2] - 2021-07-31
|
6
20
|
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
belated (0.
|
4
|
+
belated (0.4.2)
|
5
5
|
drb
|
6
6
|
dry-configurable
|
7
7
|
|
@@ -72,6 +72,10 @@ GEM
|
|
72
72
|
byebug (11.1.3)
|
73
73
|
concurrent-ruby (1.1.9)
|
74
74
|
crass (1.0.6)
|
75
|
+
database_cleaner-active_record (2.0.1)
|
76
|
+
activerecord (>= 5.a)
|
77
|
+
database_cleaner-core (~> 2.0.0)
|
78
|
+
database_cleaner-core (2.0.1)
|
75
79
|
diff-lcs (1.4.4)
|
76
80
|
drb (2.0.4)
|
77
81
|
dry-configurable (0.12.1)
|
@@ -145,6 +149,14 @@ GEM
|
|
145
149
|
rspec-mocks (3.10.2)
|
146
150
|
diff-lcs (>= 1.2.0, < 2.0)
|
147
151
|
rspec-support (~> 3.10.0)
|
152
|
+
rspec-rails (5.0.1)
|
153
|
+
actionpack (>= 5.2)
|
154
|
+
activesupport (>= 5.2)
|
155
|
+
railties (>= 5.2)
|
156
|
+
rspec-core (~> 3.10)
|
157
|
+
rspec-expectations (~> 3.10)
|
158
|
+
rspec-mocks (~> 3.10)
|
159
|
+
rspec-support (~> 3.10)
|
148
160
|
rspec-support (3.10.2)
|
149
161
|
rubocop (1.18.3)
|
150
162
|
parallel (~> 1.10)
|
@@ -166,6 +178,7 @@ GEM
|
|
166
178
|
activesupport (>= 4.0)
|
167
179
|
sprockets (>= 3.0.0)
|
168
180
|
sqlite3 (1.4.2)
|
181
|
+
stackprof (0.2.16)
|
169
182
|
thor (1.1.0)
|
170
183
|
tzinfo (2.0.4)
|
171
184
|
concurrent-ruby (~> 1.0)
|
@@ -181,11 +194,14 @@ PLATFORMS
|
|
181
194
|
DEPENDENCIES
|
182
195
|
belated!
|
183
196
|
byebug
|
197
|
+
database_cleaner-active_record
|
184
198
|
rails (>= 6.1.3)
|
185
199
|
rake (~> 13.0)
|
186
200
|
rspec (~> 3.0)
|
201
|
+
rspec-rails
|
187
202
|
rubocop (~> 1.7)
|
188
203
|
sqlite3
|
204
|
+
stackprof
|
189
205
|
|
190
206
|
BUNDLED WITH
|
191
207
|
2.2.17
|
data/README.md
CHANGED
@@ -8,25 +8,20 @@ Note that Belated used to be called HardWorker. That name was already in use in
|
|
8
8
|
|
9
9
|
It uses dRuby to do the communication! Which is absolute great. No need for Redis or PostgreSQL, just Ruby standard libraries.
|
10
10
|
|
11
|
+
Can be used with or without Rails.
|
12
|
+
|
11
13
|
TODO LIST:
|
12
14
|
|
13
|
-
-
|
14
|
-
- Now supports it, partly.
|
15
|
+
- Add some checks to the client for proper jobs.
|
15
16
|
- Don't crash on errors (Partially done)
|
16
|
-
-
|
17
|
+
- Have multiple queues?
|
17
18
|
- Maybe support ActiveJob?
|
18
19
|
- Have a web UI
|
19
20
|
- Do some performance testing
|
21
|
+
- Deploy a Rails app to production that is using Belated
|
22
|
+
and mention it in the readme.
|
20
23
|
- Add a section telling people to use Sidekiq if they can
|
21
24
|
|
22
|
-
DONE
|
23
|
-
|
24
|
-
- ~~Marshal the job queue into a file so you don't lose all progress~~
|
25
|
-
(Ended up using YAML)
|
26
|
-
- ~~Add a logger~~
|
27
|
-
- ~~Support Rails~~ (Supported!)
|
28
|
-
- ~~Parse options from command line, eg. `--workers 10`~~(Done!)
|
29
|
-
|
30
25
|
## Installation
|
31
26
|
|
32
27
|
Add this line to your application's Gemfile:
|
@@ -98,6 +93,12 @@ client.perform_belated(job)
|
|
98
93
|
|
99
94
|
If you want to pass a job to Belated.
|
100
95
|
|
96
|
+
If you don't want the job to run right away, you can also pass it a keyword param `at:` like so:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
client.perform_belated(job, Time.now + 1.month)
|
100
|
+
```
|
101
|
+
|
101
102
|
# Settings
|
102
103
|
|
103
104
|
Configuring Belated:
|
@@ -113,15 +114,15 @@ end
|
|
113
114
|
|
114
115
|
From command line:
|
115
116
|
|
116
|
-
$ bundle exec belated --rails=true
|
117
|
+
$ bundle exec belated --rails=true
|
117
118
|
|
118
119
|
Use Rails or not.
|
119
120
|
|
120
|
-
$ bundle exec belated --rails_path=/my_rails_project
|
121
|
+
$ bundle exec belated --rails_path=/my_rails_project
|
121
122
|
|
122
123
|
Path to Rails project.
|
123
124
|
|
124
|
-
$ bundle exec belated --workers=10
|
125
|
+
$ bundle exec belated --workers=10
|
125
126
|
|
126
127
|
Number of workers.
|
127
128
|
|
data/lib/belated.rb
CHANGED
@@ -9,6 +9,7 @@ require 'singleton'
|
|
9
9
|
require 'dry-configurable'
|
10
10
|
require 'belated/client'
|
11
11
|
require 'logger'
|
12
|
+
require 'belated/queue'
|
12
13
|
|
13
14
|
# Belated is a pure Ruby job backend.
|
14
15
|
# It has limited functionality, as it only accepts
|
@@ -21,8 +22,7 @@ class Belated
|
|
21
22
|
include Logging
|
22
23
|
include Singleton unless $TESTING
|
23
24
|
URI = 'druby://localhost:8788'
|
24
|
-
|
25
|
-
@@queue = Queue.new
|
25
|
+
@@queue = Belated::Queue.new
|
26
26
|
|
27
27
|
setting :rails, true
|
28
28
|
setting :rails_path, '.'
|
@@ -36,17 +36,17 @@ class Belated
|
|
36
36
|
# Aliased for testing purposes.
|
37
37
|
# This is only run from the bin file.
|
38
38
|
def start
|
39
|
-
boot_app && load_jobs
|
39
|
+
boot_app && @@queue.load_jobs
|
40
40
|
@worker_list = []
|
41
|
-
Belated.config.workers.times do |
|
42
|
-
@worker_list << Thread.new { Worker.new }
|
41
|
+
Belated.config.workers.times do |i|
|
42
|
+
@worker_list << Thread.new { Worker.new(number: i.next) }
|
43
43
|
end
|
44
44
|
return unless Belated.config.connect
|
45
45
|
|
46
46
|
connect!
|
47
47
|
banner_and_info
|
48
48
|
trap_signals
|
49
|
-
|
49
|
+
enqueue_future_jobs
|
50
50
|
end
|
51
51
|
alias initialize start
|
52
52
|
|
@@ -55,7 +55,6 @@ class Belated
|
|
55
55
|
DRb.start_service(URI, @@queue, verbose: true)
|
56
56
|
rescue DRb::DRbConnError, Errno::EADDRINUSE
|
57
57
|
Belated.logger.error 'Could not connect to DRb server.'
|
58
|
-
retry
|
59
58
|
end
|
60
59
|
|
61
60
|
def trap_signals
|
@@ -65,7 +64,7 @@ class Belated
|
|
65
64
|
@@queue.push(:shutdown)
|
66
65
|
end
|
67
66
|
Thread.new { stop_workers }
|
68
|
-
sleep 0.1 until @@queue.empty?
|
67
|
+
sleep 0.1 until @@queue.empty? || $TESTING
|
69
68
|
exit
|
70
69
|
end
|
71
70
|
end
|
@@ -84,20 +83,22 @@ class Belated
|
|
84
83
|
Belated.config.rails
|
85
84
|
end
|
86
85
|
|
87
|
-
def
|
88
|
-
log
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
86
|
+
def enqueue_future_jobs
|
87
|
+
log 'starting future jobs thread'
|
88
|
+
loop do
|
89
|
+
@@queue.future_jobs.each_with_index do |job, i|
|
90
|
+
if job[:at] <= Time.now.utc
|
91
|
+
log @@queue.future_jobs.delete_at(i)
|
92
|
+
@@queue.push(job[:klass])
|
93
|
+
end
|
94
|
+
end
|
95
|
+
sleep 0.01
|
94
96
|
end
|
95
|
-
File.delete(Belated::FILE_NAME)
|
96
97
|
end
|
97
98
|
|
98
99
|
def reload
|
99
100
|
log 'reloading...'
|
100
|
-
load_jobs
|
101
|
+
@@queue.load_jobs
|
101
102
|
end
|
102
103
|
|
103
104
|
def stop_workers
|
@@ -105,13 +106,8 @@ class Belated
|
|
105
106
|
sleep 0.1 if worker.alive?
|
106
107
|
Thread.kill(worker)
|
107
108
|
end
|
108
|
-
|
109
|
-
|
110
|
-
next if (klass = @@queue.pop).instance_of?(Proc)
|
111
|
-
|
112
|
-
class_array << klass
|
113
|
-
end
|
114
|
-
pp File.open(FILE_NAME, 'wb') { |f| f.write(YAML.dump(class_array)) }
|
109
|
+
@@queue.save_jobs
|
110
|
+
exit unless $TESTING
|
115
111
|
end
|
116
112
|
|
117
113
|
def banner
|
data/lib/belated/client.rb
CHANGED
@@ -1,16 +1,41 @@
|
|
1
1
|
class Belated
|
2
|
+
# The client class is responsible for managing the connection to the
|
3
|
+
# DRb server. If it has no connection, it adds the jobs to a bank queue.
|
4
|
+
# You can enqueue jobs to be processed by the server.
|
5
|
+
# Example:
|
6
|
+
# client = Belated::Client.new
|
7
|
+
# client.enqueue(JubJub.new, at: Time.now + 5.seconds)
|
2
8
|
class Client
|
3
|
-
attr_accessor :queue
|
9
|
+
attr_accessor :queue, :bank, :banker_thread
|
4
10
|
|
11
|
+
# Starts up the client.
|
12
|
+
# Connects to the queue through DRb.
|
13
|
+
# @return [void]
|
5
14
|
def initialize
|
6
15
|
server_uri = Belated::URI
|
7
16
|
# @bank =
|
8
17
|
DRb.start_service
|
18
|
+
self.bank = Thread::Queue.new
|
9
19
|
self.queue = DRbObject.new_with_uri(server_uri)
|
20
|
+
self.banker_thread = Thread.new do
|
21
|
+
loop do
|
22
|
+
sleep 0.05
|
23
|
+
next unless (job, at = bank.pop)
|
24
|
+
|
25
|
+
perform(job, at: at)
|
26
|
+
end
|
27
|
+
end
|
10
28
|
end
|
11
29
|
|
12
|
-
|
13
|
-
|
30
|
+
# The method that pushes the jobs to the queue.
|
31
|
+
# If there is no connection, it pushes the job to the bank.
|
32
|
+
# @param job [Object] - The the job to be pushed.
|
33
|
+
# @param at [Date] - The time at which the job should be executed.
|
34
|
+
# @return [Object] - The job that was pushed.
|
35
|
+
def perform(job, at: nil)
|
36
|
+
queue.push(job, at: at)
|
37
|
+
rescue DRb::DRbConnError
|
38
|
+
bank.push([job, at])
|
14
39
|
end
|
15
40
|
alias perform_belated perform
|
16
41
|
alias perform_later perform
|
data/lib/belated/job.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Job = Struct.new(:klass, :at)
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'belated/job'
|
4
|
+
require 'belated/logging'
|
5
|
+
class Belated
|
6
|
+
class Queue
|
7
|
+
include Logging
|
8
|
+
attr_accessor :future_jobs
|
9
|
+
|
10
|
+
FILE_NAME = 'belated_dump'
|
11
|
+
|
12
|
+
def initialize(queue: Thread::Queue.new, future_jobs: [])
|
13
|
+
@queue = queue
|
14
|
+
self.future_jobs = future_jobs
|
15
|
+
end
|
16
|
+
|
17
|
+
def push(job, at: nil)
|
18
|
+
if at.nil?
|
19
|
+
@queue.push(job)
|
20
|
+
else
|
21
|
+
@future_jobs << Job.new(job, at)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def pop
|
26
|
+
@queue.pop
|
27
|
+
end
|
28
|
+
|
29
|
+
def clear
|
30
|
+
@queue.clear
|
31
|
+
self.future_jobs = []
|
32
|
+
end
|
33
|
+
|
34
|
+
def empty?
|
35
|
+
@queue.empty?
|
36
|
+
end
|
37
|
+
|
38
|
+
def length
|
39
|
+
@queue.length
|
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
|
78
|
+
end
|
79
|
+
end
|
data/lib/belated/version.rb
CHANGED
data/lib/belated/worker.rb
CHANGED
@@ -1,22 +1,24 @@
|
|
1
1
|
require_relative 'logging'
|
2
2
|
class Belated
|
3
3
|
# The worker class that actually gets the jobs from the queue
|
4
|
-
# and calls them. Expects the jobs to be procs
|
4
|
+
# and calls them. Expects the jobs to be procs or
|
5
|
+
# classes that have a perform method.
|
5
6
|
class Worker
|
6
7
|
include Logging
|
7
8
|
|
8
|
-
def initialize
|
9
|
+
def initialize(number: 1)
|
10
|
+
@number = number
|
9
11
|
start_working
|
10
12
|
end
|
11
13
|
|
12
14
|
def start_working
|
13
15
|
loop do
|
16
|
+
log "Worker #{@number} fetching jobs!"
|
14
17
|
next unless (job = Belated.fetch_job)
|
15
18
|
|
16
19
|
break if job == :shutdown
|
17
20
|
|
18
21
|
log call_job(job)
|
19
|
-
log 'fetching jobs...'
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
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.4.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-
|
11
|
+
date: 2021-08-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: drb
|
@@ -80,7 +80,9 @@ files:
|
|
80
80
|
- bin/setup
|
81
81
|
- lib/belated.rb
|
82
82
|
- lib/belated/client.rb
|
83
|
+
- lib/belated/job.rb
|
83
84
|
- lib/belated/logging.rb
|
85
|
+
- lib/belated/queue.rb
|
84
86
|
- lib/belated/rails.rb
|
85
87
|
- lib/belated/version.rb
|
86
88
|
- lib/belated/worker.rb
|