job-iteration 1.3.1 → 1.3.5

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: 8788b6f2da0dba53c31c57d529a371e3e822091caa3654bcafc6cf25ad031adb
4
- data.tar.gz: 14cba8e6969be4d6aba0f729abd355196324f2eebd00d9b659053b7efe25117d
3
+ metadata.gz: 2d6eb941d1755c4ddb2e249e5aa50fdef6719ca173ec59643b71b4c1f724ea67
4
+ data.tar.gz: 3f75f0be9e4023c3a1f2dce9c63f311d85a72fb599b12d6b0196b3546a4db092
5
5
  SHA512:
6
- metadata.gz: 97f3d383f9eb1e82c3c68ee21bdcaf31a5df2923ebd4eb9089b7b78348f64bd69aa0da39acd0eba23cd309263931639e4e6ca702511a0d83a9528e520ff77e89
7
- data.tar.gz: beda68f91cfd51d0d78c2b0c26b20b70bc339fc25591d3ceefe825e687bdc057b448832d2abead1e80c5259eda52ef04d6b6cf83063431766ab8920dd753c396
6
+ metadata.gz: 9552d7e14685aa4aa9f69456bbc51e57d685903b2fc0752bfd2bf01f6140aa19d375000ae3c11a2f4cef8a78a5a3e87934cc542c2f719698ab539f00e6cadadd
7
+ data.tar.gz: 9fc95b241595dd1268981cd8156f8c587b71dad5cbcd7eb931fe3ee0ea723ba23521c38ddcf0658f4b4d413ed46b9c885e2dd45f2155c6477129869575390f1f
@@ -13,13 +13,18 @@ jobs:
13
13
  - 6379:6379
14
14
  strategy:
15
15
  matrix:
16
- ruby: [2.6, 2.7, 3.0]
16
+ ruby: ["2.6", "2.7", "3.0"]
17
17
  gemfile: [rails_5_2, rails_6_0, rails_edge]
18
18
  exclude:
19
- - ruby: 2.6
19
+ - ruby: "2.6"
20
20
  gemfile: rails_edge
21
- - ruby: 3.0
21
+ - ruby: "3.0"
22
22
  gemfile: rails_5_2
23
+ include:
24
+ - ruby: "3.1"
25
+ gemfile: rails_edge
26
+ - ruby: head
27
+ gemfile: rails_edge
23
28
  env:
24
29
  BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
25
30
  steps:
data/CHANGELOG.md CHANGED
@@ -1,7 +1,21 @@
1
1
  ### Master (unreleased)
2
2
 
3
+ ## v.1.3.5 (Feb 10, 2022)
4
+
5
+ - [183](https://github.com/Shopify/job-iteration/pull/183) - Add `JobIteration::EnumeratorBuilder#build_csv_enumerator`
6
+
7
+ ## v.1.3.4 (Jan 18, 2022)
8
+
9
+ - [174](https://github.com/Shopify/job-iteration/pull/174) - Fix Ruby 3.2 compatibility
10
+
11
+ ## v.1.3.3 (Nov 17, 2021)
12
+ - [153](https://github.com/Shopify/job-iteration/pull/153) - Re-enqueue jobs only after shutdown hooks have run
13
+
14
+ ## v1.3.2 (Nov 12, 2021)
15
+ - [148](https://github.com/Shopify/job-iteration/pull/148) - Revert "Do not evaluate enumerator when throttled", due to backwards incompatibility.
16
+
3
17
  ## v1.3.1 (Nov 11, 2021)
4
- - [87](https://github.com/Shopify/job-iteration/pull/87) - Do not evaluate enumerator when throttled
18
+ - [87](https://github.com/Shopify/job-iteration/pull/87) - Do not evaluate enumerator when throttled (REVERTED)
5
19
 
6
20
 
7
21
  ## v1.3.0 (Oct 7, 2021)
data/Gemfile CHANGED
@@ -11,7 +11,7 @@ gemspec
11
11
  gem "sidekiq"
12
12
  gem "resque"
13
13
 
14
- gem "mysql2", "~> 0.5"
14
+ gem "mysql2", github: "brianmario/mysql2"
15
15
  gem "globalid"
16
16
  gem "i18n"
17
17
  gem "redis"
data/Gemfile.lock CHANGED
@@ -1,21 +1,27 @@
1
+ GIT
2
+ remote: https://github.com/brianmario/mysql2
3
+ revision: 8193dc412c6a266045b9d13a9da36c16750939a4
4
+ specs:
5
+ mysql2 (0.5.3)
6
+
1
7
  PATH
2
8
  remote: .
3
9
  specs:
4
- job-iteration (1.3.1)
10
+ job-iteration (1.3.5)
5
11
  activejob (>= 5.2)
6
12
 
7
13
  GEM
8
14
  remote: https://rubygems.org/
9
15
  specs:
10
- activejob (6.1.4.1)
11
- activesupport (= 6.1.4.1)
16
+ activejob (6.1.4.4)
17
+ activesupport (= 6.1.4.4)
12
18
  globalid (>= 0.3.6)
13
- activemodel (6.1.4.1)
14
- activesupport (= 6.1.4.1)
15
- activerecord (6.1.4.1)
16
- activemodel (= 6.1.4.1)
17
- activesupport (= 6.1.4.1)
18
- activesupport (6.1.4.1)
19
+ activemodel (6.1.4.4)
20
+ activesupport (= 6.1.4.4)
21
+ activerecord (6.1.4.4)
22
+ activemodel (= 6.1.4.4)
23
+ activesupport (= 6.1.4.4)
24
+ activesupport (6.1.4.4)
19
25
  concurrent-ruby (~> 1.0, >= 1.0.2)
20
26
  i18n (>= 1.6, < 2)
21
27
  minitest (>= 5.1)
@@ -31,20 +37,19 @@ GEM
31
37
  activerecord (>= 5.a)
32
38
  database_cleaner-core (~> 2.0.0)
33
39
  database_cleaner-core (2.0.1)
34
- globalid (0.5.2)
40
+ globalid (1.0.0)
35
41
  activesupport (>= 5.0)
36
- i18n (1.8.10)
42
+ i18n (1.9.1)
37
43
  concurrent-ruby (~> 1.0)
38
44
  method_source (1.0.0)
39
- minitest (5.14.4)
45
+ minitest (5.15.0)
40
46
  mocha (1.13.0)
41
47
  mono_logger (1.1.1)
42
48
  multi_json (1.15.0)
43
49
  mustermann (1.1.1)
44
50
  ruby2_keywords (~> 0.0.1)
45
- mysql2 (0.5.3)
46
51
  parallel (1.21.0)
47
- parser (3.0.2.0)
52
+ parser (3.1.0.0)
48
53
  ast (~> 2.4.1)
49
54
  pry (0.14.1)
50
55
  coderay (~> 1.1)
@@ -52,35 +57,35 @@ GEM
52
57
  rack (2.2.3)
53
58
  rack-protection (2.1.0)
54
59
  rack
55
- rainbow (3.0.0)
60
+ rainbow (3.1.1)
56
61
  rake (13.0.6)
57
- redis (4.5.1)
62
+ redis (4.6.0)
58
63
  redis-namespace (1.8.1)
59
64
  redis (>= 3.0.4)
60
- regexp_parser (2.1.1)
61
- resque (2.1.0)
65
+ regexp_parser (2.2.0)
66
+ resque (2.2.0)
62
67
  mono_logger (~> 1.0)
63
68
  multi_json (~> 1.0)
64
69
  redis-namespace (~> 1.6)
65
70
  sinatra (>= 0.9.2)
66
71
  vegas (~> 0.1.2)
67
72
  rexml (3.2.5)
68
- rubocop (1.22.1)
73
+ rubocop (1.24.1)
69
74
  parallel (~> 1.10)
70
75
  parser (>= 3.0.0.0)
71
76
  rainbow (>= 2.2.2, < 4.0)
72
77
  regexp_parser (>= 1.8, < 3.0)
73
78
  rexml
74
- rubocop-ast (>= 1.12.0, < 2.0)
79
+ rubocop-ast (>= 1.15.1, < 2.0)
75
80
  ruby-progressbar (~> 1.7)
76
81
  unicode-display_width (>= 1.4.0, < 3.0)
77
- rubocop-ast (1.12.0)
82
+ rubocop-ast (1.15.1)
78
83
  parser (>= 3.0.1.1)
79
- rubocop-shopify (2.3.0)
80
- rubocop (~> 1.22)
84
+ rubocop-shopify (2.4.0)
85
+ rubocop (~> 1.24)
81
86
  ruby-progressbar (1.11.0)
82
87
  ruby2_keywords (0.0.5)
83
- sidekiq (6.2.2)
88
+ sidekiq (6.4.0)
84
89
  connection_pool (>= 2.2.2)
85
90
  rack (~> 2.0)
86
91
  redis (>= 4.2.0)
@@ -89,7 +94,7 @@ GEM
89
94
  rack (~> 2.2)
90
95
  rack-protection (= 2.1.0)
91
96
  tilt (~> 2.0)
92
- sorbet-runtime (0.5.9219)
97
+ sorbet-runtime (0.5.9619)
93
98
  tilt (2.0.10)
94
99
  tzinfo (2.0.4)
95
100
  concurrent-ruby (~> 1.0)
@@ -97,7 +102,7 @@ GEM
97
102
  vegas (0.1.11)
98
103
  rack (>= 1.0.0)
99
104
  yard (0.9.26)
100
- zeitwerk (2.4.2)
105
+ zeitwerk (2.5.1)
101
106
 
102
107
  PLATFORMS
103
108
  ruby
@@ -109,7 +114,7 @@ DEPENDENCIES
109
114
  i18n
110
115
  job-iteration!
111
116
  mocha
112
- mysql2 (~> 0.5)
117
+ mysql2!
113
118
  pry
114
119
  rake
115
120
  redis
@@ -120,4 +125,4 @@ DEPENDENCIES
120
125
  yard
121
126
 
122
127
  BUNDLED WITH
123
- 2.2.20
128
+ 2.3.5
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2018 Shopify
3
+ Copyright (c) 2018-present Shopify
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![CI](https://github.com/Shopify/job-iteration/actions/workflows/ci.yml/badge.svg)](https://github.com/Shopify/job-iteration/actions/workflows/ci.yml)
4
4
 
5
- Meet Iteration, an extension for [ActiveJob](https://github.com/rails/rails/tree/master/activejob) that makes your jobs interruptible and resumable, saving all progress that the job has made (aka checkpoint for jobs).
5
+ Meet Iteration, an extension for [ActiveJob](https://github.com/rails/rails/tree/main/activejob) that makes your jobs interruptible and resumable, saving all progress that the job has made (aka checkpoint for jobs).
6
6
 
7
7
  ## Background
8
8
 
@@ -123,7 +123,7 @@ class CsvJob < ApplicationJob
123
123
 
124
124
  def build_enumerator(import_id, cursor:)
125
125
  import = Import.find(import_id)
126
- JobIteration::CsvEnumerator.new(import.csv).rows(cursor: cursor)
126
+ enumerator_builder.csv(import.csv, cursor: cursor)
127
127
  end
128
128
 
129
129
  def each_iteration(csv_row)
@@ -223,4 +223,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
223
223
 
224
224
  ## Code of Conduct
225
225
 
226
- Everyone interacting in the Job::Iteration project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/Shopify/job-iteration/blob/master/CODE_OF_CONDUCT.md).
226
+ Everyone interacting in the Job::Iteration project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/Shopify/job-iteration/blob/main/CODE_OF_CONDUCT.md).
@@ -41,6 +41,14 @@ ActiveSupport::Notifications.subscribe('interrupted.iteration') do |_, _, _, _,
41
41
  tags: { job_class: tags[:job_class]&.underscore }
42
42
  )
43
43
  end
44
+
45
+ # If you're using ThrottleEnumerator
46
+ ActiveSupport::Notifications.subscribe('throttled.iteration') do |_, _, _, _, tags|
47
+ StatsD.increment(
48
+ "iteration.throttled",
49
+ tags: { job_class: tags[:job_class]&.underscore }
50
+ )
51
+ end
44
52
  ```
45
53
 
46
54
  ## Max iteration time
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
24
  spec.require_paths = ["lib"]
25
25
 
26
- spec.metadata["changelog_uri"] = "https://github.com/Shopify/job-iteration/blob/master/CHANGELOG.md"
26
+ spec.metadata["changelog_uri"] = "https://github.com/Shopify/job-iteration/blob/main/CHANGELOG.md"
27
27
  spec.metadata["allowed_push_host"] = "https://rubygems.org"
28
28
 
29
29
  spec.add_development_dependency("activerecord")
@@ -40,7 +40,7 @@ module JobIteration
40
40
  end
41
41
 
42
42
  def size
43
- (@base_relation.count + @batch_size - 1) / @batch_size # ceiling division
43
+ (@base_relation.count(:all) + @batch_size - 1) / @batch_size # ceiling division
44
44
  end
45
45
 
46
46
  private
@@ -65,7 +65,8 @@ module JobIteration
65
65
  @cursor = Array.wrap(cursor)
66
66
 
67
67
  # Yields relations by selecting the primary keys of records in the batch.
68
- # Post.where(published: nil) results in an enumerator of relations like: Post.where(ids: batch_of_ids)
68
+ # Post.where(published: nil) results in an enumerator of relations like:
69
+ # Post.where(published: nil, ids: batch_of_ids)
69
70
  @base_relation.where(@primary_key => ids)
70
71
  end
71
72
 
@@ -34,7 +34,7 @@ module JobIteration
34
34
  end
35
35
 
36
36
  def size
37
- @relation.count
37
+ @relation.count(:all)
38
38
  end
39
39
 
40
40
  private
@@ -119,12 +119,14 @@ module JobIteration
119
119
 
120
120
  # Builds Enumerator from Active Record Relation and enumerates on batches, yielding Active Record Relations.
121
121
  # See documentation for #build_active_record_enumerator_on_batches.
122
- def build_active_record_enumerator_on_batch_relations(scope, cursor:, **args)
123
- JobIteration::ActiveRecordBatchEnumerator.new(
122
+ def build_active_record_enumerator_on_batch_relations(scope, wrap: true, cursor:, **args)
123
+ enum = JobIteration::ActiveRecordBatchEnumerator.new(
124
124
  scope,
125
125
  cursor: cursor,
126
126
  **args
127
127
  ).each
128
+ enum = wrap(self, enum) if wrap
129
+ enum
128
130
  end
129
131
 
130
132
  def build_throttle_enumerator(enum, throttle_on:, backoff:)
@@ -136,6 +138,10 @@ module JobIteration
136
138
  ).to_enum
137
139
  end
138
140
 
141
+ def build_csv_enumerator(enumerable, cursor:)
142
+ CsvEnumerator.new(enumerable).rows(cursor: cursor)
143
+ end
144
+
139
145
  alias_method :once, :build_once_enumerator
140
146
  alias_method :times, :build_times_enumerator
141
147
  alias_method :array, :build_array_enumerator
@@ -143,6 +149,7 @@ module JobIteration
143
149
  alias_method :active_record_on_batches, :build_active_record_enumerator_on_batches
144
150
  alias_method :active_record_on_batch_relations, :build_active_record_enumerator_on_batch_relations
145
151
  alias_method :throttle, :build_throttle_enumerator
152
+ alias_method :csv, :build_csv_enumerator
146
153
 
147
154
  private
148
155
 
@@ -10,8 +10,14 @@ module JobIteration
10
10
  super
11
11
  end
12
12
  end
13
- # The patch is required in order to call shutdown? on a Resque::Worker instance
14
- Resque::Worker.prepend(ResqueIterationExtension)
13
+
14
+ # @private
15
+ module ::Resque
16
+ class Worker
17
+ # The patch is required in order to call shutdown? on a Resque::Worker instance
18
+ prepend(ResqueIterationExtension)
19
+ end
20
+ end
15
21
 
16
22
  JobIteration.interruption_adapter = -> { $resque_worker.try!(:shutdown?) }
17
23
  end
@@ -68,6 +68,7 @@ module JobIteration
68
68
 
69
69
  def initialize(*arguments)
70
70
  super
71
+ @needs_reenqueue = false
71
72
  self.times_interrupted = 0
72
73
  self.total_time = 0.0
73
74
  assert_implements_methods!
@@ -132,7 +133,9 @@ module JobIteration
132
133
 
133
134
  run_callbacks(:shutdown)
134
135
 
135
- if run_complete_callbacks?(completed)
136
+ if @needs_reenqueue
137
+ reenqueue_iteration_job
138
+ elsif run_complete_callbacks?(completed)
136
139
  run_callbacks(:complete)
137
140
  output_interrupt_summary
138
141
  end
@@ -141,6 +144,8 @@ module JobIteration
141
144
  def iterate_with_enumerator(enumerator, arguments)
142
145
  arguments = arguments.dup.freeze
143
146
  found_record = false
147
+ @needs_reenqueue = false
148
+
144
149
  enumerator.each do |object_from_enumerator, index|
145
150
  # Deferred until 2.0.0
146
151
  # assert_valid_cursor!(index)
@@ -153,7 +158,7 @@ module JobIteration
153
158
 
154
159
  next unless job_should_exit?
155
160
  self.executions -= 1 if executions > 1
156
- reenqueue_iteration_job
161
+ @needs_reenqueue = true
157
162
  return false
158
163
  end
159
164
 
@@ -278,7 +283,7 @@ module JobIteration
278
283
  def valid_cursor_parameter?(parameters)
279
284
  # this condition is when people use the splat operator.
280
285
  # def build_enumerator(*)
281
- return true if parameters == [[:rest]]
286
+ return true if parameters == [[:rest]] || parameters == [[:rest, :*]]
282
287
 
283
288
  parameters.each do |parameter_type, parameter_name|
284
289
  next unless parameter_name == :cursor
@@ -28,14 +28,14 @@ module JobIteration
28
28
 
29
29
  def to_enum
30
30
  Enumerator.new(-> { @enum.size }) do |yielder|
31
- loop do
31
+ @enum.each do |*val|
32
32
  if should_throttle?
33
33
  ActiveSupport::Notifications.instrument("throttled.iteration", job_class: @job.class.name)
34
34
  @job.retry_job(wait: @backoff)
35
35
  throw(:abort, :skip_complete_callbacks)
36
36
  end
37
37
 
38
- yielder.yield(*@enum.next_values)
38
+ yielder.yield(*val)
39
39
  end
40
40
  end
41
41
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JobIteration
4
- VERSION = "1.3.1"
4
+ VERSION = "1.3.5"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: job-iteration
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-11 00:00:00.000000000 Z
11
+ date: 2022-02-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -85,7 +85,7 @@ homepage: https://github.com/shopify/job-iteration
85
85
  licenses:
86
86
  - MIT
87
87
  metadata:
88
- changelog_uri: https://github.com/Shopify/job-iteration/blob/master/CHANGELOG.md
88
+ changelog_uri: https://github.com/Shopify/job-iteration/blob/main/CHANGELOG.md
89
89
  allowed_push_host: https://rubygems.org
90
90
  post_install_message:
91
91
  rdoc_options: []