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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3264ca317aa687386cf4f87b45a358b25197e0a8442d79c28116abbdf373cd5c
4
- data.tar.gz: fc520d4de51b80b7ec87622f7ef66fd17a60423800a72a402fde7f7361e52a2e
3
+ metadata.gz: b946c5167a28af0cd73bad436d52c47ad19af699d88bd8a20c592b8fb2327ea1
4
+ data.tar.gz: da03cfda6b0c4ec8b9a9a7ef4cb52747294f3b582633ad023cc98aa5e88c697f
5
5
  SHA512:
6
- metadata.gz: 5512108388bf979973d471f9107b8f11f1af79320029324053ca748eeac3940635efdbff744410305e185e781de6732fa003ca7251d5d26be1c706e59818f960
7
- data.tar.gz: 25045c09fbd423b0169cc4eda7a01a4cbf1e93c6a3ee13d0b574f24fabfd3fae9a58768eb6bef962b8613536c3585fb542e02151950eda82d6867c34a0d6e85f
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- belated (0.4.0)
4
+ belated (0.4.4)
5
5
  drb
6
6
  dry-configurable
7
7
 
data/README.md CHANGED
@@ -2,33 +2,28 @@
2
2
 
3
3
  [![CodeFactor](https://www.codefactor.io/repository/github/sampokuokkanen/belated/badge)](https://www.codefactor.io/repository/github/sampokuokkanen/belated) [![Gem Version](https://badge.fury.io/rb/belated.svg)](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
- - Catch SIGTERM and friends
14
- - Now supports it, partly.
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
- require_relative 'belated/logging'
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 'belated/queue'
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
- sleep 0.1 until @@queue.empty? || $TESTING
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
- class_array = []
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
 
@@ -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
- require 'belated/job'
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Belated
4
- VERSION = '0.4.0'
4
+ VERSION = '0.4.4'
5
5
  end
@@ -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 StandardError => e
32
- e.inspect
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.0
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-03 00:00:00.000000000 Z
11
+ date: 2021-08-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: drb