Skip to content

while_executing with on_conflict: :reschedule reschedules job when unlock fails #770

@dsander

Description

@dsander

Hi there! 👋

I am not 100% sure if this really is a bug or if I am not understanding the use case.

Describe the bug

def execute(&block)
with_logging_context do
executed = locksmith.execute do
yield
callback_safely if locksmith.unlock
ensure
locksmith.unlock
end
unless executed
reflect(:execution_failed, item)
call_strategy(origin: :server, &block)

Because executed captures the return value of the locksmith.execute block it will be falsy when the unlock operation failed (and when callback_safely returns something fasly?).

We noticed the behaviour on v7 with a sidekiq version that changed the redis key that hold the busy workers (#756), in our case this lead to a job being run over and over because unlock failed (the reaper deleted the lock of the running job).

Expected behavior

The server server strategy should only be called when the job lock could not be acquired, not when the unlock failed (successfully 😉 )

Maybe something like this?

      def execute(&block)
        with_logging_context do
          executed = false
          locksmith.execute do
            yield
            executed = true
            callback_safely if locksmith.unlock
          ensure
            locksmith.unlock
          end

          unless executed
            reflect(:execution_failed, item)
            call_strategy(origin: :server, &block)
          end
        end
      end

Worker class

class MyWorker
  include Sidekiq::Worker

  sidekiq_options queue: :assets, retry: false, lock: :while_executing, on_conflict: :reschedule
  
  ....
end

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions