{
  "version": "https://jsonfeed.org/version/1",
  "title": "Sidekiq on enumerator.dev",
  "icon": "<no value>",
  "home_page_url": "https://enumerator.dev/",
  "feed_url": "https://enumerator.dev/feed.json",
  "items": [
      {
        "id": "https://enumerator.dev/migrating-from-standalone-sidekiq-to-an-activejob-adapter/",
        "title": "Migrating from Standalone Sidekiq to an ActiveJob Adapter",
        "content_html": "<p>I paired on this problem with my coworker <a href=\"https://www.linkedin.com/in/hannah-yeates/\">Hannah Yeates</a>. The examples below are from this pairing session. Thanks for working on this together, Hannah!</p>\n<hr>\n<p>I am working on a project right now that uses Sidekiq without the ActiveJob adapter. This means that our Sidekiq jobs look something like this:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-rb\" data-lang=\"rb\"><span class=\"line\"><span class=\"cl\"><span class=\"k\">class</span> <span class=\"nc\">ExampleWorker</span>\n</span></span><span class=\"line\"><span class=\"cl\">  <span class=\"kp\">include</span> <span class=\"no\">Sidekiq</span><span class=\"o\">::</span><span class=\"no\">Worker</span>\n</span></span><span class=\"line\"><span class=\"cl\">\n</span></span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">def</span> <span class=\"nf\">perform</span><span class=\"p\">(</span><span class=\"n\">arg</span><span class=\"p\">)</span>\n</span></span><span class=\"line\"><span class=\"cl\">    <span class=\"nb\">puts</span> <span class=\"s2\">&#34;Hello, the arg was </span><span class=\"si\">#{</span><span class=\"n\">arg</span><span class=\"si\">}</span><span class=\"s2\">&#34;</span>\n</span></span><span class=\"line\"><span class=\"cl\">  <span class=\"k\">end</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end</span>\n</span></span></code></pre></div><p>And we call them like this:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-rb\" data-lang=\"rb\"><span class=\"line\"><span class=\"cl\"><span class=\"no\">ExampleWorker</span><span class=\"o\">.</span><span class=\"n\">perform_async</span><span class=\"p\">(</span><span class=\"s2\">&#34;a nice arg&#34;</span><span class=\"p\">)</span>\n</span></span></code></pre></div><p>And in dev they&rsquo;ll execute like this:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-rb\" data-lang=\"rb\"><span class=\"line\"><span class=\"cl\"><span class=\"mi\">2024</span><span class=\"o\">-</span><span class=\"mo\">01</span><span class=\"o\">-</span><span class=\"mi\">17</span><span class=\"ss\">T15</span><span class=\"p\">:</span><span class=\"mo\">05</span><span class=\"p\">:</span><span class=\"mi\">31</span><span class=\"o\">.</span><span class=\"mi\">455</span><span class=\"n\">Z</span> <span class=\"n\">pid</span><span class=\"o\">=</span><span class=\"mi\">45599</span> <span class=\"n\">tid</span><span class=\"o\">=</span><span class=\"mi\">18</span><span class=\"n\">gj</span>\n</span></span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">class</span><span class=\"o\">=</span><span class=\"no\">TestWorker</span> \n</span></span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">jid</span><span class=\"o\">=</span><span class=\"mi\">8</span><span class=\"n\">d32dcd88b1de2ed3a5419eb</span> \n</span></span><span class=\"line\"><span class=\"cl\">  <span class=\"ss\">INFO</span><span class=\"p\">:</span> <span class=\"n\">start</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"no\">Hello</span><span class=\"p\">,</span> <span class=\"n\">the</span> <span class=\"n\">arg</span> <span class=\"n\">was</span> <span class=\"n\">foo</span>\n</span></span></code></pre></div><p>However, we want to switch over to <a href=\"https://github.com/bensheldon/good_job\">GoodJob</a> so that we have a transactionally safe background job processor. Our steps for doing this are:</p>\n<ol>\n<li>Set up Sidekiq as an ActiveJob adapter instead of using Sidekiq on its own.</li>\n<li>Install GoodJob and replace Sidekiq with GoodJob.</li>\n<li>Run Sidekiq and GoodJob in parallel so that Sidekiq finishes all the work in Redis.</li>\n<li>Shut down Sidekiq and remove it from the application code.</li>\n</ol>\n<p>This post is about step 1, making Sidekiq the ActiveJob adapter instead of using it on its own.</p>\n<h2 id=\"step-1--configure-activejob\">Step 1 : Configure ActiveJob</h2>\n<p>Our first step is to configure the application to use Sidekiq for ActiveJob</p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-rb\" data-lang=\"rb\"><span class=\"line\"><span class=\"cl\"><span class=\"c1\"># in application.rb</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"n\">config</span><span class=\"o\">.</span><span class=\"n\">active_job</span><span class=\"o\">.</span><span class=\"n\">queue_adapter</span> <span class=\"o\">=</span> <span class=\"ss\">:sidekiq</span>\n</span></span></code></pre></div><p>Then we created an empty <code>ApplicationJob</code> (more on this later).</p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-rb\" data-lang=\"rb\"><span class=\"line\"><span class=\"cl\"><span class=\"c1\"># application_job.rb</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"k\">class</span> <span class=\"nc\">ApplicationJob</span> <span class=\"o\">&lt;</span> <span class=\"no\">ActiveJob</span><span class=\"o\">::</span><span class=\"no\">Base</span>\n</span></span><span class=\"line\"><span class=\"cl\">  <span class=\"c1\"># leave this empty for now</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end</span>\n</span></span></code></pre></div><h2 id=\"step-2-convert-workers-to-applicationjob\">Step 2: Convert Workers to ApplicationJob</h2>\n<p>Next we updated our jobs to inherit from application job:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-rb\" data-lang=\"rb\"><span class=\"line\"><span class=\"cl\"><span class=\"k\">class</span> <span class=\"nc\">ExampleWorker</span> <span class=\"o\">&lt;</span> <span class=\"no\">ApplicationJob</span> <span class=\"c1\"># Add this</span>\n</span></span><span class=\"line\"><span class=\"cl\">  <span class=\"c1\"># remove this: include Sidekiq::Worker</span>\n</span></span><span class=\"line\"><span class=\"cl\">\n</span></span><span class=\"line\"><span class=\"cl\">  <span class=\"c1\"># The rest of the code remains the same</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"k\">end</span>\n</span></span></code></pre></div><p>And finally, we changed all our method calls from <code>ExampleWorker.perform_async(&quot;a nice arg&quot;)</code> to <code>ExampleWorker.perform_later(&quot;a nice arg&quot;)</code>.</p>\n<h2 id=\"step-3-see-what-breaks\">Step 3: See What Breaks</h2>\n<p>So far, so good! Next, we had a question: What happens when a job is enqueued by Sidekiq but processed by ActiveJob? To emulate this we:</p>\n<ol>\n<li>Booted a Rails console locally.</li>\n<li>Use the original code to enqueue a job.</li>\n<li>Modify the worker to use <code>ApplicationJob</code>.</li>\n<li>Boot Sidekiq locally and see what errors we get.</li>\n</ol>\n<p>In the real world, this would happen when the new code is deployed and there are jobs in the queue that were put there by Sidekiq. Here&rsquo;s the first error we got:</p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-fallback\" data-lang=\"fallback\"><span class=\"line\"><span class=\"cl\">WARN: NoMethodError: undefined method `jid=&#39; for #&lt;TestWorker:...&gt;\n</span></span></code></pre></div><p>We resolved this by creating an alias to <code>ActiveJob</code>&rsquo;s <code>provider_job_id=</code> and tested again. In the end we had three <code>NoMethodError</code> messages to resolve. We updated our <code>ApplicationJob</code> to respond to those methods.</p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-mysql\" data-lang=\"mysql\"><span class=\"line\"><span class=\"cl\"><span class=\"n\">class</span><span class=\"w\"> </span><span class=\"n\">ApplicationJob</span><span class=\"w\">\n</span></span></span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  </span><span class=\"n\">def</span><span class=\"w\"> </span><span class=\"n\">jid</span><span class=\"o\">=</span><span class=\"p\">(</span><span class=\"n\">arg</span><span class=\"p\">)</span><span class=\"w\">\n</span></span></span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    </span><span class=\"n\">provider_job_id</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"n\">arg</span><span class=\"w\">\n</span></span></span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  </span><span class=\"n\">end</span><span class=\"w\">\n</span></span></span><span class=\"line\"><span class=\"cl\"><span class=\"w\">\n</span></span></span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  </span><span class=\"n\">def</span><span class=\"w\"> </span><span class=\"n\">jid</span><span class=\"w\">\n</span></span></span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    </span><span class=\"n\">provider_job_id</span><span class=\"w\">\n</span></span></span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  </span><span class=\"n\">end</span><span class=\"w\">\n</span></span></span><span class=\"line\"><span class=\"cl\"><span class=\"w\">\n</span></span></span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  </span><span class=\"n\">def</span><span class=\"w\"> </span><span class=\"n\">bid</span><span class=\"o\">=</span><span class=\"p\">(</span><span class=\"n\">arg</span><span class=\"p\">);</span><span class=\"w\">\n</span></span></span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    </span><span class=\"c1\"># We are lucky to not need batching, so we let this return `nil`\n</span></span></span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  </span><span class=\"n\">end</span><span class=\"w\">\n</span></span></span><span class=\"line\"><span class=\"cl\"><span class=\"n\">end</span><span class=\"w\">\n</span></span></span></code></pre></div><h2 id=\"wrapping-up\">Wrapping Up</h2>\n<p>Making the switch to <code>ActiveJob</code> was easier than we expected. We now have a backwards compatible way of moving from standalone Sidekiq to ActiveJob. Our next step is to swap out Sidekiq for GoodJob.</p>\n<p>If you are planning on using GoodJob, or Solid Queue, check out this article on making the switch once you&rsquo;re using ActiveJob:</p>\n<p><a href=\"https://kylekeesling.com/posts/2024/01/migrating-from-sidekiq-to-solid-queue\">Migrating from Sidekiq to Solid Queue | Kyle Keesling</a></p>\n",
        "date_published": "2024-01-17T00:00:00+00:00",
        "url": "https://enumerator.dev/migrating-from-standalone-sidekiq-to-an-activejob-adapter/",
        "tags": ["sidekiq","activejob","ruby","rails"]
      }
  ]
}
