inst-jobs 0.15.5 → 0.15.6

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: ec568aafa04aa958061f78e677b5db73d5053d251f18b2cd6ffc87e032c3c656
4
- data.tar.gz: e42b99cfa96f1eba59e86589ad05db68b1ae5be18c90caf2baa1ec4f878b5ff1
3
+ metadata.gz: 221663b9f3e3a49a829dd63a7f25b6eb8f558e3bdd594daf2e66e2adee996723
4
+ data.tar.gz: 14dd96fbad1a13b259761f4822e9f107537b6d16c92a9f1ceb5db0bb1f003e21
5
5
  SHA512:
6
- metadata.gz: 4d7d973fac64918cea16eb1a7b21009f39910bb87d2fb848014f6c9cf53effe439a1aa0d13cab62518f0239481e440fc92c7bc3f4246454ecb155e939517f50c
7
- data.tar.gz: 565e5474ed3825f3c2f152ed46674c0c346fbeae73c0a5ebec1d6b0041a95973ed07f348d8f8aec8484bb8525e97c5b683df13fb2fa82a8fce72071ed04d0d83
6
+ metadata.gz: 509766d3ede131621c056be6e95939d077dbdcdec2796217d4d53fdf8cb165d0e5a21a21a75b6bd3457d7de2b804b4786fa1b143377430825ddfd3a24fa2124b
7
+ data.tar.gz: eb31db5a091c2ff87e3d283a679830a0b77bbf85fc9b592ab988be7ca389e5c84a564d1ce021e7d87db9127d4f9b3885f4a17da24161d7949647e9da9a2dd480
@@ -0,0 +1,95 @@
1
+ class SpeedUpMaxConcurrentTriggers < ActiveRecord::Migration[4.2]
2
+ def connection
3
+ Delayed::Job.connection
4
+ end
5
+
6
+ def up
7
+ if connection.adapter_name == 'PostgreSQL'
8
+ # tl;dr sacrifice some responsiveness to max_concurrent changes for faster performance
9
+ # don't get the count every single time - it's usually safe to just set the next one in line
10
+ # since the max_concurrent doesn't change all that often for a strand
11
+ execute(<<-CODE)
12
+ CREATE OR REPLACE FUNCTION delayed_jobs_after_delete_row_tr_fn () RETURNS trigger AS $$
13
+ DECLARE
14
+ running_count integer;
15
+ BEGIN
16
+ IF OLD.strand IS NOT NULL THEN
17
+ PERFORM pg_advisory_xact_lock(half_md5_as_bigint(OLD.strand));
18
+ IF OLD.id % 20 = 0 THEN
19
+ running_count := (SELECT COUNT(*) FROM (
20
+ SELECT 1 as one FROM delayed_jobs WHERE strand = OLD.strand AND next_in_strand = 't' LIMIT OLD.max_concurrent
21
+ ) subquery_for_count);
22
+ IF running_count < OLD.max_concurrent THEN
23
+ UPDATE delayed_jobs SET next_in_strand = 't' WHERE id IN (
24
+ SELECT id FROM delayed_jobs j2 WHERE next_in_strand = 'f' AND
25
+ j2.strand = OLD.strand ORDER BY j2.id ASC LIMIT (OLD.max_concurrent - running_count) FOR UPDATE
26
+ );
27
+ END IF;
28
+ ELSE
29
+ UPDATE delayed_jobs SET next_in_strand = 't' WHERE id =
30
+ (SELECT id FROM delayed_jobs j2 WHERE next_in_strand = 'f' AND
31
+ j2.strand = OLD.strand ORDER BY j2.id ASC LIMIT 1 FOR UPDATE);
32
+ END IF;
33
+ END IF;
34
+ RETURN OLD;
35
+ END;
36
+ $$ LANGUAGE plpgsql;
37
+ CODE
38
+
39
+ # don't need the full count on insert
40
+ execute(<<-CODE)
41
+ CREATE OR REPLACE FUNCTION delayed_jobs_before_insert_row_tr_fn () RETURNS trigger AS $$
42
+ BEGIN
43
+ IF NEW.strand IS NOT NULL THEN
44
+ PERFORM pg_advisory_xact_lock(half_md5_as_bigint(NEW.strand));
45
+ IF (SELECT COUNT(*) FROM (
46
+ SELECT 1 AS one FROM delayed_jobs WHERE strand = NEW.strand LIMIT NEW.max_concurrent
47
+ ) subquery_for_count) = NEW.max_concurrent THEN
48
+ NEW.next_in_strand := 'f';
49
+ END IF;
50
+ END IF;
51
+ RETURN NEW;
52
+ END;
53
+ $$ LANGUAGE plpgsql;
54
+ CODE
55
+ end
56
+ end
57
+
58
+ def down
59
+ if connection.adapter_name == 'PostgreSQL'
60
+ execute(<<-CODE)
61
+ CREATE OR REPLACE FUNCTION delayed_jobs_after_delete_row_tr_fn () RETURNS trigger AS $$
62
+ DECLARE
63
+ running_count integer;
64
+ BEGIN
65
+ IF OLD.strand IS NOT NULL THEN
66
+ PERFORM pg_advisory_xact_lock(half_md5_as_bigint(OLD.strand));
67
+ running_count := (SELECT COUNT(*) FROM delayed_jobs WHERE strand = OLD.strand AND next_in_strand = 't');
68
+ IF running_count < OLD.max_concurrent THEN
69
+ UPDATE delayed_jobs SET next_in_strand = 't' WHERE id IN (
70
+ SELECT id FROM delayed_jobs j2 WHERE next_in_strand = 'f' AND
71
+ j2.strand = OLD.strand ORDER BY j2.id ASC LIMIT (OLD.max_concurrent - running_count) FOR UPDATE
72
+ );
73
+ END IF;
74
+ END IF;
75
+ RETURN OLD;
76
+ END;
77
+ $$ LANGUAGE plpgsql;
78
+ CODE
79
+
80
+ execute(<<-CODE)
81
+ CREATE OR REPLACE FUNCTION delayed_jobs_before_insert_row_tr_fn () RETURNS trigger AS $$
82
+ BEGIN
83
+ IF NEW.strand IS NOT NULL THEN
84
+ PERFORM pg_advisory_xact_lock(half_md5_as_bigint(NEW.strand));
85
+ IF (SELECT COUNT(*) FROM delayed_jobs WHERE strand = NEW.strand) >= NEW.max_concurrent THEN
86
+ NEW.next_in_strand := 'f';
87
+ END IF;
88
+ END IF;
89
+ RETURN NEW;
90
+ END;
91
+ $$ LANGUAGE plpgsql;
92
+ CODE
93
+ end
94
+ end
95
+ end
@@ -1,3 +1,3 @@
1
1
  module Delayed
2
- VERSION = "0.15.5"
2
+ VERSION = "0.15.6"
3
3
  end
@@ -32,11 +32,15 @@ module Delayed
32
32
  # prefetched jobs have their own way of automatically unlocking themselves
33
33
  next if job.locked_by.start_with?("prefetch:")
34
34
  unless live_workers.include?(job.locked_by)
35
- Delayed::Job.transaction do
36
- # double check that the job is still there. locked_by will immediately be reset
37
- # to nil in this transaction by Job#reschedule
38
- next unless Delayed::Job.where(id: job, locked_by: job.locked_by).update_all(locked_by: "abandoned job cleanup") == 1
39
- job.reschedule
35
+ begin
36
+ Delayed::Job.transaction do
37
+ # double check that the job is still there. locked_by will immediately be reset
38
+ # to nil in this transaction by Job#reschedule
39
+ next unless Delayed::Job.where(id: job, locked_by: job.locked_by).update_all(locked_by: "abandoned job cleanup") == 1
40
+ job.reschedule
41
+ end
42
+ rescue
43
+ ::Rails.logger.error "Failure rescheduling abandoned job #{job.id} #{$!.inspect}"
40
44
  end
41
45
  end
42
46
  end
@@ -208,40 +208,6 @@ describe 'Delayed::Backed::ActiveRecord::Job' do
208
208
  job3.next_in_strand.should == true
209
209
  end
210
210
  end
211
-
212
- it "should set multiple jobs as next_in_strand at once if needed" do
213
- change_setting(Delayed::Settings, :num_strands, ->(strand_name) {
214
- case strand_name
215
- when "njobs"; 2
216
- else nil
217
- end
218
- }) do
219
- job1 = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs"])
220
- job1.reload
221
- job1.next_in_strand.should == true
222
- job2 = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs"])
223
- job2.reload
224
- job2.next_in_strand.should == true
225
-
226
- job3 = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs"])
227
- job3.reload
228
- job3.next_in_strand.should == false
229
-
230
- # manually unset next_in_strand
231
- Delayed::Job.where(:id => job2).update_all(:next_in_strand => false)
232
- job2.reload
233
- job2.next_in_strand.should == false
234
-
235
- run_job(job1) # should update both jobs
236
-
237
- job3.reload
238
- job3.next_in_strand.should == true
239
-
240
- job2.reload
241
- job2.next_in_strand.should == true
242
-
243
- end
244
- end
245
211
  end
246
212
  end
247
213
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inst-jobs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.5
4
+ version: 0.15.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Luetke
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2018-11-26 00:00:00.000000000 Z
12
+ date: 2019-06-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -346,6 +346,7 @@ files:
346
346
  - db/migrate/20151123210429_add_expires_at_to_jobs.rb
347
347
  - db/migrate/20151210162949_improve_max_concurrent.rb
348
348
  - db/migrate/20161206323555_add_back_default_string_limits_jobs.rb
349
+ - db/migrate/20181217155351_speed_up_max_concurrent_triggers.rb
349
350
  - exe/inst_jobs
350
351
  - lib/delayed/backend/active_record.rb
351
352
  - lib/delayed/backend/base.rb