belated 0.6.0 → 0.6.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: 4ca7f7d0a3a78ca41e6ba3afed7630e1ac72d4a88c4fdea08604066518c843a6
4
- data.tar.gz: 2fb05c90501681f9f45ab4476cbdc4c1ac88de9addafaa1c54da0a16731426df
3
+ metadata.gz: 535f6d7f0af3565867c6f621fb328966d35ff524e38ffc22813e4410fd66eb2f
4
+ data.tar.gz: ace8cc58b9519d07e7bce2f12c5b1e45eba570f75a0a5f34b0496a5acfac679d
5
5
  SHA512:
6
- metadata.gz: 5182420208c866b37511bda56cc5a2e8fddac8d87a23274923318f576b66f3d3848b33c6633296bbfed088e6bd339a458e92ccc057a63c8a815dfaf12aa3fdf7
7
- data.tar.gz: 78ef5824e2afdd45910dbe81e79e54986dcc2c7ccf346515228c978a55c5d2aa0d0f29c4d894e219667ee6d6b735fbef43c94b61bd36d645a3e9ca1152bf6a86
6
+ metadata.gz: '058ed5f47971a9f39d7ec39997f23bdfeb54221b516ee9162330e9a0c783dc9ec6d7633ad029b7d96792e08bd317d5efced10ca2ea97b0e8322507a6e5f9a045'
7
+ data.tar.gz: c5ef2e3ad64ecda5e1fa2cb0feab2dda1b50388a523e571fe3be829af76e864973429bb95d0433353dd5a58bf97f2f366d19bd19a7ae0d6d578030646156f542
data/.rubocop.yml CHANGED
@@ -37,6 +37,9 @@ Style/BlockDelimiters:
37
37
  Style/ModuleFunction:
38
38
  EnforcedStyle: extend_self
39
39
 
40
+ Metrics/AbcSize:
41
+ Max: 17
42
+
40
43
  Metrics/BlockLength:
41
44
  Exclude:
42
45
  - 'spec/**/*.rb'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.6.4] - 2021-08-22
4
+ - Inline jobs for testing!
5
+ ```ruby
6
+ `belated/testing`
7
+ Belated::Testing.inline!
8
+ ```
9
+ - Very much inspired by how Sidekiq is doing this.
10
+ - Read more in the testing part of README.md
11
+
12
+ ## [0.6.3] - 2021-08-21
13
+
14
+ - Needed to have the hash inside the mutex when going over it; otherwise you still the get can't add key into hash during iteration error. Of course.
15
+
16
+ ## [0.6.2] - 2021-08-20
17
+
18
+ - Use a mutex for the proc_table used by the client. Fixes
19
+ `RuntimeError: can't add a new key into hash during iteration (Most recent call first)`, so starting improving thread safety with this fix.
20
+
21
+ ## [0.6.1] - 2021-08-20
22
+
23
+ When the client closes and worker has a reference to a proc, a `DRb::ConnError` is raised. Rescueing it and ignoring it.
3
24
  ## [0.6.0] - 2021-08-19
4
25
 
5
26
  - Only need to keep references on the client side for procs. Not needed for classes, as they are pass-by-value. However, you can only pass procs by reference, so need to keep track of them. They're removed from the client side when they're completed though.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- belated (0.6.0)
4
+ belated (0.6.4)
5
5
  drb
6
6
  dry-configurable
7
7
  sorted_set
data/README.md CHANGED
@@ -14,15 +14,14 @@ Note that currently the timezone is hardcoded to UTC.
14
14
 
15
15
  Can be used with or without Rails.
16
16
 
17
+ Can be used if you're on a normal instance such as EC2 or Digital Ocean drop. Not if you're on a Heroku or Docker, or anything with ephemeral storage.
18
+
17
19
  TODO LIST:
18
20
 
19
- - Use GDBM for queue storage? That way could maybe get rid of YAML dumping and make things a bit safer. Not ordered though, so maybe keep a list of the jobs as YAML and update it sometimes? Just as backup.
20
- - Rescue `DRb::DRbRemoteError` when shutting down, might not need to if using GDBM?
21
- - Don't use class instance variables.
21
+ - Use GDBM for queue storage? That way could maybe get rid of YAML dumping and make things a bit safer. Not ordered though, so maybe keep a list of the jobs as YAML and update it sometimes? Just as backup. Or RocksDB? Would need to be configurable if you don't have something installed.
22
22
  - Make DRb port configurable.
23
- - Don't hardcode timezone.
23
+ - Don't hardcode timezone to UTC.
24
24
  - Add some checks to the client for proper jobs.
25
- - Have multiple queues?
26
25
  - Maybe support ActiveJob?
27
26
  - Have a web UI.
28
27
  - Have a job history
@@ -140,6 +139,22 @@ Path to Rails project.
140
139
 
141
140
  Number of workers.
142
141
 
142
+ ## Testing
143
+
144
+ When testing, you can require `belated/testing` and then call `Belated::Testing.inline!` to make your jobs perform inline.
145
+
146
+ ```ruby
147
+ `belated/testing`
148
+ c = Belated::Client.instance
149
+ c.start
150
+ c.perform(proc { 2/ 1}) # Tries to push the job to the drb backend
151
+ # <Belated::JobWrapper:0x00005654bc2db1f0 @at=nil, @completed=false, @id="95e4dc6a-1876-4adf-ae0f-5ae902f5f024", @job=#<Proc:0x00005654bc2db330 (irb):3>, @max_retries=5, @proc_klass=true, @retries=0>
152
+ Belated::Testing.inline! # Sidekiq-inspired, now jobs run inline
153
+ c.perform(proc { 2/ 1}) # Returns 2 right away
154
+ # 2
155
+ Belated::Client.test_mode_off! # Turn off inline job processing
156
+ ```
157
+
143
158
  ## Development
144
159
 
145
160
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/lib/belated.rb CHANGED
@@ -29,7 +29,7 @@ class Belated
29
29
  setting :rails_path, '.'
30
30
  setting :workers, 1
31
31
  setting :connect, true
32
- setting :environment, 'development'
32
+ setting :environment, 'development', reader: true
33
33
  setting :logger, Logger.new($stdout), reader: true
34
34
  setting :log_level, :info, reader: true
35
35
 
@@ -16,12 +16,15 @@ class Belated
16
16
  # Connects to the queue through DRb.
17
17
  # @return [void]
18
18
  def start
19
+ return if started?
20
+
19
21
  server_uri = Belated::URI
20
22
  DRb.start_service
21
23
  self.proc_table = {}
22
24
  self.bank = Thread::Queue.new
23
25
  self.queue = DRbObject.new_with_uri(server_uri)
24
26
  @started = true
27
+ @mutex = Mutex.new
25
28
  end
26
29
  alias initialize start
27
30
 
@@ -29,32 +32,41 @@ class Belated
29
32
  @started
30
33
  end
31
34
 
35
+ # Makes it possible to reset the client
36
+ def turn_off
37
+ @started = false
38
+ banker_thread&.kill
39
+ end
40
+
32
41
  # Thread in charge of handling the bank queue.
33
42
  # You probably want to memoize the client in order to avoid
34
43
  # having many threads in the sleep state.
35
44
  # @return [void]
36
45
  def start_banker_thread
37
- self.banker_thread = Thread.new do
46
+ Thread.new do
38
47
  loop do
39
48
  delete_from_table
40
- if bank.empty?
41
- sleep 10
42
- next
43
- end
44
- begin
45
- queue.push(wrapper = bank.pop)
46
- rescue DRb::DRbConnError
47
- bank.push(wrapper)
49
+ sleep 10 and next if bank.empty?
50
+
51
+ until bank.empty?
52
+ begin
53
+ queue.push(wrapper = bank.pop)
54
+ rescue DRb::DRbConnError
55
+ bank.push(wrapper)
56
+ sleep 5
57
+ end
48
58
  end
49
59
  end
50
60
  end
51
61
  end
52
62
 
53
63
  def delete_from_table
54
- return if proc_table.empty?
64
+ return if proc_table.length < 25
55
65
 
56
- proc_table.select { |_k, v| v.completed }.each do |key, _value|
57
- proc_table.delete(key)
66
+ @mutex.synchronize do
67
+ proc_table.select { |_k, v| v.completed }.each do |key, _value|
68
+ proc_table.delete(key)
69
+ end
58
70
  end
59
71
  end
60
72
 
@@ -65,16 +77,14 @@ class Belated
65
77
  # @param max_retries [Integer] - Times the job should be retried if it fails.
66
78
  # @return [JobWrapper] - The job wrapper for the queue.
67
79
  def perform(job, at: nil, max_retries: 5)
68
- log 'Passing a proc and at time is deprecated and will be removed in 0.6' if job.instance_of?(Proc) && !at.nil?
80
+ log 'Call .start on the client instance first!' unless started?
69
81
 
70
- job_wrapper = if job.is_a?(JobWrapper)
71
- job
72
- else
73
- JobWrapper.new(job: job, at: at, max_retries: max_retries)
74
- end
82
+ job_wrapper = wrap_job(job, at: at, max_retries: max_retries)
75
83
  bank.push(job_wrapper)
76
- proc_table[job_wrapper.object_id] = job_wrapper if job_wrapper.proc_klass
77
- start_banker_thread if banker_thread.nil?
84
+ @mutex.synchronize do
85
+ proc_table[job_wrapper.object_id] = job_wrapper if job_wrapper.proc_klass
86
+ end
87
+ self.banker_thread = start_banker_thread if banker_thread.nil?
78
88
  job_wrapper
79
89
  end
80
90
  alias perform_belated perform
@@ -82,6 +92,12 @@ class Belated
82
92
 
83
93
  private
84
94
 
95
+ def wrap_job(job, at:, max_retries:)
96
+ return job if job.is_a?(JobWrapper)
97
+
98
+ JobWrapper.new(job: job, at: at, max_retries: max_retries)
99
+ end
100
+
85
101
  def drb_connected?
86
102
  queue.connected?
87
103
  rescue StandardError
@@ -0,0 +1,37 @@
1
+ class Belated
2
+ # Testing helpers
3
+ # Enable or disable testing
4
+ class Testing
5
+ @@testing = false
6
+
7
+ def self.inline?
8
+ @@testing == true
9
+ end
10
+
11
+ def self.inline!
12
+ @@testing = true
13
+ end
14
+
15
+ def self.test_mode_off!
16
+ @@testing = false
17
+ end
18
+ end
19
+ end
20
+
21
+ class Belated
22
+ # A client that can perform jobs inline
23
+ class Client
24
+ alias old_perform perform
25
+ def perform(job, at: nil, max_retries: 5)
26
+ if Belated::Testing.inline?
27
+ if job.respond_to?(:call)
28
+ job.call
29
+ else
30
+ job.perform
31
+ end
32
+ else
33
+ old_perform(job, at: at, max_retries: max_retries)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Belated
4
- VERSION = '0.6.0'
4
+ VERSION = '0.6.4'
5
5
  end
@@ -20,7 +20,7 @@ class Belated
20
20
 
21
21
  log "Worker #{@number} got job: #{job.inspect}"
22
22
  log job.perform
23
- rescue Errno::ECONNREFUSED, RangeError => e
23
+ rescue DRb::DRbConnError, Errno::ECONNREFUSED, RangeError => e
24
24
  log e
25
25
  end
26
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.6.0
4
+ version: 0.6.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-19 00:00:00.000000000 Z
11
+ date: 2021-08-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: drb
@@ -99,6 +99,7 @@ files:
99
99
  - lib/belated/logging.rb
100
100
  - lib/belated/queue.rb
101
101
  - lib/belated/rails.rb
102
+ - lib/belated/testing.rb
102
103
  - lib/belated/version.rb
103
104
  - lib/belated/worker.rb
104
105
  homepage: https://github.com/sampokuokkanen/belated