belated 0.4.0 → 0.4.4

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: 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