rubocop-sidekiq_plus 0.1.0
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 +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +322 -0
- data/config/default.yml +396 -0
- data/lib/rubocop/cop/sidekiq/active_record_argument.rb +77 -0
- data/lib/rubocop/cop/sidekiq/async_in_test.rb +42 -0
- data/lib/rubocop/cop/sidekiq/base.rb +14 -0
- data/lib/rubocop/cop/sidekiq/consistent_job_suffix.rb +44 -0
- data/lib/rubocop/cop/sidekiq/constant_job_class_name.rb +53 -0
- data/lib/rubocop/cop/sidekiq/database_connection_leak.rb +33 -0
- data/lib/rubocop/cop/sidekiq/date_time_argument.rb +80 -0
- data/lib/rubocop/cop/sidekiq/deprecated_default_worker_options.rb +44 -0
- data/lib/rubocop/cop/sidekiq/deprecated_delay_extension.rb +29 -0
- data/lib/rubocop/cop/sidekiq/deprecated_worker_module.rb +40 -0
- data/lib/rubocop/cop/sidekiq/enqueue_inefficiency.rb +75 -0
- data/lib/rubocop/cop/sidekiq/excessive_retry.rb +52 -0
- data/lib/rubocop/cop/sidekiq/find_each_in_job.rb +58 -0
- data/lib/rubocop/cop/sidekiq/huge_job_arguments.rb +73 -0
- data/lib/rubocop/cop/sidekiq/job_dependency.rb +30 -0
- data/lib/rubocop/cop/sidekiq/job_file_location.rb +52 -0
- data/lib/rubocop/cop/sidekiq/job_file_naming.rb +38 -0
- data/lib/rubocop/cop/sidekiq/job_include.rb +67 -0
- data/lib/rubocop/cop/sidekiq/missing_logging.rb +49 -0
- data/lib/rubocop/cop/sidekiq/missing_timeout.rb +65 -0
- data/lib/rubocop/cop/sidekiq/mixed_retry_strategies.rb +55 -0
- data/lib/rubocop/cop/sidekiq/mixin/argument_traversal.rb +28 -0
- data/lib/rubocop/cop/sidekiq/mixin/class_name_helper.rb +23 -0
- data/lib/rubocop/cop/sidekiq/mixin/processed_source_path.rb +19 -0
- data/lib/rubocop/cop/sidekiq/no_rescue_all.rb +70 -0
- data/lib/rubocop/cop/sidekiq/perform_inline_usage.rb +53 -0
- data/lib/rubocop/cop/sidekiq/perform_method_parameters.rb +53 -0
- data/lib/rubocop/cop/sidekiq/pii_in_arguments.rb +90 -0
- data/lib/rubocop/cop/sidekiq/puts_or_print_usage.rb +37 -0
- data/lib/rubocop/cop/sidekiq/queue_specified.rb +74 -0
- data/lib/rubocop/cop/sidekiq/redis_in_job.rb +32 -0
- data/lib/rubocop/cop/sidekiq/retry_specified.rb +81 -0
- data/lib/rubocop/cop/sidekiq/retry_zero.rb +48 -0
- data/lib/rubocop/cop/sidekiq/self_scheduling_job.rb +54 -0
- data/lib/rubocop/cop/sidekiq/sensitive_data_in_arguments.rb +92 -0
- data/lib/rubocop/cop/sidekiq/sidekiq_over_active_job.rb +30 -0
- data/lib/rubocop/cop/sidekiq/silent_rescue.rb +63 -0
- data/lib/rubocop/cop/sidekiq/sleep_in_jobs.rb +46 -0
- data/lib/rubocop/cop/sidekiq/symbol_argument.rb +69 -0
- data/lib/rubocop/cop/sidekiq/thread_in_job.rb +53 -0
- data/lib/rubocop/cop/sidekiq/transaction_leak.rb +72 -0
- data/lib/rubocop/cop/sidekiq/unknown_sidekiq_option.rb +52 -0
- data/lib/rubocop/cop/sidekiq_cops.rb +71 -0
- data/lib/rubocop/cop/sidekiq_ent/base.rb +43 -0
- data/lib/rubocop/cop/sidekiq_ent/encryption_with_many_arguments.rb +71 -0
- data/lib/rubocop/cop/sidekiq_ent/encryption_without_secret_bag.rb +83 -0
- data/lib/rubocop/cop/sidekiq_ent/leader_election_without_block.rb +75 -0
- data/lib/rubocop/cop/sidekiq_ent/limiter_not_reused.rb +79 -0
- data/lib/rubocop/cop/sidekiq_ent/limiter_without_lock_timeout.rb +46 -0
- data/lib/rubocop/cop/sidekiq_ent/limiter_without_wait_timeout.rb +49 -0
- data/lib/rubocop/cop/sidekiq_ent/periodic_job_invalid_cron.rb +108 -0
- data/lib/rubocop/cop/sidekiq_ent/periodic_job_with_arguments.rb +94 -0
- data/lib/rubocop/cop/sidekiq_ent/unique_job_too_short_ttl.rb +80 -0
- data/lib/rubocop/cop/sidekiq_ent/unique_job_without_ttl.rb +52 -0
- data/lib/rubocop/cop/sidekiq_ent/unique_until_mismatch.rb +59 -0
- data/lib/rubocop/cop/sidekiq_pro/base.rb +39 -0
- data/lib/rubocop/cop/sidekiq_pro/batch_callback_method.rb +66 -0
- data/lib/rubocop/cop/sidekiq_pro/batch_retry_in_callback.rb +54 -0
- data/lib/rubocop/cop/sidekiq_pro/batch_status_polling.rb +68 -0
- data/lib/rubocop/cop/sidekiq_pro/batch_without_callback.rb +92 -0
- data/lib/rubocop/cop/sidekiq_pro/empty_batch.rb +108 -0
- data/lib/rubocop/cop/sidekiq_pro/expiring_job_without_ttl.rb +101 -0
- data/lib/rubocop/cop/sidekiq_pro/large_argument_in_batch.rb +93 -0
- data/lib/rubocop/cop/sidekiq_pro/nested_batch_without_parent.rb +55 -0
- data/lib/rubocop/cop/sidekiq_pro/reliability_not_enabled.rb +67 -0
- data/lib/rubocop/sidekiq/config_formatter.rb +60 -0
- data/lib/rubocop/sidekiq/description_extractor.rb +70 -0
- data/lib/rubocop/sidekiq/language.rb +79 -0
- data/lib/rubocop/sidekiq/plugin.rb +30 -0
- data/lib/rubocop/sidekiq/version.rb +7 -0
- data/lib/rubocop/sidekiq.rb +10 -0
- data/lib/rubocop-sidekiq.rb +5 -0
- data/lib/rubocop-sidekiq_plus.rb +9 -0
- metadata +150 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module SidekiqPro
|
|
6
|
+
# Checks for large arguments passed to jobs within a batch.
|
|
7
|
+
#
|
|
8
|
+
# When using batches, passing large arguments to jobs is especially
|
|
9
|
+
# problematic because it can exhaust Redis memory when many jobs
|
|
10
|
+
# are enqueued simultaneously.
|
|
11
|
+
#
|
|
12
|
+
# @example
|
|
13
|
+
# # bad
|
|
14
|
+
# batch.jobs do
|
|
15
|
+
# items.each do |item|
|
|
16
|
+
# ProcessJob.perform_async(item.attributes)
|
|
17
|
+
# end
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# # good
|
|
21
|
+
# batch.jobs do
|
|
22
|
+
# items.each do |item|
|
|
23
|
+
# ProcessJob.perform_async(item.id)
|
|
24
|
+
# end
|
|
25
|
+
# end
|
|
26
|
+
#
|
|
27
|
+
class LargeArgumentInBatch < Base
|
|
28
|
+
MSG = 'Avoid passing large arguments to jobs within a batch. Pass IDs instead.'
|
|
29
|
+
|
|
30
|
+
DEFAULT_MAX_ARRAY_SIZE = 10
|
|
31
|
+
DEFAULT_MAX_HASH_SIZE = 10
|
|
32
|
+
|
|
33
|
+
def on_block(node)
|
|
34
|
+
batch_jobs_block?(node) do |_receiver, body|
|
|
35
|
+
check_body_for_large_arguments(body)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
alias on_numblock on_block
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def check_body_for_large_arguments(body)
|
|
44
|
+
return unless body
|
|
45
|
+
|
|
46
|
+
find_perform_calls(body).each do |call|
|
|
47
|
+
call.arguments.each do |arg|
|
|
48
|
+
add_offense(arg) if large_argument?(arg)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def find_perform_calls(node, calls = [])
|
|
54
|
+
return calls unless node.is_a?(::Parser::AST::Node)
|
|
55
|
+
|
|
56
|
+
calls << node if node.send_type? && perform_call?(node)
|
|
57
|
+
node.children.each { |child| find_perform_calls(child, calls) }
|
|
58
|
+
calls
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def large_argument?(arg)
|
|
62
|
+
large_array?(arg) || large_hash?(arg) || attributes_call?(arg)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def large_array?(arg)
|
|
66
|
+
return false unless arg.array_type?
|
|
67
|
+
|
|
68
|
+
arg.values.size > max_array_size
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def large_hash?(arg)
|
|
72
|
+
return false unless arg.hash_type?
|
|
73
|
+
|
|
74
|
+
arg.pairs.size > max_hash_size
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def attributes_call?(arg)
|
|
78
|
+
return false unless arg.send_type?
|
|
79
|
+
|
|
80
|
+
%i[attributes as_json to_h to_hash].include?(arg.method_name)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def max_array_size
|
|
84
|
+
cop_config.fetch('MaxArraySize', DEFAULT_MAX_ARRAY_SIZE)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def max_hash_size
|
|
88
|
+
cop_config.fetch('MaxHashSize', DEFAULT_MAX_HASH_SIZE)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module SidekiqPro
|
|
6
|
+
# Checks that nested batches have proper parent relationship.
|
|
7
|
+
#
|
|
8
|
+
# When creating nested batches inside a batch.jobs block,
|
|
9
|
+
# the child batch should reference the parent for proper tracking.
|
|
10
|
+
#
|
|
11
|
+
# @example
|
|
12
|
+
# # bad - nested batch without parent reference
|
|
13
|
+
# class ProcessBatchJob
|
|
14
|
+
# include Sidekiq::Job
|
|
15
|
+
#
|
|
16
|
+
# def perform
|
|
17
|
+
# batch.jobs do
|
|
18
|
+
# child_batch = Sidekiq::Batch.new
|
|
19
|
+
# child_batch.jobs do
|
|
20
|
+
# SomeJob.perform_async
|
|
21
|
+
# end
|
|
22
|
+
# end
|
|
23
|
+
# end
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# # good - explicit parent reference
|
|
27
|
+
# class ProcessBatchJob
|
|
28
|
+
# include Sidekiq::Job
|
|
29
|
+
#
|
|
30
|
+
# def perform
|
|
31
|
+
# parent_batch = batch
|
|
32
|
+
# parent_batch.jobs do
|
|
33
|
+
# child_batch = Sidekiq::Batch.new(parent_batch.bid)
|
|
34
|
+
# child_batch.jobs do
|
|
35
|
+
# SomeJob.perform_async
|
|
36
|
+
# end
|
|
37
|
+
# end
|
|
38
|
+
# end
|
|
39
|
+
# end
|
|
40
|
+
#
|
|
41
|
+
class NestedBatchWithoutParent < Base
|
|
42
|
+
MSG = 'Nested batch should reference parent batch for proper tracking.'
|
|
43
|
+
|
|
44
|
+
def on_block(node)
|
|
45
|
+
return unless batch_jobs_block?(node)
|
|
46
|
+
|
|
47
|
+
node.body&.each_descendant(:send) do |send_node|
|
|
48
|
+
add_offense(send_node) if batch_new?(send_node) && send_node.arguments.empty?
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
alias on_numblock on_block
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module SidekiqPro
|
|
6
|
+
# Checks that Sidekiq Pro reliability features are enabled.
|
|
7
|
+
#
|
|
8
|
+
# Sidekiq Pro provides `super_fetch!` and `reliable_push!` for
|
|
9
|
+
# improved job reliability. These should be enabled in production.
|
|
10
|
+
#
|
|
11
|
+
# @example
|
|
12
|
+
# # bad - reliability features not enabled
|
|
13
|
+
# Sidekiq.configure_server do |config|
|
|
14
|
+
# config.redis = { url: ENV['REDIS_URL'] }
|
|
15
|
+
# end
|
|
16
|
+
#
|
|
17
|
+
# # good - reliability features enabled
|
|
18
|
+
# Sidekiq.configure_server do |config|
|
|
19
|
+
# config.redis = { url: ENV['REDIS_URL'] }
|
|
20
|
+
# config.super_fetch!
|
|
21
|
+
# config.reliable_push!
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
class ReliabilityNotEnabled < Base
|
|
25
|
+
MSG_SUPER_FETCH = 'Consider enabling `super_fetch!` for reliable job fetching.'
|
|
26
|
+
MSG_RELIABLE_PUSH = 'Consider enabling `reliable_push!` for reliable job pushing.'
|
|
27
|
+
|
|
28
|
+
# @!method configure_server_block?(node)
|
|
29
|
+
def_node_matcher :configure_server_block?, <<~PATTERN
|
|
30
|
+
(block
|
|
31
|
+
(send (const {nil? cbase} :Sidekiq) :configure_server)
|
|
32
|
+
(args (arg $_))
|
|
33
|
+
$_
|
|
34
|
+
)
|
|
35
|
+
PATTERN
|
|
36
|
+
|
|
37
|
+
def on_block(node)
|
|
38
|
+
configure_server_block?(node) do |config_var, body|
|
|
39
|
+
return unless body
|
|
40
|
+
|
|
41
|
+
check_reliability_features(node, config_var, body)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
alias on_numblock on_block
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def check_reliability_features(node, config_var, body)
|
|
49
|
+
has_super_fetch = method_call?(body, config_var, :super_fetch!)
|
|
50
|
+
has_reliable_push = method_call?(body, config_var, :reliable_push!)
|
|
51
|
+
|
|
52
|
+
add_offense(node.send_node, message: MSG_SUPER_FETCH) unless has_super_fetch
|
|
53
|
+
add_offense(node.send_node, message: MSG_RELIABLE_PUSH) unless has_reliable_push
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def method_call?(body, config_var, method_name)
|
|
57
|
+
nodes_to_check = body.send_type? ? [body] : body.each_descendant(:send).to_a
|
|
58
|
+
nodes_to_check.any? do |send_node|
|
|
59
|
+
send_node.method?(method_name) &&
|
|
60
|
+
send_node.receiver&.lvar_type? &&
|
|
61
|
+
send_node.receiver.children.first == config_var
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yaml'
|
|
4
|
+
|
|
5
|
+
module RuboCop
|
|
6
|
+
module Sidekiq
|
|
7
|
+
# Builds a YAML config file from two config hashes
|
|
8
|
+
class ConfigFormatter
|
|
9
|
+
EXTENSION_ROOT_DEPARTMENT = %r{^(Sidekiq(?:Pro|Ent)?/)}.freeze
|
|
10
|
+
SUBDEPARTMENTS = %w[].freeze
|
|
11
|
+
AMENDMENTS = [].freeze
|
|
12
|
+
COP_DOC_BASE_URL = 'https://www.rubydoc.info/gems/rubocop-sidekiq_plus/RuboCop/Cop/'
|
|
13
|
+
|
|
14
|
+
def initialize(config, descriptions)
|
|
15
|
+
@config = config
|
|
16
|
+
@descriptions = descriptions
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def dump
|
|
20
|
+
YAML.dump(unified_config)
|
|
21
|
+
.gsub(EXTENSION_ROOT_DEPARTMENT, "\n\\1")
|
|
22
|
+
.gsub(/^(SidekiqPro:|SidekiqEnt:)/, "\n\\1")
|
|
23
|
+
.gsub(/^(\s+)- /, '\1 - ')
|
|
24
|
+
.gsub('"~"', '~')
|
|
25
|
+
# .gsub(*AMENDMENTS, "\n\\0")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def unified_config
|
|
31
|
+
cops.each_with_object(config.dup) do |cop, unified|
|
|
32
|
+
next if SUBDEPARTMENTS.include?(cop) || AMENDMENTS.include?(cop)
|
|
33
|
+
|
|
34
|
+
unified[cop] ||= {}
|
|
35
|
+
replace_nil(unified[cop])
|
|
36
|
+
unified[cop].merge!(descriptions.fetch(cop, {}))
|
|
37
|
+
unified[cop]['Reference'] = reference(cop)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def cops
|
|
42
|
+
(descriptions.keys | config.keys).grep(EXTENSION_ROOT_DEPARTMENT)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def replace_nil(config)
|
|
46
|
+
return unless config
|
|
47
|
+
|
|
48
|
+
config.each do |key, value|
|
|
49
|
+
config[key] = '~' if value.nil?
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def reference(cop)
|
|
54
|
+
COP_DOC_BASE_URL + cop
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
attr_reader :config, :descriptions
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Sidekiq
|
|
5
|
+
# Extracts cop descriptions from YARD docstrings
|
|
6
|
+
class DescriptionExtractor
|
|
7
|
+
def initialize(yardocs)
|
|
8
|
+
@code_objects = yardocs.map(&CodeObject.public_method(:new))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def to_h
|
|
12
|
+
configs = code_objects.select(&:cop?).map(&:configuration)
|
|
13
|
+
return {} if configs.empty?
|
|
14
|
+
|
|
15
|
+
configs.reduce(:merge)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
attr_reader :code_objects
|
|
21
|
+
|
|
22
|
+
# Decorator of a YARD code object for working with documented cops
|
|
23
|
+
class CodeObject
|
|
24
|
+
RUBOCOP_COP_CLASS_NAME = 'RuboCop::Cop::Base'
|
|
25
|
+
|
|
26
|
+
def initialize(yardoc)
|
|
27
|
+
@yardoc = yardoc
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Test if the YARD code object documents a concrete cop class
|
|
31
|
+
#
|
|
32
|
+
# @return [Boolean]
|
|
33
|
+
def cop?
|
|
34
|
+
cop_subclass? && !abstract?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Configuration for the documented cop that would live in default.yml
|
|
38
|
+
#
|
|
39
|
+
# @return [Hash]
|
|
40
|
+
def configuration
|
|
41
|
+
{ cop_name => { 'Description' => description } }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def cop_name
|
|
47
|
+
Object.const_get(documented_constant).cop_name
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def description
|
|
51
|
+
yardoc.docstring.split("\n\n").first.to_s
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def documented_constant
|
|
55
|
+
yardoc.to_s
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def cop_subclass?
|
|
59
|
+
yardoc.superclass.path == RUBOCOP_COP_CLASS_NAME
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def abstract?
|
|
63
|
+
yardoc.tags.any? { |tag| tag.tag_name.eql?('abstract') }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
attr_reader :yardoc
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Sidekiq
|
|
5
|
+
# Centralized Sidekiq API definitions used by cops.
|
|
6
|
+
module Language
|
|
7
|
+
extend RuboCop::NodePattern::Macros
|
|
8
|
+
|
|
9
|
+
module PerformMethods # :nodoc:
|
|
10
|
+
ALL = %i[perform_async perform_in perform_at perform_bulk].freeze
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
def all
|
|
14
|
+
ALL
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def include?(method)
|
|
18
|
+
ALL.include?(method)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module JobModules # :nodoc:
|
|
24
|
+
ALL = %i[Job Worker].freeze
|
|
25
|
+
|
|
26
|
+
class << self
|
|
27
|
+
def all
|
|
28
|
+
ALL
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def include?(name)
|
|
32
|
+
ALL.include?(name)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @!method sidekiq_include?(node)
|
|
38
|
+
# Matches `include Sidekiq::Job` or `include Sidekiq::Worker`
|
|
39
|
+
# Also matches when included with other modules: `include Sidekiq::Job, OtherModule`
|
|
40
|
+
def_node_matcher :sidekiq_include?, <<~PATTERN
|
|
41
|
+
(send nil? :include <(const (const {nil? cbase} :Sidekiq)
|
|
42
|
+
{#{JobModules.all.map(&:inspect).join(' ')}}) ...>)
|
|
43
|
+
PATTERN
|
|
44
|
+
|
|
45
|
+
# @!method sidekiq_options_call?(node)
|
|
46
|
+
def_node_matcher :sidekiq_options_call?, <<~PATTERN
|
|
47
|
+
(send nil? :sidekiq_options $...)
|
|
48
|
+
PATTERN
|
|
49
|
+
|
|
50
|
+
# @!method active_job_class?(node)
|
|
51
|
+
def_node_matcher :active_job_class?, <<~PATTERN
|
|
52
|
+
(class _ (const {nil? cbase} :ApplicationJob) ...)
|
|
53
|
+
PATTERN
|
|
54
|
+
|
|
55
|
+
# @!method perform_call?(node)
|
|
56
|
+
def_node_matcher :perform_call?, <<~PATTERN
|
|
57
|
+
(send $_ {#{PerformMethods.all.map(&:inspect).join(' ')}} ...)
|
|
58
|
+
PATTERN
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def in_sidekiq_job?(node)
|
|
63
|
+
node.each_ancestor(:class).any? do |class_node|
|
|
64
|
+
sidekiq_job_class?(class_node)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def sidekiq_job_class?(class_node)
|
|
69
|
+
return false unless class_node.body
|
|
70
|
+
|
|
71
|
+
if class_node.body.begin_type?
|
|
72
|
+
class_node.body.each_child_node.any? { |n| sidekiq_include?(n) }
|
|
73
|
+
else
|
|
74
|
+
sidekiq_include?(class_node.body)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'lint_roller'
|
|
4
|
+
|
|
5
|
+
module RuboCop
|
|
6
|
+
module Sidekiq
|
|
7
|
+
class Plugin < LintRoller::Plugin
|
|
8
|
+
def about
|
|
9
|
+
LintRoller::About.new(
|
|
10
|
+
name: 'rubocop-sidekiq_plus',
|
|
11
|
+
version: VERSION,
|
|
12
|
+
homepage: 'https://github.com/ydah/rubocop-sidekiq_plus',
|
|
13
|
+
description: 'Code style checking for Sidekiq.'
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def supported?(context)
|
|
18
|
+
context.engine == :rubocop
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def rules(_context)
|
|
22
|
+
LintRoller::Rules.new(
|
|
23
|
+
type: :path,
|
|
24
|
+
config_format: :rubocop,
|
|
25
|
+
value: CONFIG_DEFAULT.to_s
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rubocop-sidekiq_plus
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Yudai Takada
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: lint_roller
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.1'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '1.1'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rubocop
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '1.81'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.81'
|
|
40
|
+
description: A RuboCop extension focused on enforcing Sidekiq best practices and coding
|
|
41
|
+
conventions.
|
|
42
|
+
email:
|
|
43
|
+
- t.yudai92@gmail.com
|
|
44
|
+
executables: []
|
|
45
|
+
extensions: []
|
|
46
|
+
extra_rdoc_files: []
|
|
47
|
+
files:
|
|
48
|
+
- LICENSE.txt
|
|
49
|
+
- README.md
|
|
50
|
+
- config/default.yml
|
|
51
|
+
- lib/rubocop-sidekiq.rb
|
|
52
|
+
- lib/rubocop-sidekiq_plus.rb
|
|
53
|
+
- lib/rubocop/cop/sidekiq/active_record_argument.rb
|
|
54
|
+
- lib/rubocop/cop/sidekiq/async_in_test.rb
|
|
55
|
+
- lib/rubocop/cop/sidekiq/base.rb
|
|
56
|
+
- lib/rubocop/cop/sidekiq/consistent_job_suffix.rb
|
|
57
|
+
- lib/rubocop/cop/sidekiq/constant_job_class_name.rb
|
|
58
|
+
- lib/rubocop/cop/sidekiq/database_connection_leak.rb
|
|
59
|
+
- lib/rubocop/cop/sidekiq/date_time_argument.rb
|
|
60
|
+
- lib/rubocop/cop/sidekiq/deprecated_default_worker_options.rb
|
|
61
|
+
- lib/rubocop/cop/sidekiq/deprecated_delay_extension.rb
|
|
62
|
+
- lib/rubocop/cop/sidekiq/deprecated_worker_module.rb
|
|
63
|
+
- lib/rubocop/cop/sidekiq/enqueue_inefficiency.rb
|
|
64
|
+
- lib/rubocop/cop/sidekiq/excessive_retry.rb
|
|
65
|
+
- lib/rubocop/cop/sidekiq/find_each_in_job.rb
|
|
66
|
+
- lib/rubocop/cop/sidekiq/huge_job_arguments.rb
|
|
67
|
+
- lib/rubocop/cop/sidekiq/job_dependency.rb
|
|
68
|
+
- lib/rubocop/cop/sidekiq/job_file_location.rb
|
|
69
|
+
- lib/rubocop/cop/sidekiq/job_file_naming.rb
|
|
70
|
+
- lib/rubocop/cop/sidekiq/job_include.rb
|
|
71
|
+
- lib/rubocop/cop/sidekiq/missing_logging.rb
|
|
72
|
+
- lib/rubocop/cop/sidekiq/missing_timeout.rb
|
|
73
|
+
- lib/rubocop/cop/sidekiq/mixed_retry_strategies.rb
|
|
74
|
+
- lib/rubocop/cop/sidekiq/mixin/argument_traversal.rb
|
|
75
|
+
- lib/rubocop/cop/sidekiq/mixin/class_name_helper.rb
|
|
76
|
+
- lib/rubocop/cop/sidekiq/mixin/processed_source_path.rb
|
|
77
|
+
- lib/rubocop/cop/sidekiq/no_rescue_all.rb
|
|
78
|
+
- lib/rubocop/cop/sidekiq/perform_inline_usage.rb
|
|
79
|
+
- lib/rubocop/cop/sidekiq/perform_method_parameters.rb
|
|
80
|
+
- lib/rubocop/cop/sidekiq/pii_in_arguments.rb
|
|
81
|
+
- lib/rubocop/cop/sidekiq/puts_or_print_usage.rb
|
|
82
|
+
- lib/rubocop/cop/sidekiq/queue_specified.rb
|
|
83
|
+
- lib/rubocop/cop/sidekiq/redis_in_job.rb
|
|
84
|
+
- lib/rubocop/cop/sidekiq/retry_specified.rb
|
|
85
|
+
- lib/rubocop/cop/sidekiq/retry_zero.rb
|
|
86
|
+
- lib/rubocop/cop/sidekiq/self_scheduling_job.rb
|
|
87
|
+
- lib/rubocop/cop/sidekiq/sensitive_data_in_arguments.rb
|
|
88
|
+
- lib/rubocop/cop/sidekiq/sidekiq_over_active_job.rb
|
|
89
|
+
- lib/rubocop/cop/sidekiq/silent_rescue.rb
|
|
90
|
+
- lib/rubocop/cop/sidekiq/sleep_in_jobs.rb
|
|
91
|
+
- lib/rubocop/cop/sidekiq/symbol_argument.rb
|
|
92
|
+
- lib/rubocop/cop/sidekiq/thread_in_job.rb
|
|
93
|
+
- lib/rubocop/cop/sidekiq/transaction_leak.rb
|
|
94
|
+
- lib/rubocop/cop/sidekiq/unknown_sidekiq_option.rb
|
|
95
|
+
- lib/rubocop/cop/sidekiq_cops.rb
|
|
96
|
+
- lib/rubocop/cop/sidekiq_ent/base.rb
|
|
97
|
+
- lib/rubocop/cop/sidekiq_ent/encryption_with_many_arguments.rb
|
|
98
|
+
- lib/rubocop/cop/sidekiq_ent/encryption_without_secret_bag.rb
|
|
99
|
+
- lib/rubocop/cop/sidekiq_ent/leader_election_without_block.rb
|
|
100
|
+
- lib/rubocop/cop/sidekiq_ent/limiter_not_reused.rb
|
|
101
|
+
- lib/rubocop/cop/sidekiq_ent/limiter_without_lock_timeout.rb
|
|
102
|
+
- lib/rubocop/cop/sidekiq_ent/limiter_without_wait_timeout.rb
|
|
103
|
+
- lib/rubocop/cop/sidekiq_ent/periodic_job_invalid_cron.rb
|
|
104
|
+
- lib/rubocop/cop/sidekiq_ent/periodic_job_with_arguments.rb
|
|
105
|
+
- lib/rubocop/cop/sidekiq_ent/unique_job_too_short_ttl.rb
|
|
106
|
+
- lib/rubocop/cop/sidekiq_ent/unique_job_without_ttl.rb
|
|
107
|
+
- lib/rubocop/cop/sidekiq_ent/unique_until_mismatch.rb
|
|
108
|
+
- lib/rubocop/cop/sidekiq_pro/base.rb
|
|
109
|
+
- lib/rubocop/cop/sidekiq_pro/batch_callback_method.rb
|
|
110
|
+
- lib/rubocop/cop/sidekiq_pro/batch_retry_in_callback.rb
|
|
111
|
+
- lib/rubocop/cop/sidekiq_pro/batch_status_polling.rb
|
|
112
|
+
- lib/rubocop/cop/sidekiq_pro/batch_without_callback.rb
|
|
113
|
+
- lib/rubocop/cop/sidekiq_pro/empty_batch.rb
|
|
114
|
+
- lib/rubocop/cop/sidekiq_pro/expiring_job_without_ttl.rb
|
|
115
|
+
- lib/rubocop/cop/sidekiq_pro/large_argument_in_batch.rb
|
|
116
|
+
- lib/rubocop/cop/sidekiq_pro/nested_batch_without_parent.rb
|
|
117
|
+
- lib/rubocop/cop/sidekiq_pro/reliability_not_enabled.rb
|
|
118
|
+
- lib/rubocop/sidekiq.rb
|
|
119
|
+
- lib/rubocop/sidekiq/config_formatter.rb
|
|
120
|
+
- lib/rubocop/sidekiq/description_extractor.rb
|
|
121
|
+
- lib/rubocop/sidekiq/language.rb
|
|
122
|
+
- lib/rubocop/sidekiq/plugin.rb
|
|
123
|
+
- lib/rubocop/sidekiq/version.rb
|
|
124
|
+
homepage: https://github.com/ydah/rubocop-sidekiq_plus
|
|
125
|
+
licenses:
|
|
126
|
+
- MIT
|
|
127
|
+
metadata:
|
|
128
|
+
homepage_uri: https://github.com/ydah/rubocop-sidekiq_plus
|
|
129
|
+
source_code_uri: https://github.com/ydah/rubocop-sidekiq_plus
|
|
130
|
+
changelog_uri: https://github.com/ydah/rubocop-sidekiq_plus/blob/main/CHANGELOG.md
|
|
131
|
+
default_lint_roller_plugin: RuboCop::Sidekiq::Plugin
|
|
132
|
+
rubygems_mfa_required: 'true'
|
|
133
|
+
rdoc_options: []
|
|
134
|
+
require_paths:
|
|
135
|
+
- lib
|
|
136
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
137
|
+
requirements:
|
|
138
|
+
- - ">="
|
|
139
|
+
- !ruby/object:Gem::Version
|
|
140
|
+
version: 2.7.0
|
|
141
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
|
+
requirements:
|
|
143
|
+
- - ">="
|
|
144
|
+
- !ruby/object:Gem::Version
|
|
145
|
+
version: '0'
|
|
146
|
+
requirements: []
|
|
147
|
+
rubygems_version: 4.0.4
|
|
148
|
+
specification_version: 4
|
|
149
|
+
summary: Code style checking for Sidekiq
|
|
150
|
+
test_files: []
|