sidekiq-unique-jobs 8.0.3 → 8.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +157 -1
  3. data/README.md +2 -4
  4. data/lib/sidekiq_unique_jobs/batch_delete.rb +1 -1
  5. data/lib/sidekiq_unique_jobs/changelog.rb +1 -1
  6. data/lib/sidekiq_unique_jobs/config.rb +4 -4
  7. data/lib/sidekiq_unique_jobs/constants.rb +1 -0
  8. data/lib/sidekiq_unique_jobs/digests.rb +46 -13
  9. data/lib/sidekiq_unique_jobs/job.rb +4 -4
  10. data/lib/sidekiq_unique_jobs/lock/base_lock.rb +1 -1
  11. data/lib/sidekiq_unique_jobs/lock/while_executing.rb +3 -0
  12. data/lib/sidekiq_unique_jobs/lock.rb +14 -11
  13. data/lib/sidekiq_unique_jobs/lock_config.rb +10 -4
  14. data/lib/sidekiq_unique_jobs/locksmith.rb +10 -5
  15. data/lib/sidekiq_unique_jobs/lua/delete.lua +6 -5
  16. data/lib/sidekiq_unique_jobs/lua/lock.lua +16 -7
  17. data/lib/sidekiq_unique_jobs/lua/queue.lua +9 -8
  18. data/lib/sidekiq_unique_jobs/lua/shared/_delete_from_queue.lua +10 -10
  19. data/lib/sidekiq_unique_jobs/lua/shared/_delete_from_sorted_set.lua +20 -10
  20. data/lib/sidekiq_unique_jobs/lua/unlock.lua +26 -18
  21. data/lib/sidekiq_unique_jobs/middleware/client.rb +1 -1
  22. data/lib/sidekiq_unique_jobs/middleware/server.rb +1 -1
  23. data/lib/sidekiq_unique_jobs/middleware.rb +5 -5
  24. data/lib/sidekiq_unique_jobs/on_conflict/replace.rb +1 -1
  25. data/lib/sidekiq_unique_jobs/on_conflict/reschedule.rb +5 -1
  26. data/lib/sidekiq_unique_jobs/orphans/manager.rb +8 -7
  27. data/lib/sidekiq_unique_jobs/orphans/reaper.rb +2 -1
  28. data/lib/sidekiq_unique_jobs/orphans/ruby_reaper.rb +26 -7
  29. data/lib/sidekiq_unique_jobs/redis/sorted_set.rb +12 -3
  30. data/lib/sidekiq_unique_jobs/script/caller.rb +1 -1
  31. data/lib/sidekiq_unique_jobs/script/client.rb +94 -0
  32. data/lib/sidekiq_unique_jobs/script/config.rb +68 -0
  33. data/lib/sidekiq_unique_jobs/script/dsl.rb +60 -0
  34. data/lib/sidekiq_unique_jobs/script/logging.rb +95 -0
  35. data/lib/sidekiq_unique_jobs/script/lua_error.rb +96 -0
  36. data/lib/sidekiq_unique_jobs/script/script.rb +75 -0
  37. data/lib/sidekiq_unique_jobs/script/scripts.rb +123 -0
  38. data/lib/sidekiq_unique_jobs/script/template.rb +41 -0
  39. data/lib/sidekiq_unique_jobs/script/timing.rb +35 -0
  40. data/lib/sidekiq_unique_jobs/script.rb +32 -1
  41. data/lib/sidekiq_unique_jobs/server.rb +2 -0
  42. data/lib/sidekiq_unique_jobs/sidekiq_unique_ext.rb +13 -35
  43. data/lib/sidekiq_unique_jobs/sidekiq_unique_jobs.rb +4 -4
  44. data/lib/sidekiq_unique_jobs/sidekiq_worker_methods.rb +3 -3
  45. data/lib/sidekiq_unique_jobs/testing.rb +4 -4
  46. data/lib/sidekiq_unique_jobs/version.rb +1 -1
  47. data/lib/sidekiq_unique_jobs/web/helpers.rb +3 -3
  48. data/lib/sidekiq_unique_jobs/web/views/changelogs.erb +1 -1
  49. data/lib/sidekiq_unique_jobs/web/views/lock.erb +2 -2
  50. data/lib/sidekiq_unique_jobs/web/views/locks.erb +1 -1
  51. data/lib/sidekiq_unique_jobs/web.rb +18 -17
  52. data/lib/sidekiq_unique_jobs.rb +5 -4
  53. metadata +12 -23
@@ -1,19 +1,29 @@
1
1
  local function delete_from_sorted_set(name, digest)
2
- local per = 50
3
- local total = redis.call("zcard", name)
4
- local index = 0
5
- local result
2
+ local score = redis.call("ZSCORE", "uniquejobs:digests", digest)
3
+ local total = redis.call("ZCARD", name)
4
+ local per = 50
5
+
6
+ for offset = 0, total, per do
7
+ local items
8
+
9
+ if score then
10
+ items = redis.call("ZRANGE", name, score, "+inf", "BYSCORE", "LIMIT", offset, per)
11
+ else
12
+ items = redis.call("ZRANGE", name, offset, offset + per -1)
13
+ end
14
+
15
+ if #items == 0 then
16
+ break
17
+ end
6
18
 
7
- while (index < total) do
8
- local items = redis.call("ZRANGE", name, index, index + per -1)
9
19
  for _, item in pairs(items) do
10
20
  if string.find(item, digest) then
11
21
  redis.call("ZREM", name, item)
12
- result = item
13
- break
22
+
23
+ return item
14
24
  end
15
25
  end
16
- index = index + per
17
26
  end
18
- return result
27
+
28
+ return nil
19
29
  end
@@ -10,19 +10,20 @@ local digests = KEYS[7]
10
10
 
11
11
 
12
12
  -------- BEGIN lock arguments ---------
13
- local job_id = ARGV[1]
14
- local pttl = tonumber(ARGV[2])
15
- local lock_type = ARGV[3]
16
- local limit = tonumber(ARGV[4])
13
+ local job_id = ARGV[1]
14
+ local pttl = tonumber(ARGV[2])
15
+ local lock_type = ARGV[3]
16
+ local limit = tonumber(ARGV[4])
17
+ local lock_score = ARGV[5]
17
18
  -------- END lock arguments -----------
18
19
 
19
20
 
20
21
  -------- BEGIN injected arguments --------
21
- local current_time = tonumber(ARGV[5])
22
- local debug_lua = tostring(ARGV[6]) == "1"
23
- local max_history = tonumber(ARGV[7])
24
- local script_name = tostring(ARGV[8]) .. ".lua"
25
- local redisversion = ARGV[9]
22
+ local current_time = tonumber(ARGV[6])
23
+ local debug_lua = tostring(ARGV[7]) == "1"
24
+ local max_history = tonumber(ARGV[8])
25
+ local script_name = tostring(ARGV[9]) .. ".lua"
26
+ local redisversion = ARGV[10]
26
27
  --------- END injected arguments ---------
27
28
 
28
29
 
@@ -75,21 +76,28 @@ if lock_type ~= "until_expired" then
75
76
  redis.call("HDEL", locked, job_id)
76
77
  end
77
78
 
79
+ if redis.call("LLEN", primed) == 0 then
80
+ log_debug("UNLINK", primed)
81
+ redis.call("UNLINK", primed)
82
+ end
83
+
78
84
  local locked_count = redis.call("HLEN", locked)
79
85
 
80
- if locked_count and locked_count < 1 then
86
+ if locked_count < 1 then
81
87
  log_debug("UNLINK", locked)
82
88
  redis.call("UNLINK", locked)
83
89
  end
84
90
 
85
- if redis.call("LLEN", primed) == 0 then
86
- log_debug("UNLINK", primed)
87
- redis.call("UNLINK", primed)
88
- end
89
-
90
- if limit and limit <= 1 and locked_count and locked_count <= 1 then
91
- log_debug("ZREM", digests, digest)
92
- redis.call("ZREM", digests, digest)
91
+ if limit then
92
+ if limit <= 1 and locked_count <= 1 then
93
+ log_debug("ZREM", digests, digest)
94
+ redis.call("ZREM", digests, digest)
95
+ end
96
+ else
97
+ if locked_count <= 1 then
98
+ log_debug("ZREM", digests, digest)
99
+ redis.call("ZREM", digests, digest)
100
+ end
93
101
  end
94
102
 
95
103
  log_debug("LPUSH", queued, "1")
@@ -6,7 +6,7 @@ module SidekiqUniqueJobs
6
6
  #
7
7
  # @author Mikael Henriksson <mikael@mhenrixon.com>
8
8
  class Client
9
- include Sidekiq::ClientMiddleware if defined?(Sidekiq::ClientMiddleware)
9
+ include Sidekiq::ClientMiddleware
10
10
 
11
11
  # prepend "SidekiqUniqueJobs::Middleware"
12
12
  # @!parse prepends SidekiqUniqueJobs::Middleware
@@ -6,7 +6,7 @@ module SidekiqUniqueJobs
6
6
  #
7
7
  # @author Mikael Henriksson <mikael@mhenrixon.com>
8
8
  class Server
9
- include Sidekiq::ServerMiddleware if defined?(Sidekiq::ServerMiddleware)
9
+ include Sidekiq::ServerMiddleware
10
10
 
11
11
  # prepend "SidekiqUniqueJobs::Middleware"
12
12
  # @!parse prepends SidekiqUniqueJobs::Middleware
@@ -19,15 +19,15 @@ module SidekiqUniqueJobs
19
19
  # This method runs before (prepended) the actual middleware implementation.
20
20
  # This is done to reduce duplication
21
21
  #
22
- # @param [Sidekiq::Worker] worker_class
22
+ # @param [Sidekiq::Job] worker_class
23
23
  # @param [Hash] item a sidekiq job hash
24
24
  # @param [String] queue name of the queue
25
25
  # @param [ConnectionPool] redis_pool only used for compatility reasons
26
26
  #
27
- # @return [yield<super>] <description>
27
+ # @return [yield<super>] call the rest of the middleware stack
28
28
  #
29
- # @yieldparam [<type>] if <description>
30
- # @yieldreturn [<type>] <describe what yield should return>
29
+ # @yieldparam [void] if uniquejobs is disable
30
+ # @yieldreturn [void] delegate back to other sidekiq middleware
31
31
  def call(worker_class, item, queue, redis_pool = nil)
32
32
  @item = item
33
33
  @queue = queue
@@ -35,7 +35,7 @@ module SidekiqUniqueJobs
35
35
  self.job_class = worker_class
36
36
  return yield if unique_disabled?
37
37
 
38
- SidekiqUniqueJobs::Job.prepare(item) unless item[LOCK_DIGEST]
38
+ SidekiqUniqueJobs::Job.prepare(item)
39
39
 
40
40
  with_logging_context do
41
41
  super
@@ -65,7 +65,7 @@ module SidekiqUniqueJobs
65
65
  # @return [Integer] the number of keys deleted
66
66
  #
67
67
  def delete_lock
68
- digests.delete_by_digest(lock_digest)
68
+ digests.delete_by_digest(lock_digest, runtime: false)
69
69
  end
70
70
 
71
71
  #
@@ -21,7 +21,7 @@ module SidekiqUniqueJobs
21
21
  # This will mess up sidekiq stats because a new job is created
22
22
  def call
23
23
  if sidekiq_job_class?
24
- if job_class.set(queue: item["queue"].to_sym).perform_in(5, *item[ARGS])
24
+ if job_class.set(queue: item["queue"].to_sym).perform_in(schedule_in, *item[ARGS])
25
25
  reflect(:rescheduled, item)
26
26
  else
27
27
  reflect(:reschedule_failed, item)
@@ -30,6 +30,10 @@ module SidekiqUniqueJobs
30
30
  reflect(:unknown_sidekiq_worker, item)
31
31
  end
32
32
  end
33
+
34
+ def schedule_in
35
+ job_class.get_sidekiq_options["schedule_in"] || 5
36
+ end
33
37
  end
34
38
  end
35
39
  end
@@ -39,12 +39,13 @@ module SidekiqUniqueJobs
39
39
  self.task = test_task || default_task
40
40
 
41
41
  with_logging_context do
42
- register_reaper_process
43
- log_info("Starting Reaper")
42
+ if register_reaper_process
43
+ log_info("Starting Reaper")
44
44
 
45
- task.add_observer(Observer.new)
46
- task.execute
47
- task
45
+ task.add_observer(Observer.new)
46
+ task.execute
47
+ task
48
+ end
48
49
  end
49
50
  end
50
51
 
@@ -192,7 +193,7 @@ module SidekiqUniqueJobs
192
193
  # @return [void]
193
194
  #
194
195
  def register_reaper_process
195
- redis { |conn| conn.set(UNIQUE_REAPER, current_timestamp, nx: true, ex: drift_reaper_interval) }
196
+ redis { |conn| conn.set(UNIQUE_REAPER, current_timestamp, "nx", "ex", drift_reaper_interval) }
196
197
  end
197
198
 
198
199
  #
@@ -202,7 +203,7 @@ module SidekiqUniqueJobs
202
203
  # @return [void]
203
204
  #
204
205
  def refresh_reaper_mutex
205
- redis { |conn| conn.set(UNIQUE_REAPER, current_timestamp, ex: drift_reaper_interval) }
206
+ redis { |conn| conn.set(UNIQUE_REAPER, current_timestamp, "ex", drift_reaper_interval) }
206
207
  end
207
208
 
208
209
  #
@@ -22,11 +22,12 @@ module SidekiqUniqueJobs
22
22
  #
23
23
  # @return [Hash<Symbol, SidekiqUniqueJobs::Orphans::Reaper] the current implementation of reapers
24
24
  REAPERS = {
25
- lua: SidekiqUniqueJobs::Orphans::LuaReaper,
25
+ lua: SidekiqUniqueJobs::Orphans::RubyReaper,
26
26
  ruby: SidekiqUniqueJobs::Orphans::RubyReaper,
27
27
  none: SidekiqUniqueJobs::Orphans::NullReaper,
28
28
  nil => SidekiqUniqueJobs::Orphans::NullReaper,
29
29
  false => SidekiqUniqueJobs::Orphans::NullReaper,
30
+ true => SidekiqUniqueJobs::Orphans::RubyReaper,
30
31
  }.freeze
31
32
 
32
33
  #
@@ -13,6 +13,9 @@ module SidekiqUniqueJobs
13
13
  class RubyReaper < Reaper
14
14
  include SidekiqUniqueJobs::Timing
15
15
 
16
+ #
17
+ # @return [Integer] a best guess of Sidekiq::Launcher::BEAT_PAUSE
18
+ SIDEKIQ_BEAT_PAUSE = 10
16
19
  #
17
20
  # @return [String] the suffix for :RUN locks
18
21
  RUN_SUFFIX = ":RUN"
@@ -74,12 +77,28 @@ module SidekiqUniqueJobs
74
77
 
75
78
  BatchDelete.call(expired_digests, conn)
76
79
  BatchDelete.call(orphans, conn)
80
+
81
+ # orphans.each_slice(500) do |chunk|
82
+ # conn.pipelined do |pipeline|
83
+ # chunk.each do |digest|
84
+ # next if belongs_to_job?(digest)
85
+
86
+ # pipeline.zadd(ORPHANED_DIGESTS, now_f, digest)
87
+ # end
88
+ # end
89
+ # end
77
90
  end
78
91
 
79
92
  def expired_digests
80
- max_score = (start_time - reaper_timeout).to_f
93
+ conn.zrange(EXPIRING_DIGESTS, 0, max_score, "byscore")
94
+ end
95
+
96
+ def orphaned_digests
97
+ conn.zrange(ORPHANED_DIGESTS, 0, max_score, "byscore")
98
+ end
81
99
 
82
- conn.zrange(EXPIRING_DIGESTS, 0, max_score, byscore: true)
100
+ def max_score
101
+ (start_time - reaper_timeout - SIDEKIQ_BEAT_PAUSE).to_f
83
102
  end
84
103
 
85
104
  #
@@ -89,10 +108,10 @@ module SidekiqUniqueJobs
89
108
  # @return [Array<String>] an array of orphaned digests
90
109
  #
91
110
  def orphans # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
92
- page = 0
93
- per = reaper_count * 2
94
111
  orphans = []
95
- results = conn.zrange(digests.key, page * per, (page + 1) * per)
112
+ page = 0
113
+ per = reaper_count * 2
114
+ results = digests.byscore(0, max_score, offset: page * per, count: (page + 1) * per)
96
115
 
97
116
  while results.size.positive?
98
117
  results.each do |digest|
@@ -107,7 +126,7 @@ module SidekiqUniqueJobs
107
126
  break if orphans.size >= reaper_count
108
127
 
109
128
  page += 1
110
- results = conn.zrange(digests.key, page * per, (page + 1) * per)
129
+ results = digests.byscore(0, max_score, offset: page * per, count: (page + 1) * per)
111
130
  end
112
131
 
113
132
  orphans
@@ -218,7 +237,7 @@ module SidekiqUniqueJobs
218
237
  end
219
238
 
220
239
  def considered_active?(time_f)
221
- (Time.now - reaper_timeout).to_f < time_f
240
+ max_score < time_f
222
241
  end
223
242
 
224
243
  #
@@ -24,10 +24,11 @@ module SidekiqUniqueJobs
24
24
  # @return [Hash] when given with_scores: true
25
25
  #
26
26
  def entries(with_scores: true)
27
- entrys = redis { |conn| conn.zrange(key, 0, -1, withscores: with_scores) }
28
- return entrys unless with_scores
27
+ return redis { |conn| conn.zrange(key, 0, -1) } unless with_scores
29
28
 
30
- entrys.each_with_object({}) { |pair, hash| hash[pair[0]] = pair[1] }
29
+ redis { |conn| conn.zrange(key, 0, -1, "withscores") }.each_with_object({}) do |pair, hash|
30
+ hash[pair[0]] = pair[1]
31
+ end
31
32
  end
32
33
 
33
34
  #
@@ -47,6 +48,14 @@ module SidekiqUniqueJobs
47
48
  end
48
49
  end
49
50
 
51
+ def byscore(min, max, offset: nil, count: nil)
52
+ redis do |conn|
53
+ return conn.zrange(key, min, max, "byscore") unless offset && count
54
+
55
+ conn.zrange(key, min, max, "byscore", "limit", offset, count)
56
+ end
57
+ end
58
+
50
59
  #
51
60
  # Return the zrak of the member
52
61
  #
@@ -56,7 +56,7 @@ module SidekiqUniqueJobs
56
56
  def do_call(file_name, conn, keys, argv)
57
57
  argv = argv.dup.push(now_f, debug_lua, max_history, file_name, redis_version)
58
58
 
59
- Script.execute(file_name, conn, keys: keys, argv: normalize_argv(argv))
59
+ SidekiqUniqueJobs::Script.execute(file_name, conn, keys: keys, argv: normalize_argv(argv))
60
60
  end
61
61
 
62
62
  #
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SidekiqUniqueJobs
4
+ module Script
5
+ # Interface to dealing with .lua files
6
+ #
7
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
8
+ class Client
9
+ include SidekiqUniqueJobs::Script::Timing
10
+
11
+ #
12
+ # @!attribute [r] logger
13
+ # @return [Logger] an instance of a logger
14
+ attr_reader :logger
15
+ #
16
+ # @!attribute [r] file_name
17
+ # @return [String] The name of the file to execute
18
+ attr_reader :config
19
+ #
20
+ # @!attribute [r] scripts
21
+ # @return [Scripts] the collection with loaded scripts
22
+ attr_reader :scripts
23
+
24
+ def initialize(config)
25
+ @config = config
26
+ @logger = config.logger
27
+ @scripts = Scripts.fetch(config.scripts_path)
28
+ end
29
+
30
+ #
31
+ # Execute a lua script with the provided script_name
32
+ #
33
+ # @note this method is recursive if we need to load a lua script
34
+ # that wasn't previously loaded.
35
+ #
36
+ # @param [Symbol] script_name the name of the script to execute
37
+ # @param [Redis] conn the redis connection to use for execution
38
+ # @param [Array<String>] keys script keys
39
+ # @param [Array<Object>] argv script arguments
40
+ #
41
+ # @return value from script
42
+ #
43
+ def execute(script_name, conn, keys: [], argv: [])
44
+ result, elapsed = timed do
45
+ scripts.execute(script_name, conn, keys: keys, argv: argv)
46
+ end
47
+
48
+ logger.debug("Executed #{script_name}.lua in #{elapsed}ms")
49
+ result
50
+ rescue ::RedisClient::CommandError => ex
51
+ handle_error(script_name, conn, ex) do
52
+ execute(script_name, conn, keys: keys, argv: argv)
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ #
59
+ # Handle errors to allow retrying errors that need retrying
60
+ #
61
+ # @param [RedisClient::CommandError] ex exception to handle
62
+ #
63
+ # @return [void]
64
+ #
65
+ # @yieldreturn [void] yields back to the caller when NOSCRIPT is raised
66
+ def handle_error(script_name, conn, ex)
67
+ case ex.message
68
+ when /NOSCRIPT/
69
+ handle_noscript(script_name) { return yield }
70
+ when /BUSY/
71
+ handle_busy(conn) { return yield }
72
+ end
73
+
74
+ raise unless LuaError.intercepts?(ex)
75
+
76
+ script = scripts.fetch(script_name, conn)
77
+ raise LuaError.new(ex, script)
78
+ end
79
+
80
+ def handle_noscript(script_name)
81
+ scripts.delete(script_name)
82
+ yield
83
+ end
84
+
85
+ def handle_busy(conn)
86
+ scripts.kill(conn)
87
+ rescue ::RedisClient::CommandError => ex
88
+ logger.warn(ex)
89
+ ensure
90
+ yield
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SidekiqUniqueJobs
4
+ module Script
5
+ #
6
+ # Class holding gem configuration
7
+ #
8
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
9
+ class Config
10
+ #
11
+ # @!attribute [r] logger
12
+ # @return [Logger] a logger to use for debugging
13
+ attr_reader :logger
14
+ #
15
+ # @!attribute [r] scripts_path
16
+ # @return [Pathname] a directory with lua scripts
17
+ attr_reader :scripts_path
18
+
19
+ #
20
+ # Initialize a new instance of {Config}
21
+ #
22
+ #
23
+ def initialize
24
+ @conn = RedisClient.new
25
+ @logger = Logger.new($stdout)
26
+ @scripts_path = nil
27
+ end
28
+
29
+ #
30
+ # Sets a value for scripts_path
31
+ #
32
+ # @param [String, Pathname] obj <description>
33
+ #
34
+ # @raise [ArgumentError] when directory does not exist
35
+ # @raise [ArgumentError] when argument isn't supported
36
+ #
37
+ # @return [Pathname]
38
+ #
39
+ def scripts_path=(obj)
40
+ raise ArgumentError, "#{obj} should be a Pathname or String" unless obj.is_a?(Pathname) || obj.is_a?(String)
41
+ raise ArgumentError, "#{obj} does not exist" unless Dir.exist?(obj.to_s)
42
+
43
+ @scripts_path =
44
+ case obj
45
+ when String
46
+ Pathname.new(obj)
47
+ else
48
+ obj
49
+ end
50
+ end
51
+
52
+ #
53
+ # Sets a value for logger
54
+ #
55
+ # @param [Logger] obj a logger to use
56
+ #
57
+ # @raise [ArgumentError] when given argument isn't a Logger
58
+ #
59
+ # @return [Logger]
60
+ #
61
+ def logger=(obj)
62
+ raise ArgumentError, "#{obj} should be a Logger" unless obj.is_a?(Logger)
63
+
64
+ @logger = obj
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SidekiqUniqueJobs
4
+ module Script
5
+ # Interface to dealing with .lua files
6
+ #
7
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
8
+ module DSL
9
+ MUTEX = Mutex.new
10
+
11
+ def self.included(base)
12
+ base.class_eval do
13
+ extend ClassMethods
14
+ end
15
+ end
16
+
17
+ #
18
+ # Module ClassMethods extends the base class with necessary methods
19
+ #
20
+ # @author Mikael Henriksson <mikael@zoolutions.se>
21
+ #
22
+ module ClassMethods
23
+ def execute(file_name, conn, keys: [], argv: [])
24
+ SidekiqUniqueJobs::Script::Client
25
+ .new(config)
26
+ .execute(file_name, conn, keys: keys, argv: argv)
27
+ end
28
+
29
+ # Configure the gem
30
+ #
31
+ # This is usually called once at startup of an application
32
+ # @param [Hash] options global gem options
33
+ # @option options [String, Pathname] :path
34
+ # @option options [Logger] :logger (default is Logger.new(STDOUT))
35
+ # @yield control to the caller when given block
36
+ def configure(options = {})
37
+ if block_given?
38
+ yield config
39
+ else
40
+ options.each do |key, val|
41
+ config.send(:"#{key}=", val)
42
+ end
43
+ end
44
+ end
45
+
46
+ #
47
+ # The current configuration (See: {.configure} on how to configure)
48
+ #
49
+ #
50
+ # @return [Script::Config] the gem configuration
51
+ #
52
+ def config
53
+ MUTEX.synchronize do
54
+ @config ||= Config.new
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SidekiqUniqueJobs
4
+ module Script
5
+ # Utility module for reducing the number of uses of logger.
6
+ #
7
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
8
+ module Logging
9
+ def self.included(base)
10
+ base.send(:extend, self)
11
+ end
12
+
13
+ #
14
+ # A convenience method for using the configured gem logger
15
+ #
16
+ # @see Script#.logger
17
+ #
18
+ # @return [Logger]
19
+ #
20
+ def logger
21
+ SidekiqUniqueJobs::Script.logger
22
+ end
23
+
24
+ #
25
+ # Logs a message at debug level
26
+ #
27
+ # @param [String, Exception] message_or_exception the message or exception to log
28
+ #
29
+ # @return [void]
30
+ #
31
+ # @yield [String, Exception] the message or exception to use for log message
32
+ #
33
+ def log_debug(message_or_exception = nil, &block)
34
+ logger.debug(message_or_exception, &block)
35
+ nil
36
+ end
37
+
38
+ #
39
+ # Logs a message at info level
40
+ #
41
+ # @param [String, Exception] message_or_exception the message or exception to log
42
+ #
43
+ # @return [void]
44
+ #
45
+ # @yield [String, Exception] the message or exception to use for log message
46
+ #
47
+ def log_info(message_or_exception = nil, &block)
48
+ logger.info(message_or_exception, &block)
49
+ nil
50
+ end
51
+
52
+ #
53
+ # Logs a message at warn level
54
+ #
55
+ # @param [String, Exception] message_or_exception the message or exception to log
56
+ #
57
+ # @return [void]
58
+ #
59
+ # @yield [String, Exception] the message or exception to use for log message
60
+ #
61
+ def log_warn(message_or_exception = nil, &block)
62
+ logger.warn(message_or_exception, &block)
63
+ nil
64
+ end
65
+
66
+ #
67
+ # Logs a message at error level
68
+ #
69
+ # @param [String, Exception] message_or_exception the message or exception to log
70
+ #
71
+ # @return [void]
72
+ #
73
+ # @yield [String, Exception] the message or exception to use for log message
74
+ #
75
+ def log_error(message_or_exception = nil, &block)
76
+ logger.error(message_or_exception, &block)
77
+ nil
78
+ end
79
+
80
+ #
81
+ # Logs a message at fatal level
82
+ #
83
+ # @param [String, Exception] message_or_exception the message or exception to log
84
+ #
85
+ # @return [void]
86
+ #
87
+ # @yield [String, Exception] the message or exception to use for log message
88
+ #
89
+ def log_fatal(message_or_exception = nil, &block)
90
+ logger.fatal(message_or_exception, &block)
91
+ nil
92
+ end
93
+ end
94
+ end
95
+ end