job-iteration 1.1.10 → 1.1.11

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: 7868f8da1aee096abee4d4a1848c2242d0a7ac9bb1b456ad8385cfe6421a902e
4
- data.tar.gz: fd82a4cdfcbff16220363e1c53aa064b0cd5e599e17290aa968fdb01d8fe4002
3
+ metadata.gz: 18324439fe7b98c7f1bca543c078ddbfdff18af5a7e97a87b21b48890e919769
4
+ data.tar.gz: 3d912ea06a5a66ee841fbd605e8dfc414bd1760c61d9edf74445e79ae16a6466
5
5
  SHA512:
6
- metadata.gz: 42a601bb25a38571c97d108a8847317892a5289e2d3f8d818b68c99a49fc6d142dffcdd9191350261a89db65bf24aa3b0691057238f2416e2a0140bf16c47485
7
- data.tar.gz: 364868992c7fe4602f31d453891f4597d73d0b7b76482510d7ae9d3d3de7baf951465c5df7fcf9923592abb05b3584a9206f104bd610ab52dbbf3625c03be3f6
6
+ metadata.gz: 622368d1208ea23014188c028f832f51f899b6bdfbca8938c6396dcca48f913679ee7f41a035c5cbe0376346ea40a583c4615bd665251cf7dc36a30aeb37904a
7
+ data.tar.gz: 51931d565cffb4600141e1e96dc9a1a6b8a522589c8b0b38dc4cd1846e8d59a9f150d0d0bfcde4aaee587478af57418093a9e313b2f17c9f2c54ffb6cf18382a
@@ -1,11 +1,11 @@
1
- name: Ruby
1
+ name: CI
2
2
 
3
3
  on: [push]
4
4
 
5
5
  jobs:
6
6
  build:
7
7
  runs-on: ubuntu-latest
8
- name: Ruby ${{ matrix.ruby }}
8
+ name: Ruby ${{ matrix.ruby }} | Gemfile ${{ matrix.gemfile }}
9
9
  services:
10
10
  redis:
11
11
  image: redis
data/CHANGELOG.md CHANGED
@@ -4,13 +4,20 @@
4
4
 
5
5
  #### Bug fix
6
6
 
7
+
8
+ ## v1.1.11 (April 19, 2021)
9
+
10
+ #### Bug fix
11
+
12
+ - [73](https://github.com/Shopify/job-iteration/pull/73) - Enforce cursor be serializable
13
+
7
14
  ## v1.1.10 (March 30, 2021)
8
15
 
9
- - [69](https://github.com/Shopify/job-iteration/pull/69) Fix memory leak in ActiveRecordCursor
16
+ - [69](https://github.com/Shopify/job-iteration/pull/69) - Fix memory leak in ActiveRecordCursor
10
17
 
11
18
  ## v1.1.9 (January 6, 2021)
12
19
 
13
- - [61](https://github.com/Shopify/job-iteration/pull/61) Call `super` in `method_added`
20
+ - [61](https://github.com/Shopify/job-iteration/pull/61) - Call `super` in `method_added`
14
21
 
15
22
  ## v1.1.8 (June 8, 2020)
16
23
 
@@ -6,6 +6,28 @@ module JobIteration
6
6
  module Iteration
7
7
  extend ActiveSupport::Concern
8
8
 
9
+ class CursorError < ArgumentError
10
+ attr_reader :cursor
11
+
12
+ def initialize(message, cursor:)
13
+ super(message)
14
+ @cursor = cursor
15
+ end
16
+
17
+ def message
18
+ "#{super} (#{inspected_cursor})"
19
+ end
20
+
21
+ private
22
+
23
+ def inspected_cursor
24
+ cursor.inspect
25
+ rescue NoMethodError
26
+ # For those brave enough to try to use BasicObject as cursor. Nice try.
27
+ Object.instance_method(:inspect).bind(cursor).call
28
+ end
29
+ end
30
+
9
31
  included do |_base|
10
32
  attr_accessor(
11
33
  :cursor_position,
@@ -120,6 +142,8 @@ module JobIteration
120
142
  arguments = arguments.dup.freeze
121
143
  found_record = false
122
144
  enumerator.each do |object_from_enumerator, index|
145
+ assert_valid_cursor!(index)
146
+
123
147
  record_unit_of_work do
124
148
  found_record = true
125
149
  each_iteration(object_from_enumerator, *arguments)
@@ -176,6 +200,18 @@ module JobIteration
176
200
  EOS
177
201
  end
178
202
 
203
+ # The adapter must be able to serialize and deserialize the cursor back into an equivalent object.
204
+ # https://github.com/mperham/sidekiq/wiki/Best-Practices#1-make-your-job-parameters-small-and-simple
205
+ def assert_valid_cursor!(cursor)
206
+ return if serializable?(cursor)
207
+
208
+ raise CursorError.new(
209
+ "Cursor must be composed of objects capable of built-in (de)serialization: " \
210
+ "Strings, Integers, Floats, Arrays, Hashes, true, false, or nil.",
211
+ cursor: cursor,
212
+ )
213
+ end
214
+
179
215
  def assert_implements_methods!
180
216
  unless respond_to?(:each_iteration, true)
181
217
  raise(
@@ -251,5 +287,21 @@ module JobIteration
251
287
  end
252
288
  false
253
289
  end
290
+
291
+ SIMPLE_SERIALIZABLE_CLASSES = [String, Integer, Float, NilClass, TrueClass, FalseClass].freeze
292
+ private_constant :SIMPLE_SERIALIZABLE_CLASSES
293
+ def serializable?(object)
294
+ # Subclasses must be excluded, hence not using is_a? or ===.
295
+ if object.instance_of?(Array)
296
+ object.all? { |element| serializable?(element) }
297
+ elsif object.instance_of?(Hash)
298
+ object.all? { |key, value| serializable?(key) && serializable?(value) }
299
+ else
300
+ SIMPLE_SERIALIZABLE_CLASSES.any? { |klass| object.instance_of?(klass) }
301
+ end
302
+ rescue NoMethodError
303
+ # BasicObject doesn't respond to instance_of, but we can't serialize it anyway
304
+ false
305
+ end
254
306
  end
255
307
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JobIteration
4
- VERSION = "1.1.10"
4
+ VERSION = "1.1.11"
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.1.10
4
+ version: 1.1.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-30 00:00:00.000000000 Z
11
+ date: 2021-04-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -45,7 +45,7 @@ executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
47
47
  files:
48
- - ".github/workflows/ruby.yml"
48
+ - ".github/workflows/ci.yml"
49
49
  - ".gitignore"
50
50
  - ".rubocop.yml"
51
51
  - ".yardopts"