chained_job 0.1.2 → 0.4.1

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: 0cf0d92c19a3955df5206dc54e7ca3883120a73fdcc1fd8743495f9c37690308
4
- data.tar.gz: '09617e3e0873985b586da6903f604e89f1d429bab84bf99e88d652d807408d08'
3
+ metadata.gz: 84c8c12fdb15c63dfa9fe2cb031382284e0eedcb2fdfad5f5af4d5dc8f01370a
4
+ data.tar.gz: 467051fa730945c836e93222c8057b9c8e2a9d635a46e550db299cc99b36f380
5
5
  SHA512:
6
- metadata.gz: 37ca1b1aa5dc58b495a0dac015b024919713ecf4a6ccfc63b252f81f1adfb9090b702e6175f3f9aaa5da85a0293e043e398226a67c684138bffceb28c819db63
7
- data.tar.gz: dbe7e4ce4dd1c92f955e62f0e0cf806df9a580fa54658960ee9889c92adb02eb30f8de3b61c57b9e652a1fff1167f86cb8c0caf613e43ca2ac07fc7b77bf2dfb
6
+ metadata.gz: b590497db0ae0fdb36f2e928da3bcb72c5c4ae7eabe5225a863d301ec27f462dda2f13c0a57f941eec07cf96b347935eed995835c67a89d3617d184516709f7a
7
+ data.tar.gz: 98146d3133f14943b3a262014e6dba6e729cc019e945af887de311e416995b5dc52f4ba8f236c0d8df941cfec208de72712b19f1ad5ff8aeb89ceba2e4dd0d6b
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'chained_job/helpers'
4
+
5
+ module ChainedJob
6
+ class CleanUpQueue
7
+ def self.run(job_class)
8
+ new(job_class).run
9
+ end
10
+
11
+ TRIM_STEP_SIZE = 1_000
12
+
13
+ attr_reader :job_class
14
+
15
+ def initialize(job_class)
16
+ @job_class = job_class
17
+ end
18
+
19
+ # rubocop:disable Metrics/AbcSize
20
+ def run
21
+ loop do
22
+ tag = ChainedJob.redis.spop(tag_list)
23
+
24
+ break unless tag
25
+
26
+ redis_key = Helpers.redis_key(job_key, tag)
27
+ size = ChainedJob.redis.llen(redis_key)
28
+ (size / TRIM_STEP_SIZE).times { ChainedJob.redis.ltrim(redis_key, 0, -TRIM_STEP_SIZE) }
29
+
30
+ ChainedJob.redis.del(redis_key)
31
+ end
32
+ end
33
+ # rubocop:enable Metrics/AbcSize
34
+
35
+ private
36
+
37
+ def tag_list
38
+ @tag_list ||= Helpers.tag_list(job_key)
39
+ end
40
+
41
+ def job_key
42
+ @job_key ||= Helpers.job_key(job_class)
43
+ end
44
+ end
45
+ end
@@ -12,9 +12,12 @@ module ChainedJob
12
12
  :arguments_queue_expiration,
13
13
  :around_start_chains,
14
14
  :around_chain_process,
15
+ :around_array_of_job_arguments,
16
+ :after_worker_finished,
15
17
  :debug,
16
18
  :logger,
17
19
  :redis,
20
+ :queue,
18
21
  )
19
22
 
20
23
  def initialize
@@ -25,6 +28,8 @@ module ChainedJob
25
28
 
26
29
  self.around_start_chains = ->(_options, &block) { block.call }
27
30
  self.around_chain_process = ->(_options, &block) { block.call }
31
+ self.around_array_of_job_arguments = ->(_options, &block) { block.call }
32
+ self.after_worker_finished = ->(_options) {}
28
33
 
29
34
  self.debug = true
30
35
  end
@@ -4,8 +4,16 @@ module ChainedJob
4
4
  module Helpers
5
5
  module_function
6
6
 
7
- def redis_key(job_class)
7
+ def job_key(job_class)
8
8
  "chained_job:#{job_class}"
9
9
  end
10
+
11
+ def redis_key(job_key, tag)
12
+ "#{job_key}:#{tag}"
13
+ end
14
+
15
+ def tag_list(prefix)
16
+ "#{prefix}:tags"
17
+ end
10
18
  end
11
19
  end
@@ -5,14 +5,23 @@ require 'chained_job/process'
5
5
 
6
6
  module ChainedJob
7
7
  module Middleware
8
- def perform(worker_id = nil)
8
+ def self.included(base)
9
+ base.queue_as ChainedJob.config.queue if ChainedJob.config.queue
10
+ end
11
+
12
+ def perform(worker_id = nil, tag = nil)
9
13
  if worker_id
10
- ChainedJob::Process.run(self, worker_id)
14
+ ChainedJob::Process.run(self, worker_id, tag)
11
15
  else
12
- ChainedJob::StartChains.run(self.class, array_of_job_arguments, parallelism)
16
+ ChainedJob::StartChains.run(self.class, arguments_array, parallelism)
13
17
  end
14
18
  end
15
19
 
20
+ def arguments_array
21
+ options = { job_class: self.class }
22
+ ChainedJob.config.around_array_of_job_arguments.call(options) { array_of_job_arguments }
23
+ end
24
+
16
25
  def array_of_job_arguments
17
26
  raise NoMethodError, 'undefined method array_of_job_arguments'
18
27
  end
@@ -4,23 +4,24 @@ require 'chained_job/helpers'
4
4
 
5
5
  module ChainedJob
6
6
  class Process
7
- def self.run(job_instance, worker_id)
8
- new(job_instance, worker_id).run
7
+ def self.run(job_instance, worker_id, job_tag)
8
+ new(job_instance, worker_id, job_tag).run
9
9
  end
10
10
 
11
- attr_reader :job_instance, :worker_id
11
+ attr_reader :job_instance, :worker_id, :job_tag
12
12
 
13
- def initialize(job_instance, worker_id)
13
+ def initialize(job_instance, worker_id, job_tag)
14
14
  @job_instance = job_instance
15
15
  @worker_id = worker_id
16
+ @job_tag = job_tag
16
17
  end
17
18
 
18
19
  def run
19
20
  with_hooks do
20
- return log_finished_worker unless argument
21
+ return finished_worker unless argument
21
22
 
22
23
  job_instance.process(argument)
23
- job_instance.class.perform_later(worker_id)
24
+ job_instance.class.perform_later(worker_id, job_tag)
24
25
  end
25
26
  end
26
27
 
@@ -31,12 +32,18 @@ module ChainedJob
31
32
  end
32
33
 
33
34
  def options
34
- { job_class: job_instance.class, worker_id: worker_id }
35
+ @options ||= { job_class: job_instance.class, worker_id: worker_id }
36
+ end
37
+
38
+ def finished_worker
39
+ log_finished_worker
40
+
41
+ ChainedJob.config.after_worker_finished&.call(options)
35
42
  end
36
43
 
37
44
  def log_finished_worker
38
45
  ChainedJob.logger.info(
39
- "#{job_instance.class} worker #{worker_id} finished"
46
+ "#{job_instance.class}:#{job_tag} worker #{worker_id} finished"
40
47
  )
41
48
  end
42
49
 
@@ -45,7 +52,11 @@ module ChainedJob
45
52
  end
46
53
 
47
54
  def redis_key
48
- Helpers.redis_key(job_instance.class)
55
+ Helpers.redis_key(job_key, job_tag)
56
+ end
57
+
58
+ def job_key
59
+ Helpers.job_key(job_instance.class)
49
60
  end
50
61
  end
51
62
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'chained_job/helpers'
4
+ require 'chained_job/clean_up_queue'
5
+ require 'chained_job/store_job_arguments'
4
6
 
5
7
  module ChainedJob
6
8
  class StartChains
@@ -16,19 +18,23 @@ module ChainedJob
16
18
  @parallelism = parallelism
17
19
  end
18
20
 
21
+ # rubocop:disable Metrics/AbcSize
19
22
  def run
20
23
  with_hooks do
21
- redis.del(redis_key)
24
+ log_chained_job_cleanup
25
+
26
+ ChainedJob::CleanUpQueue.run(job_class)
22
27
 
23
28
  next unless array_of_job_arguments.count.positive?
24
29
 
25
- store_job_arguments
30
+ ChainedJob::StoreJobArguments.run(job_class, job_tag, array_of_job_arguments)
26
31
 
27
32
  log_chained_job_start
28
33
 
29
- parallelism.times { |worked_id| job_class.perform_later(worked_id) }
34
+ parallelism.times { |worked_id| job_class.perform_later(worked_id, job_tag) }
30
35
  end
31
36
  end
37
+ # rubocop:enable Metrics/AbcSize
32
38
 
33
39
  private
34
40
 
@@ -44,31 +50,21 @@ module ChainedJob
44
50
  }
45
51
  end
46
52
 
47
- def store_job_arguments
48
- array_of_job_arguments.each_slice(config.arguments_batch_size) do |sublist|
49
- redis.rpush(redis_key, sublist)
50
- end
51
-
52
- redis.expire(redis_key, config.arguments_queue_expiration)
53
+ def job_tag
54
+ @job_tag ||= Time.now.to_f.to_s
53
55
  end
54
56
 
55
57
  def log_chained_job_start
56
58
  ChainedJob.logger.info(
57
- "#{job_class} starting #{parallelism} workers "\
59
+ "#{job_class}:#{job_tag} starting #{parallelism} workers "\
58
60
  "processing #{array_of_job_arguments.count} items"
59
61
  )
60
62
  end
61
63
 
62
- def redis
63
- ChainedJob.redis
64
- end
65
-
66
- def redis_key
67
- Helpers.redis_key(job_class)
68
- end
69
-
70
- def config
71
- ChainedJob.config
64
+ def log_chained_job_cleanup
65
+ ChainedJob.logger.info(
66
+ "#{job_class}:#{job_tag} cleanup"
67
+ )
72
68
  end
73
69
  end
74
70
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'chained_job/helpers'
4
+
5
+ module ChainedJob
6
+ class StoreJobArguments
7
+ def self.run(job_class, job_tag, array_of_job_arguments)
8
+ new(job_class, job_tag, array_of_job_arguments).run
9
+ end
10
+
11
+ attr_reader :job_class, :job_tag, :array_of_job_arguments
12
+
13
+ def initialize(job_class, job_tag, array_of_job_arguments)
14
+ @job_class = job_class
15
+ @job_tag = job_tag
16
+ @array_of_job_arguments = array_of_job_arguments
17
+ end
18
+
19
+ def run
20
+ set_tag_list
21
+
22
+ array_of_job_arguments.each_slice(config.arguments_batch_size) do |sublist|
23
+ ChainedJob.redis.rpush(redis_key, sublist)
24
+ end
25
+
26
+ ChainedJob.redis.expire(redis_key, config.arguments_queue_expiration)
27
+ end
28
+
29
+ private
30
+
31
+ def set_tag_list
32
+ ChainedJob.redis.sadd(tag_list, job_tag)
33
+ end
34
+
35
+ def tag_list
36
+ Helpers.tag_list(job_key)
37
+ end
38
+
39
+ def redis_key
40
+ @redis_key ||= Helpers.redis_key(job_key, job_tag)
41
+ end
42
+
43
+ def job_key
44
+ @job_key ||= Helpers.job_key(job_class)
45
+ end
46
+
47
+ def config
48
+ ChainedJob.config
49
+ end
50
+ end
51
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ChainedJob
4
- VERSION = '0.1.2'
4
+ VERSION = '0.4.1'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chained_job
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mantas Kūjalis
@@ -9,22 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-04-29 00:00:00.000000000 Z
12
+ date: 2021-04-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - "~>"
18
+ - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: '1.17'
20
+ version: '0'
21
21
  type: :development
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - "~>"
25
+ - - ">="
26
26
  - !ruby/object:Gem::Version
27
- version: '1.17'
27
+ version: '0'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: minitest
30
30
  requirement: !ruby/object:Gem::Requirement
@@ -53,35 +53,22 @@ dependencies:
53
53
  - - "~>"
54
54
  - !ruby/object:Gem::Version
55
55
  version: '12.0'
56
- - !ruby/object:Gem::Dependency
57
- name: rubocop-vinted
58
- requirement: !ruby/object:Gem::Requirement
59
- requirements:
60
- - - "~>"
61
- - !ruby/object:Gem::Version
62
- version: '0.3'
63
- type: :development
64
- prerelease: false
65
- version_requirements: !ruby/object:Gem::Requirement
66
- requirements:
67
- - - "~>"
68
- - !ruby/object:Gem::Version
69
- version: '0.3'
70
56
  description: Chained job allows you to define an array of queued jobs that should
71
57
  be run in sequence after the main job has been executed successfully.
72
58
  email:
73
- - mantas.kujalis@vinted.com
74
- - titas@vinted.com
59
+ - backend@vinted.com
75
60
  executables: []
76
61
  extensions: []
77
62
  extra_rdoc_files: []
78
63
  files:
79
64
  - lib/chained_job.rb
65
+ - lib/chained_job/clean_up_queue.rb
80
66
  - lib/chained_job/config.rb
81
67
  - lib/chained_job/helpers.rb
82
68
  - lib/chained_job/middleware.rb
83
69
  - lib/chained_job/process.rb
84
70
  - lib/chained_job/start_chains.rb
71
+ - lib/chained_job/store_job_arguments.rb
85
72
  - lib/chained_job/version.rb
86
73
  homepage: https://github.com/vinted/chained_job
87
74
  licenses:
@@ -102,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
89
  - !ruby/object:Gem::Version
103
90
  version: '0'
104
91
  requirements: []
105
- rubygems_version: 3.0.3
92
+ rubygems_version: 3.1.4
106
93
  signing_key:
107
94
  specification_version: 4
108
95
  summary: Chained job helper