disqualified 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/models/disqualified/record.rb +41 -9
- data/app/models/disqualified/sequence_record.rb +3 -0
- data/lib/disqualified/error.rb +3 -0
- data/lib/disqualified/job.rb +11 -3
- data/lib/disqualified/main.rb +13 -20
- data/lib/disqualified/sequence.rb +21 -0
- data/lib/disqualified/version.rb +1 -1
- data/lib/disqualified.rb +1 -0
- data/lib/generators/disqualified/install/USAGE +2 -0
- data/lib/generators/disqualified/install/install_generator.rb +13 -1
- data/lib/generators/disqualified/install/templates/20241119023328_create_disqualified_sequences.rb +17 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbe745886eb9d17ecb6537e23724c48423523695e7c3c1243e166116710d99c0
|
4
|
+
data.tar.gz: f4f9f74ec95f4d3f1f3a8cd2a95907b7d247708676b9c7134c88026813bb7363
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b2d18b8f154938fcb9a6231aa9ba4edd544b06d9a78dba0f7e1def10b12c597d2258f60a5fd7e7ad9704700dab1f3584c96d94a732a26cceba8f4989166d5a7
|
7
|
+
data.tar.gz: 5c648be8f80189afadc35f90a9e6f3c713550626dfc8744629a3867e8b989552c8455f449fef530c9aa13bbeea4be4acbc9654f36a765b48767051af0e731cbb
|
@@ -1,7 +1,18 @@
|
|
1
1
|
class Disqualified::Record < Disqualified::BaseRecord
|
2
2
|
self.table_name = "disqualified_jobs"
|
3
3
|
|
4
|
-
|
4
|
+
belongs_to :disqualified_sequence,
|
5
|
+
class_name: "Disqualified::SequenceRecord",
|
6
|
+
foreign_key: "sequence_uuid",
|
7
|
+
primary_key: "uuid",
|
8
|
+
optional: true
|
9
|
+
|
10
|
+
scope :with_sequence, -> {
|
11
|
+
joins("LEFT OUTER JOIN disqualified_sequences ds ON ds.uuid = sequence_uuid AND ds.current_step = sequence_step")
|
12
|
+
.where("ds.uuid = sequence_uuid OR (ds.uuid IS NULL AND sequence_uuid IS NULL)")
|
13
|
+
}
|
14
|
+
scope :pending, -> { where(finished_at: nil, run_at: (..Time.now), locked_by: nil) }
|
15
|
+
scope :runnable, -> { with_sequence.pending }
|
5
16
|
|
6
17
|
def self.claim_one!(id: nil)
|
7
18
|
run_id = SecureRandom.uuid
|
@@ -22,31 +33,52 @@ class Disqualified::Record < Disqualified::BaseRecord
|
|
22
33
|
attempts: Arel.sql("attempts + 1")
|
23
34
|
)
|
24
35
|
|
25
|
-
raise
|
36
|
+
raise Disqualified::Error::NoClaimableJob if claimed_count == 0
|
26
37
|
|
27
38
|
Disqualified::Record.find_by!(locked_by: run_id)
|
39
|
+
rescue ActiveRecord::RecordNotFound
|
40
|
+
raise Disqualified::Error::NoClaimableJob
|
28
41
|
end
|
29
42
|
|
30
43
|
def run!
|
31
44
|
record = self.class.claim_one!(id:)
|
32
|
-
|
33
|
-
|
45
|
+
begin
|
46
|
+
record.send(:instantiate_handler_and_perform_with_args)
|
47
|
+
rescue => e
|
48
|
+
record.unclaim
|
49
|
+
raise e
|
50
|
+
else
|
51
|
+
record.finish
|
52
|
+
end
|
34
53
|
record
|
35
54
|
end
|
36
55
|
|
37
56
|
def finish
|
38
|
-
|
57
|
+
transaction do
|
58
|
+
update!(locked_by: nil, locked_at: nil, finished_at: Time.now)
|
59
|
+
if sequence_uuid && sequence_step
|
60
|
+
Disqualified::SequenceRecord
|
61
|
+
.where(uuid: sequence_uuid, current_step: sequence_step)
|
62
|
+
.update_all(
|
63
|
+
current_step: sequence_step + 1,
|
64
|
+
updated_at: Time.now
|
65
|
+
)
|
66
|
+
end
|
67
|
+
end
|
39
68
|
end
|
40
69
|
|
41
70
|
def requeue
|
42
71
|
retry_count = attempts - 1
|
43
72
|
sleep = (retry_count**4) + 15 + (rand(10) * (retry_count + 1))
|
44
|
-
|
73
|
+
unclaim(next_run_at: Time.now + sleep)
|
45
74
|
end
|
46
75
|
|
47
|
-
def
|
48
|
-
|
49
|
-
|
76
|
+
def unclaim(next_run_at: nil)
|
77
|
+
if next_run_at
|
78
|
+
update!(locked_by: nil, locked_at: nil, run_at: next_run_at)
|
79
|
+
else
|
80
|
+
update!(locked_by: nil, locked_at: nil)
|
81
|
+
end
|
50
82
|
end
|
51
83
|
|
52
84
|
private def instantiate_handler_and_perform_with_args
|
data/lib/disqualified/error.rb
CHANGED
data/lib/disqualified/job.rb
CHANGED
@@ -1,11 +1,19 @@
|
|
1
1
|
module Disqualified::Job
|
2
2
|
module ClassMethods
|
3
3
|
def perform_at(the_time, *args)
|
4
|
+
if Thread.current[Disqualified::Sequence::UUID]
|
5
|
+
Thread.current[Disqualified::Sequence::COUNT] += 1
|
6
|
+
sequence_uuid = Thread.current[Disqualified::Sequence::UUID]
|
7
|
+
sequence_step = Thread.current[Disqualified::Sequence::COUNT]
|
8
|
+
end
|
9
|
+
|
4
10
|
Disqualified::Record.create!(
|
5
11
|
handler: name,
|
6
12
|
arguments: JSON.dump(args),
|
7
13
|
queue: "default",
|
8
|
-
run_at: the_time
|
14
|
+
run_at: the_time,
|
15
|
+
sequence_uuid:,
|
16
|
+
sequence_step:
|
9
17
|
)
|
10
18
|
end
|
11
19
|
|
@@ -18,7 +26,7 @@ module Disqualified::Job
|
|
18
26
|
end
|
19
27
|
end
|
20
28
|
|
21
|
-
def self.included(
|
22
|
-
|
29
|
+
def self.included(other)
|
30
|
+
other.extend(ClassMethods)
|
23
31
|
end
|
24
32
|
end
|
data/lib/disqualified/main.rb
CHANGED
@@ -8,28 +8,21 @@ class Disqualified::Main
|
|
8
8
|
|
9
9
|
def call
|
10
10
|
Rails.application.reloader.wrap do
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
18
|
-
next
|
11
|
+
record = Disqualified::Record.claim_one!
|
12
|
+
run_id = record.locked_by
|
13
|
+
record.send(:instantiate_handler_and_perform_with_args)
|
14
|
+
record.finish
|
15
|
+
@logger.info do
|
16
|
+
format_log("Disqualified::Main#call", "Runner #{run_id}", "Done")
|
19
17
|
end
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
record.finish
|
24
|
-
|
25
|
-
@logger.info do
|
26
|
-
format_log("Disqualified::Main#call", "Runner #{run_id}", "Done")
|
27
|
-
end
|
28
|
-
rescue => e
|
29
|
-
handle_error(@error_hooks, e, {record: record.attributes})
|
30
|
-
@logger.error { format_log("Disqualified::Main#run", "Runner #{run_id}", "Rescued Record ##{record.id}") }
|
31
|
-
record.requeue
|
18
|
+
rescue Disqualified::Error::NoClaimableJob
|
19
|
+
@logger.warn do
|
20
|
+
format_log("Disqualified::Main#call", "No claimable jobs")
|
32
21
|
end
|
22
|
+
rescue => e
|
23
|
+
handle_error(@error_hooks, e, {record: record.attributes})
|
24
|
+
@logger.error { format_log("Disqualified::Main#run", "Runner #{run_id}", "Rescued Record ##{record.id}") }
|
25
|
+
record.requeue
|
33
26
|
end
|
34
27
|
end
|
35
28
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class Disqualified::Sequence
|
2
|
+
UUID = :disqualified_sequence_uuid
|
3
|
+
COUNT = :disqualified_sequence_count
|
4
|
+
|
5
|
+
def self.queue(description: nil, &block)
|
6
|
+
Disqualified::SequenceRecord.transaction do
|
7
|
+
Thread.current[UUID] = SecureRandom.uuid
|
8
|
+
Thread.current[COUNT] = 0
|
9
|
+
yield
|
10
|
+
Disqualified::SequenceRecord.create!(
|
11
|
+
uuid: Thread.current[UUID],
|
12
|
+
current_step: 1,
|
13
|
+
final_step: Thread.current[COUNT],
|
14
|
+
description:
|
15
|
+
)
|
16
|
+
end
|
17
|
+
ensure
|
18
|
+
Thread.current[UUID] = nil
|
19
|
+
Thread.current[COUNT] = nil
|
20
|
+
end
|
21
|
+
end
|
data/lib/disqualified/version.rb
CHANGED
data/lib/disqualified.rb
CHANGED
@@ -1,8 +1,20 @@
|
|
1
|
+
require "rails/generators/active_record"
|
2
|
+
|
1
3
|
class Disqualified::InstallGenerator < Rails::Generators::Base
|
4
|
+
include ActiveRecord::Generators::Migration
|
5
|
+
|
2
6
|
source_root File.expand_path("templates", __dir__)
|
3
7
|
|
8
|
+
class_option :database,
|
9
|
+
type: :string,
|
10
|
+
aliases: %i[--db],
|
11
|
+
desc: "The database for your migration. By default, the current environment's primary database is used."
|
12
|
+
|
4
13
|
def copy_migration_file
|
5
14
|
basename = "20220703062536_create_disqualified_jobs.rb"
|
6
|
-
copy_file
|
15
|
+
copy_file(basename, File.join(db_migrate_path, basename))
|
16
|
+
|
17
|
+
basename = "20241119023328_create_disqualified_sequences.rb"
|
18
|
+
copy_file(basename, File.join(db_migrate_path, basename))
|
7
19
|
end
|
8
20
|
end
|
data/lib/generators/disqualified/install/templates/20241119023328_create_disqualified_sequences.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
class CreateDisqualifiedSequences < ActiveRecord::Migration[7.2]
|
2
|
+
def change
|
3
|
+
create_table :disqualified_sequences do |t|
|
4
|
+
t.text :uuid, null: false
|
5
|
+
t.integer :current_step, null: false
|
6
|
+
t.integer :final_step, null: false
|
7
|
+
t.text :description
|
8
|
+
t.timestamps
|
9
|
+
|
10
|
+
t.index :uuid, unique: true
|
11
|
+
end
|
12
|
+
|
13
|
+
add_column :disqualified_jobs, :sequence_uuid, :text
|
14
|
+
add_column :disqualified_jobs, :sequence_step, :integer
|
15
|
+
add_index :disqualified_jobs, [:sequence_uuid, :sequence_step], unique: true
|
16
|
+
end
|
17
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: disqualified
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zach Ahn
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -50,6 +50,7 @@ files:
|
|
50
50
|
- README.md
|
51
51
|
- app/models/disqualified/base_record.rb
|
52
52
|
- app/models/disqualified/record.rb
|
53
|
+
- app/models/disqualified/sequence_record.rb
|
53
54
|
- disqualified.gemspec
|
54
55
|
- exe/disqualified
|
55
56
|
- lib/disqualified.rb
|
@@ -63,10 +64,12 @@ files:
|
|
63
64
|
- lib/disqualified/logging.rb
|
64
65
|
- lib/disqualified/main.rb
|
65
66
|
- lib/disqualified/pool.rb
|
67
|
+
- lib/disqualified/sequence.rb
|
66
68
|
- lib/disqualified/version.rb
|
67
69
|
- lib/generators/disqualified/install/USAGE
|
68
70
|
- lib/generators/disqualified/install/install_generator.rb
|
69
71
|
- lib/generators/disqualified/install/templates/20220703062536_create_disqualified_jobs.rb
|
72
|
+
- lib/generators/disqualified/install/templates/20241119023328_create_disqualified_sequences.rb
|
70
73
|
homepage: https://github.com/zachahn/disqualified
|
71
74
|
licenses:
|
72
75
|
- LGPL-3.0-only
|