<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="264145" data-post-id="264145">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="laiboonh" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/laiboonh/120/8524_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  laiboonh
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Ok this kinda make sense thanks</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="264145" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/oban-reliable-and-observable-job-processing/22449/273">Post #272</a>
	                </div>
	            </div>
              <div id="likers-container-264145" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="264145"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #272"></div>
  </section>
</div>
    <div class="postbit" id="276049" data-post-id="276049">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sorentwo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sorentwo/120/37360_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sorentwo
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Oban Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Oban v2.14 has been released!</p>
<h2><a name="p-276049-sqlite3-support-with-the-lite-engine-1" class="anchor" href="#p-276049-sqlite3-support-with-the-lite-engine-1" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/feather.png?v=15" title=":feather:" class="emoji" alt=":feather:" loading="lazy" width="20" height="20"> SQLite3 Support with the Lite Engine</h2>
<p>Increasingly, developers are choosing SQLite for small to medium-sized projects, not just in the<br>
embedded space where it’s had utility for many years. Many of Oban’s features, such as isolated<br>
queues, scheduling, cron, unique jobs, and observability, are valuable in smaller or embedded<br>
environments. That’s why we’ve added a new SQLite3 storage engine to bring Oban to smaller,<br>
stand-alone, or embedded environments where PostgreSQL isn’t ideal (or possible).</p>
<p>There’s frighteningly little configuration needed to run with SQLite3. Migrations, queues, and<br>
plugins all “Just Work™”.</p>
<p>To get started, add the <code>ecto_sqlite3</code> package to your deps and configure Oban to use the<br>
<code>Oban.Engines.Lite</code> engine:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">config :my_app, Oban,
  engine: Oban.Engines.Lite,
  queues: [default: 10],
  repo: MyApp.Repo
</code></pre>
<p>Presto! Run the migrations, include Oban in your application’s supervision tree, and then start<br>
inserting and executing jobs as normal.</p>
<p><img src="https://forum.elixirforum.com/images/emoji/apple/warning.png?v=15" title=":warning:" class="emoji" alt=":warning:" loading="lazy" width="20" height="20"> SQLite3 support is new, and while not experimental, there may be sharp edges. Please report any<br>
issues or gaps in documentation.</p>
<h2><a name="p-276049-smarter-job-fetching-2" class="anchor" href="#p-276049-smarter-job-fetching-2" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/woman_scientist.png?v=15" title=":woman_scientist:" class="emoji" alt=":woman_scientist:" loading="lazy" width="20" height="20"> Smarter Job Fetching</h2>
<p>The most common cause of “jobs not processing” is when PubSub isn’t available. Our troubleshooting<br>
section instructed people to investigate their PubSub and optionally include the <code>Repeater</code><br>
plugin. That kind of manual remediation isn’t necessary now! Instead, we automatically switch back<br>
to local polling mode when PubSub isn’t available—if it is a temporary glitch, then fetching<br>
returns to the optimized global mode after the next health check.</p>
<p>Along with smarter fetching, <code>Stager</code> is no longer a plugin. It wasn’t ever <em>really</em> a plugin, as<br>
it’s core to Oban’s operation, but it was treated as a plugin to simplify configuration and<br>
testing. If you’re in the minority that tweaked the staging interval, don’t worry, the existing<br>
plugin configuration is automatically translated for backward compatibility. However, if you’re a<br>
stickler for avoiding deprecated options, you can switch to the top-level <code>stage_interval</code>:</p>
<pre data-code-wrap="diff"><code class="lang-diff">config :my_app, Oban,
  queues: [default: 10],
- plugins: [{Stager, interval: 5_000}]
+ stage_interval: 5_000
</code></pre>
<h2><a name="p-276049-comprehensive-telemetry-data-3" class="anchor" href="#p-276049-comprehensive-telemetry-data-3" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/satellite_antenna.png?v=15" title=":satellite_antenna:" class="emoji" alt=":satellite_antenna:" loading="lazy" width="20" height="20"> Comprehensive Telemetry Data</h2>
<p>Oban has exposed telemetry data that allows you to collect and track metrics about jobs and queues<br>
since the very beginning. Telemetry events followed a job’s lifecycle from insertion through<br>
execution. Still, there were holes in the data—it wasn’t possible to track the exact state of your<br>
entire Oban system through telemetry data.</p>
<p>Now that’s changed. All operations that change job state, whether inserting, deleting, scheduling,<br>
or processing jobs report complete state-change events for <em>every</em> job including <code>queue</code>, <code>state</code>,<br>
and <code>worker</code> details. Even bulk operations such as <code>insert_all_jobs</code>, <code>cancel_all_jobs</code>, and<br>
<code>retry_all_jobs</code> return a subset of fields for <em>all modified jobs</em>, rather than a simple count.</p>
<p>See the <a rel="nofollow">2.14 upgrade guide</a> for step-by-step instructions (all two of them).</p>
<h3><a name="p-276049-enhancements-4" class="anchor" href="#p-276049-enhancements-4" aria-label="Heading link" rel="nofollow"></a>Enhancements</h3>
<ul>
<li>
<p>[Oban] Store a <code>{:cancel, :shutdown}</code> error and emit <code>[:oban, :job, :stop]</code> telemetry when jobs<br>
are manually cancelled with <code>cancel_job/1</code> or <code>cancel_all_jobs/1</code>.</p>
</li>
<li>
<p>[Oban] Include “did you mean” suggestions for <code>Oban.start_link/1</code> and all nested plugins when a<br>
similar option is available.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">Oban.start_link(rep: MyApp.Repo, queues: [default: 10])
** (ArgumentError) unknown option :rep, did you mean :repo?
    (oban 2.14.0-dev) lib/oban/validation.ex:46: Oban.Validation.validate!/2
    (oban 2.14.0-dev) lib/oban/config.ex:88: Oban.Config.new/1
    (oban 2.14.0-dev) lib/oban.ex:227: Oban.start_link/1
    iex:1: (file)
</code></pre>
</li>
<li>
<p>[Oban] Support scoping queue actions to a particular node.</p>
<p>In addition to scoping to the current node with <code>:local_only</code>, it is now possible to scope<br>
<code>pause</code>, <code>resume</code>, <code>scale</code>, <code>start</code>, and <code>stop</code> queues on a single node using the <code>:node</code><br>
option.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">Oban.scale_queue(queue: :default, node: "worker.123")
</code></pre>
</li>
<li>
<p>[Oban] Remove <code>retry_job/1</code> and <code>retry_all_jobs/1</code> restriction around retrying <code>scheduled</code> jobs.</p>
</li>
<li>
<p>[Job] Restrict <code>replace</code> option to specific states when unique job’s have a conflict.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># Replace the scheduled time only if the job is still scheduled
SomeWorker.new(args, replace: [scheduled: [:schedule_in]], schedule_in: 60)

# Change the args only if the job is still available
SomeWorker.new(args, replace: [available: [:args]])
</code></pre>
</li>
<li>
<p>[Job] Introduce <code>format_attempt/1</code> helper to standardize error and attempt formatting<br>
across engines</p>
</li>
<li>
<p>[Repo] Wrap <em>nearly</em> all <code>Ecto.Repo</code> callbacks.</p>
<p>Now every <code>Ecto.Repo</code> callback, aside from a handful that are only used to manage a <code>Repo</code><br>
instance, are wrapped with code generation that omits any typespecs. Slight inconsistencies<br>
between the wrapper’s specs and <code>Ecto.Repo</code>’s own specs caused dialyzer failures when nothing<br>
was genuinely broken. Furthermore, many functions were missing because it was tedious to<br>
manually define every wrapper function.</p>
</li>
<li>
<p>[Peer] Emit telemetry events for peer leadership elections.</p>
<p>Both peer modules, <code>Postgres</code> and <code>Global</code>, now emit <code>[:oban, :peer, :election]</code> events during<br>
leader election. The telemetry meta includes a <code>leader?</code> field for start and stop events to<br>
indicate if a leadership change took place.</p>
</li>
<li>
<p>[Notifier] Allow passing a single channel to <code>listen/2</code> rather than a list.</p>
</li>
<li>
<p>[Registry] Add <code>lookup/2</code> for conveniently fetching registered <code>{pid, value}</code> pairs.</p>
</li>
</ul>
<h3><a name="p-276049-bug-fixes-5" class="anchor" href="#p-276049-bug-fixes-5" aria-label="Heading link" rel="nofollow"></a>Bug Fixes</h3>
<ul>
<li>
<p>[Basic] Capture <code>StaleEntryError</code> on unique replace.</p>
<p>Replacing while a job is updated externally, e.g. it starts executing, could occasionally raise<br>
an <code>Ecto.StaleEntryError</code> within the Basic engine. Now, that exception is translated into an<br>
error tuple and bubbles up to the <code>insert</code> call site.</p>
</li>
<li>
<p>[Job] Update <code>t:Oban.Job/0</code> to indicate timestamp fields are nullable.</p>
</li>
</ul>
<h3><a name="p-276049-deprecations-6" class="anchor" href="#p-276049-deprecations-6" aria-label="Heading link" rel="nofollow"></a>Deprecations</h3>
<ul>
<li>
<p>[Stager] Deprecate the <code>Stager</code> plugin as it’s part of the core supervision tree and may be<br>
configured with the top-level <code>stage_interval</code> option.</p>
</li>
<li>
<p>[Repeater] Deprecate the <code>Repeater</code> plugin as it’s no longer necessary with hybrid staging.</p>
</li>
<li>
<p>[Migration] Rename <code>Migrations</code> to <code>Migration</code>, but continue delegating functions for backward<br>
compatibility.</p>
</li>
</ul>
<p>From the <a href="https://hexdocs.pm/oban/2.14.0/changelog.html" rel="noopener nofollow ugc">CHANGELOG</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="276049" data-batch-url="/posts/batch_likers">
                        15
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/oban-reliable-and-observable-job-processing/22449/274">Post #273</a>
	                </div>
	            </div>
              <div id="likers-container-276049" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="276049"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #273"></div>
  </section>
</div>
    <div class="postbit" id="276054" data-post-id="276054">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="mindreframer" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mindreframer/120/25559_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  mindreframer
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Thanks, the SQLite support is awesome!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="276054" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/oban-reliable-and-observable-job-processing/22449/275">Post #274</a>
	                </div>
	            </div>
              <div id="likers-container-276054" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="276054"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #274"></div>
  </section>
</div>
    <div class="postbit" id="282182" data-post-id="282182">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="maz" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/maz/120/6075_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  maz
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Is there a way to have a particular job run every Monday, every 5 minutes for 6 hours(And not run any other time)?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="282182" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/oban-reliable-and-observable-job-processing/22449/276">Post #275</a>
	                </div>
	            </div>
              <div id="likers-container-282182" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="282182"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #275"></div>
  </section>
</div>
    <div class="postbit" id="282185" data-post-id="282185">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sorentwo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sorentwo/120/37360_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sorentwo
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Oban Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>There is: <code>*/5 0-6 * * 1</code> will do it. Take a look at a tool like crontab.guru to play around with schedules.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="282185" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/oban-reliable-and-observable-job-processing/22449/277">Post #276</a>
	                </div>
	            </div>
              <div id="likers-container-282185" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="282185"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #276"></div>
  </section>
</div>
    <div class="postbit" id="285054" data-post-id="285054">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sorentwo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sorentwo/120/37360_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sorentwo
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Oban Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Oban v2.15.0 has been released!</p>
<h2><a name="p-285054-notification-compression-1" class="anchor" href="#p-285054-notification-compression-1" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/clamp.png?v=15" title=":clamp:" class="emoji" alt=":clamp:" loading="lazy" width="20" height="20"> Notification Compression</h2>
<p>Oban uses notifications across most core functionality, from job staging to cancellation. Some notifications, such as gossip, contain massive redundancy that compresses nicely. For example, this table breaks down the compression ratios for a fairly standard gossip payload containing data from ten queues:</p>
<div class="md-table">
<table>
<thead>
<tr>
<th>Mode</th>
<th>Bytes</th>
<th>% of Original</th>
</tr>
</thead>
<tbody>
<tr>
<td>Original</td>
<td>4720</td>
<td>100%</td>
</tr>
<tr>
<td>Gzip</td>
<td>307</td>
<td>7%</td>
</tr>
<tr>
<td>Encode 64</td>
<td>412</td>
<td>9%</td>
</tr>
</tbody>
</table>
</div><p>Minimizing notification payloads is especially important for Postgres because it applies an 8kb limit to all messages. Now all pub/sub notifications are compressed automatically, with a safety mechanism for compatibility with external notifiers, namely Postgres triggers.</p>
<h2><a name="p-285054-query-improvements-2" class="anchor" href="#p-285054-query-improvements-2" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/card_file_box.png?v=15" title=":card_file_box:" class="emoji" alt=":card_file_box:" loading="lazy" width="20" height="20"> Query Improvements</h2>
<p>There has been an ongoing issue with systems recording a job attempt twice when it only executed once. While that sounds minor, it could break an entire queue when the attempt exceeded max attempts because it would violate a database constraint.</p>
<p>Apparently, the Postgres planner may choose to generate a plan that executes a nested loop over the LIMITing subquery, causing more UPDATEs than LIMIT. That could cause unexpected updates, including attempts &gt; max_attempts in some cases. The solution is to use a CTE as an “optimization fence” that forces Postgres <em>not</em> to optimize the query.</p>
<p>We also worked in a few additional query improvements:</p>
<ul>
<li>Use an index only scan for job staging to safely handle tables with millions of scheduled jobs.</li>
<li>Remove unnecessary row locking from staging and pruning queries.</li>
</ul>
<h2><a name="p-285054-new-engine-callbacks-for-sql-compatibility-3" class="anchor" href="#p-285054-new-engine-callbacks-for-sql-compatibility-3" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/feather.png?v=15" title=":feather:" class="emoji" alt=":feather:" loading="lazy" width="20" height="20"> New Engine Callbacks for SQL Compatibility</h2>
<p>We’re pleased to share improvements in Oban’s SQLite integration. A few SQLite pioneers identified pruning and staging compatibility bugs, and instead of simply patching around the issues with conditional logic, we tackled them with new engine callbacks: <code>stage_jobs/3</code> and <code>prune_jobs/3</code>. The result is safer, optimized queries for each specific database.</p>
<p>Introducing new engine callbacks with database-specific queries paves the way for working with other databases. There’s even an <a href="https://github.com/sorentwo/oban/issues/836" rel="noopener nofollow ugc">open issue for MySQL support</a>…</p>
<h2><a name="p-285054-v2150-2023-04-13-4" class="anchor" href="#p-285054-v2150-2023-04-13-4" aria-label="Heading link" rel="nofollow"></a>v2.15.0 — 2023-04-13</h2>
<h3><a name="p-285054-enhancements-5" class="anchor" href="#p-285054-enhancements-5" aria-label="Heading link" rel="nofollow"></a>Enhancements</h3>
<ul>
<li>
<p>[Oban] Use DynamicSupervisor to supervise queues for optimal shutdown</p>
<p>Standard supervisors shut down in a fixed order, which could make shutting down queues with active jobs and a lengthy grace period very slow. This switches to a <code>DynamicSupervisor</code> for queue supervision so queues can shut down simultaneously while still respecting the grace period.</p>
</li>
<li>
<p>[Executor] Retry acking infinitely after job execution</p>
<p>After jobs execute the producer must record their status in the database. Previously, if lacking failed due to a connection error after 10 retries it would orphan the job. Now, acking retries infinitely (with backoff) until the function succeeds. The result is stronger execution guarantees with backpressure during periods of database fragility.</p>
</li>
<li>
<p>[Oban] Accept a <code>Job</code> struct as well as a job id for <code>cancel_job/1</code> and <code>retry_job/1</code></p>
<p>Now it’s possible to write <code>Oban.cancel_job(job)</code> directly, rather than <code>Oban.cancel_job(job.id)</code>.</p>
</li>
<li>
<p>[Worker] Allow snoozing jobs for zero seconds.</p>
<p>Returning <code>{:snooze, 0}</code> immediately reschedules a job without any delay.</p>
</li>
<li>
<p>[Notifier] Accept arbitrary channel names for notifications, e.g. “my-channel”</p>
</li>
<li>
<p>[Telemetry] Add ‘detach_default_logger/0’ to programmatically disable an attached logger.</p>
</li>
<li>
<p>[Testing] Avoid unnecessary query for “happy path” assertion errors in <code>assert_enqueued/2</code></p>
</li>
<li>
<p>[Testing] Inspect charlists as lists in testing assertions</p>
<p>Args frequently contain lists of integers like <code>[123]</code>, which was curiously displayed as <code>'{'</code>.</p>
</li>
</ul>
<h3><a name="p-285054-bug-fixes-6" class="anchor" href="#p-285054-bug-fixes-6" aria-label="Heading link" rel="nofollow"></a>Bug Fixes</h3>
<ul>
<li>
<p>[Executor] Correctly raise “unknown worker” errors.</p>
<p>Unknown workers triggered an unknown case error rather than the appropriate “unknown worker” runtime error.</p>
</li>
<li>
<p>[Testing] Allow <code>assert_enqueued</code> with a <code>scheduled_at</code> time for <code>available</code> jobs</p>
<p>The use of <code>Job.new</code> to normalize query fields would change assertions with a “scheduled_at” date to <em>only</em> check scheduled, never “available”</p>
</li>
<li>
<p>[Telemetry] Remove <code>:worker</code> from engine and plugin query meta.</p>
<p>The <code>worker</code> isn’t part of any query indexes and prevents optimal index usage.</p>
</li>
<li>
<p>[Job] Correct priority type to cover default of 0</p>
</li>
</ul> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="285054" data-batch-url="/posts/batch_likers">
                        8
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/oban-reliable-and-observable-job-processing/22449/278">Post #277</a>
	                </div>
	            </div>
              <div id="likers-container-285054" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="285054"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #277"></div>
  </section>
</div>
    <div class="postbit" id="287983" data-post-id="287983">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="crova" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/crova/120/25853_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  crova
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Is this still the case <a class="mention" href="/u/sorentwo" rel="nofollow">@sorentwo</a> ?</p>
<p>Sorry to ping you, but I ask because I’m starting a job during application boot (inside <code>start/2</code> from <code>application.ex</code>) and, no matter what I try with <code>unique</code>, I keep getting 2 jobs when the application starts (deploying to Fly with 2 machines).</p>
<p>So I was wondering if this is what is happening here.</p>
<p>Let me know if you want more context.</p>
<p>Cheers.</p>
<p>(and thanks for the awesome work)</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="287983" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/oban-reliable-and-observable-job-processing/22449/279">Post #278</a>
	                </div>
	            </div>
              <div id="likers-container-287983" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="287983"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #278"></div>
  </section>
</div>
    <div class="postbit" id="288041" data-post-id="288041">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sorentwo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sorentwo/120/37360_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sorentwo
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Oban Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="crova" data-post="279" data-topic="22449">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/crova/48/25853_2.png" class="avatar"> crova:</div>
<blockquote>
<p>Is this still the case <a class="mention" href="/u/sorentwo" rel="nofollow">@sorentwo</a> ?</p>
</blockquote>
</aside>
<p>It’s true, cron jobs are unique for 59 seconds by default. However, you can override the unique period and there’s now a leadership mechanism to ensure only one node enqueues cron jobs.</p>
<aside class="quote no-group" data-username="crova" data-post="279" data-topic="22449">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/crova/48/25853_2.png" class="avatar"> crova:</div>
<blockquote>
<p>Sorry to ping you, but I ask because I’m starting a job during application boot (inside <code>start/2</code> from <code>application.ex</code>) and, no matter what I try with <code>unique</code>, I keep getting 2 jobs when the application starts (deploying to Fly with 2 machines).</p>
<p>So I was wondering if this is what is happening here.</p>
</blockquote>
</aside>
<p>How are you starting a job during boot? Is it an <code>@reboot</code> cron job? What are the unique settings? There isn’t enough information for me to help diagnose your issue.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="288041" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/oban-reliable-and-observable-job-processing/22449/280">Post #279</a>
	                </div>
	            </div>
              <div id="likers-container-288041" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="288041"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #279"></div>
  </section>
</div>
    <div class="postbit" id="288161" data-post-id="288161">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="crova" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/crova/120/25853_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  crova
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Thanks for getting back to me and confirming the first question.</p>
<p>Sorry I wasn’t more specific before.</p>
<p>This job does not rely on cron, I’m enqueuing it on start up like so, inside my <code>application.ex</code>:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule MyApp.Application do
  # See https://hexdocs.pm/elixir/Application.html
  # for more information on OTP Applications
  @moduledoc false

  use Application
  alias MyApp.Workers.MyWorker

  @impl true
  def start(_type, _args) do
    children = [
      # Start the Telemetry supervisor
      MyAppWeb.Telemetry,
      # Start the Ecto repository
      MyApp.Repo,
      # Start the PubSub system
      {Phoenix.PubSub, name: MyApp.PubSub},
      # Start Finch
      {Finch, name: MyApp.Finch},
      # Start the Endpoint (http/https)
      MyAppWeb.Endpoint,
      {Oban, Application.fetch_env!(:my_app, Oban)}
      # Start a worker by calling: MyApp.Worker.start_link(arg)
      # {MyApp.Worker, arg}
    ]

    # See https://hexdocs.pm/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: MyApp.Supervisor]
    result = Supervisor.start_link(children, opts)
    MyWorker.enqueue()
    result
  end

  # Tell Phoenix to update the endpoint configuration
  # whenever the application is updated.
  @impl true
  def config_change(changed, _new, removed) do
    MyAppWeb.Endpoint.config_change(changed, removed)
    :ok
  end
end
</code></pre>
<p>And the worker (simplfied version):</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule MyApp.Workers.MyWorker do
  use Oban.Worker, unique: [fields: [:queue, :worker], period: :infinity]

  def perform(_) do
    with :ok &lt;- do_some_stuff(),
         :ok &lt;- do_more_stuff() do
      enqueue()
    else
      error -&gt; error
    end

    :ok
  end
  
  def enqueue(args \\ %{}) do 
      args
      |&gt; Oban.Job.new(worker: __MODULE__)
      |&gt; Oban.insert!()
  end
end
</code></pre>
<p>I also tried to move the unique options to the <code>enqueue</code> function and got the same situation.<br>
As you can see, I’m not really passing any args, but I did try passing a dummy <code>job: :search</code> arg just so I could try and limit by that as well.</p>
<p>In any case, I managed to make it work using an insert helper function like you suggested <a href="https://sorentwo.com/2019/07/18/oban-recipes-part-1-unique-jobs.html" rel="noopener nofollow ugc">here</a>.</p>
<p>But now I’m wondering if my initial issue was due to job pruning, <a href="https://forum.elixirforum.com/t/unique-oban-jobs-with-period-still-seems-to-insert-into-db/52256" rel="nofollow">like we can see here</a>.</p>
<p>In any case, thank you again for all your work and help here.</p>
<p>Cheers.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="288161" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/oban-reliable-and-observable-job-processing/22449/281">Post #280</a>
	                </div>
	            </div>
              <div id="likers-container-288161" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="288161"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #280"></div>
  </section>
</div>
    <div class="postbit" id="288394" data-post-id="288394">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="enkr1" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/enkr1/120/25195_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  enkr1
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="sorentwo" data-post="122" data-topic="22449">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sorentwo/48/37360_2.png" class="avatar"> sorentwo:</div>
<blockquote>
<ul>
<li>Work without connected nodes. Quantum uses node communication for leadership, to prevent double-enqueuing a job.</li>
</ul>
</blockquote>
</aside>
<p>Hi,</p>
<p>if my case is just to run a function at a specific date, which dep would be the best?</p>
<p>Thank you so much!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="288394" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/oban-reliable-and-observable-job-processing/22449/282">Post #281</a>
	                </div>
	            </div>
              <div id="likers-container-288394" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="288394"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #281"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/22449/load_more?page=29">Load more posts (31 remaining)</a>
</div></template></turbo-stream>