job-iteration 1.3.1 → 1.3.5

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