<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="288471" data-post-id="288471">
  <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="enkr1" data-post="282" 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/enkr1/48/25195_2.png" class="avatar"> enkr1:</div>
<blockquote>
<p>if my case is just to run a function at a specific date, which dep would be the best?</p>
</blockquote>
</aside>
<p>If you’re running on a cron-like schedule (e.g. the first of every month) then either one is viable. However, if you’re scheduling functions at a particular date on the fly (e.g. one day from now), then you’d want Oban.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="288471" 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/283">Post #282</a>
	                </div>
	            </div>
              <div id="likers-container-288471" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="288471"
                     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 #282"></div>
  </section>
</div>
    <div class="postbit" id="302905" data-post-id="302905">
  <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>Announcing releases on the forum slipped a little, but better late than never:</p>
<p><a href="https://hexdocs.pm/oban/2.16.0/changelog.html" rel="noopener nofollow ugc">Oban v2.16.0</a> was released (on 2023-09-22)!</p>
<h2><a name="p-302905-oban-instance-module-1" class="anchor" href="#p-302905-oban-instance-module-1" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/ewe.png?v=15" title=":ewe:" class="emoji" alt=":ewe:" loading="lazy" width="20" height="20"> Oban Instance Module</h2>
<p>New facade modules allow you to call <code>Oban</code> functions on instances with custom names, e.g. not <code>Oban</code>, without passing a <code>t:Oban.name/0</code> as the first argument.</p>
<p>For example, rather than calling <code>Oban.config/1</code> you’d call <code>MyOban.config/0</code>:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">MyOban.config()
</code></pre>
<p>It also makes piping into Oban functions far more convenient:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">%{some: :args}
|&gt; MyWorker.new()
|&gt; MyOban.insert()
</code></pre>
<h2><a name="p-302905-partial-matches-in-testing-assertions-2" class="anchor" href="#p-302905-partial-matches-in-testing-assertions-2" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/puzzle_piece.png?v=15" title=":puzzle_piece:" class="emoji" alt=":puzzle_piece:" loading="lazy" width="20" height="20"> Partial Matches in Testing Assertions</h2>
<p>It’s now possible to match a subset of fields on args or meta with <code>all_enqueued</code>, <code>assert_enqueued</code>, and <code>refute_enqueued</code>. For example, the following assertion will now pass:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># Given a job with these args: %{id: 123, mode: "active"}

assert_enqueued args: %{id: 123} #=&gt; true
assert_enqueued args: %{mode: "active"} #=&gt; true
assert_enqueued args: %{id: 321, mode: "active"} #=&gt; false
</code></pre>
<p>The change applies to <code>args</code> and <code>meta</code> queries for <code>all_enqueued/2</code>, <code>assert_enqueued/2</code> and <code>refute_enqueued/2</code> helpers.</p>
<h2><a name="p-302905-unique-timestamp-option-3" class="anchor" href="#p-302905-unique-timestamp-option-3" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/timer_clock.png?v=15" title=":timer_clock:" class="emoji" alt=":timer_clock:" loading="lazy" width="20" height="20"> Unique Timestamp Option</h2>
<p>Jobs are frequently scheduled for a time far in the future and it’s often desirable for to consider <code>scheduled</code> jobs for uniqueness, but unique jobs only checked the <code>:inserted_at</code> timestamp.</p>
<p>Now <code>unique</code> has a <code>timestamp</code> option that allows checking the <code>:scheduled_at</code> timestamp instead:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">use Oban.Worker, unique: [period: 120, timestamp: :scheduled_at]
</code></pre>
<h2><a name="p-302905-v2160-2023-09-22-4" class="anchor" href="#p-302905-v2160-2023-09-22-4" aria-label="Heading link" rel="nofollow"></a>v2.16.0 — 2023-09-22</h2>
<h3><a name="p-302905-bug-fixes-5" class="anchor" href="#p-302905-bug-fixes-5" aria-label="Heading link" rel="nofollow"></a>Bug Fixes</h3>
<ul>
<li>
<p>[Reindexer] Correct relname match for reindexer plugin</p>
<p>We can safely assume all indexes start with <code>oban_jobs</code>. The previous pattern was based on an outdated index format from older migrations.</p>
</li>
<li>
<p>[Testing] Support <code>repo</code>, <code>prefix</code>, and <code>log</code> query options in <code>use Oban.Testing</code></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="302905" 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/285">Post #284</a>
	                </div>
	            </div>
              <div id="likers-container-302905" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="302905"
                     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 #284"></div>
  </section>
</div>
    <div class="postbit" id="302906" data-post-id="302906">
  <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>To keep playing catch-up, Oban <a href="https://hexdocs.pm/oban/2.16.1/changelog.html" rel="noopener nofollow ugc">v2.16.1</a> and <a href="https://hexdocs.pm/oban/2.16.2/changelog.html" rel="noopener nofollow ugc">v2.16.2</a> are also released!</p>
<p><img src="https://forum.elixirforum.com/images/emoji/apple/shushing_face.png?v=15" title=":shushing_face:" class="emoji" alt=":shushing_face:" loading="lazy" width="20" height="20"> <em>Notice that v2.16.2 sneaks in a frequently requested wildcard matcher for test assertions</em></p>
<h2><a name="p-302906-v2162-2023-10-03-1" class="anchor" href="#p-302906-v2162-2023-10-03-1" aria-label="Heading link" rel="nofollow"></a>v2.16.2 — 2023-10-03</h2>
<h3><a name="p-302906-bug-fixes-2" class="anchor" href="#p-302906-bug-fixes-2" aria-label="Heading link" rel="nofollow"></a>Bug Fixes</h3>
<ul>
<li>
<p>[Testing] Match args/meta patterns in Elixir rather than the database</p>
<p>The containment operators, <code>@&gt;</code> and <code>&lt;@</code>, used for pattern matching in tests are only available in Postgres and have some quirks. Most notably, containment considers matching any value in a list a successful match, which isn’t intuitive or desirable.</p>
<p>The other issue with using a containment operator in tests is that SQLite doesn’t have those operators available and test helpers are shared between all engines.</p>
</li>
</ul>
<h3><a name="p-302906-enhancements-3" class="anchor" href="#p-302906-enhancements-3" aria-label="Heading link" rel="nofollow"></a>Enhancements</h3>
<ul>
<li>
<p>[Testing] Support wildcard matcher in patterns for args/meta</p>
<p>Now that we match in Elixir, it’s simple to support wildcard matching with a <code>:_</code> to assert that a key is present in a json field without specifying an exact value.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">assert_enqueued args: %{batch_id: :_, callback: true}
</code></pre>
</li>
</ul>
<h2><a name="p-302906-v2161-2023-09-25-4" class="anchor" href="#p-302906-v2161-2023-09-25-4" aria-label="Heading link" rel="nofollow"></a>v2.16.1 — 2023-09-25</h2>
<h3><a name="p-302906-bug-fixes-5" class="anchor" href="#p-302906-bug-fixes-5" aria-label="Heading link" rel="nofollow"></a>Bug Fixes</h3>
<ul>
<li>
<p>[Testing] Restore splitting out all config options in helpers.</p>
<p>Splitting all configuration keys is necessary when using <code>perform_job/3</code> with non-job options such as <code>:engine</code>.</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="302906" data-batch-url="/posts/batch_likers">
                        2
                      </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/286">Post #285</a>
	                </div>
	            </div>
              <div id="likers-container-302906" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="302906"
                     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 #285"></div>
  </section>
</div>
    <div class="postbit" id="310724" data-post-id="310724">
  <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><a href="https://github.com/sorentwo/oban/releases/tag/v2.17.0" rel="noopener nofollow ugc">Oban v2.17</a> is out!</p>
<p>This release includes an optional database migration to disable triggers and relax priority checks. See the <a href="https://hexdocs.pm/oban/v2-17.html" rel="noopener nofollow ugc">v2.17 upgrade guide</a> for step-by-step instructions.</p>
<h2><a name="p-310724-universal-insert-notifications-1" class="anchor" href="#p-310724-universal-insert-notifications-1" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/pager.png?v=15" title=":pager:" class="emoji" alt=":pager:" loading="lazy" width="20" height="20"> Universal Insert Notifications</h2>
<p>Historically, Oban used database triggers to emit a notification after a job is inserted. That allowed jobs to execute sooner, without waiting up to a second until the next poll event. Those triggers and subsequent notifications added some overhead to database operations bulk inserts into the same queue, despite deduplication logic in the trigger. Even worse, trigger notifications didn’t work behind connection poolers and were restricted to the Postgres notifier.</p>
<p>Now insert notifications have moved out of the database and into application code, so it’s possible to disable triggers without running database migrations, and they work for <em>any</em> notifier, not just Postgres.</p>
<p>Disable notifications with the <code>insert_trigger</code> option if sub-second job execution isn’t important or you’d like to reduce PubSub chatter:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">config :my_app, Oban,
  insert_trigger: false,
  ...
</code></pre>
<h2><a name="p-310724-worker-conveniences-2" class="anchor" href="#p-310724-worker-conveniences-2" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/factory_worker.png?v=15" title=":factory_worker:" class="emoji" alt=":factory_worker:" loading="lazy" width="20" height="20"> Worker Conveniences</h2>
<p>Workers received a few quality of life improvements to make defining <code>unique</code> behaviour more expressive and intuitive.</p>
<p>First, it’s now possible to define a job’s unique period with time units like <code>{1, :minute}</code> or <code>{2, :hours}</code>, just like a job’s <code>:schedule_in</code> option:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">use Oban.Worker, unique: [period: {5, :minutes}]
</code></pre>
<p>Second, you can set the <code>replace</code> option in <code>use Oban.Worker</code> rather than in an overridden <code>new/2</code> or as a runtime option. For example, to enable updating a job’s <code>scheduled_at</code> value on unique conflict:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">use Oban.Worker, unique: [period: 60], replace: [scheduled: [:scheduled_at]]
</code></pre>
<h2><a name="p-310724-oban-phoenix-notifier-3" class="anchor" href="#p-310724-oban-phoenix-notifier-3" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/phoenix.png?v=15" title=":phoenix:" class="emoji" alt=":phoenix:" loading="lazy" width="20" height="20"> Oban Phoenix Notifier</h2>
<p>The new <a href="https://github.com/sorentwo/oban_notifiers_phoenix" rel="noopener nofollow ugc"><code>oban_notifiers_phoenix</code> package</a> allows Oban to share a Phoenix application’s PubSub for notifications. In addition to centralizing PubSub communications, it opens up the possible transports to all PubSub adapters. As Oban already provides <code>Postgres</code> and <code>PG</code> (Distributed Erlang) notifiers, the new package primarily enables Redis notifications.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">config :my_app, Oban,
  notifier: {Oban.Notifiers.Phoenix, pubsub: MyApp.PubSub},
  ...
</code></pre>
<h2><a name="p-310724-ten-levels-of-job-priority-4" class="anchor" href="#p-310724-ten-levels-of-job-priority-4" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/level_slider.png?v=15" title=":level_slider:" class="emoji" alt=":level_slider:" loading="lazy" width="20" height="20"> Ten Levels of Job Priority</h2>
<p>Job priority may now be set to values between 0 (highest) and 9 (lowest). This increases the range from 4 to 10 possible priorities, giving applications much finer control over execution order.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">args
|&gt; MyApp.PrioritizedWorker.new(priority: 9)
|&gt; Oban.insert()
</code></pre>
<h3><a name="p-310724-enhancements-5" class="anchor" href="#p-310724-enhancements-5" aria-label="Heading link" rel="nofollow"></a>Enhancements</h3>
<ul>
<li>
<p>[Oban] Add <code>Oban.pause_all_queues/2</code> and <code>Oban.resume_all_queues/2</code>.</p>
<p>Pause and resume all queues with a single function call and a single notification signal, rather than manually looping through all queues and issuing separate calls.</p>
</li>
<li>
<p>[Cron] Add non-raising <code>Expression.parse/2</code> for use in <code>Cron.parse/2</code> and shared validations.</p>
<p>Multiple locations used <code>parse!</code> and converted a raised exception into an error tuple. That was inefficient, repetitive, and violated the common practice of avoiding exceptions for flow control.</p>
</li>
<li>
<p>[Validation] Use schema based validation for workers, plugins, and config.</p>
<p>Validations are now simpler and more consistent, and behaviour based notifiers such as Engine, Repo, and Peer are more descriptive.</p>
</li>
<li>
<p>[Engine] Expand telemetry meta for all engine callbacks events.</p>
<p>All callbacks now include every argument in telemetry event metadata. In some situations, e.g. <code>:init</code>, this simplifies testing and can be used to eliminate the need to poll a supervision tree to see which queues started.</p>
</li>
<li>
<p>[Notifier] Add <code>Isolated</code> notifier for local use and simplified testing.</p>
<p>Using PG for async tests has occasional flakes due to its eventually consistent nature. In tests and single node systems, we don’t need to broadcast messages between instances or nodes, and a simplified “isolated” mechanism is ideal.</p>
</li>
<li>
<p>[Repo] Add <code>Repo.query!/4</code> for <code>Ecto.Repo</code> parity</p>
</li>
<li>
<p>[Migration] Configure a third-party engine’s migrator using the repo’s <code>config</code> map.</p>
</li>
</ul>
<h3><a name="p-310724-bug-fixes-6" class="anchor" href="#p-310724-bug-fixes-6" aria-label="Heading link" rel="nofollow"></a>Bug Fixes</h3>
<ul>
<li>
<p>[Cron] Guard against invalid cron range expressions where the left side is greater than the right, e.g. <code>SAT-FRI</code>.</p>
</li>
<li>
<p>[Testing] Disable the <code>prefix</code> by default in generated testing helpers.</p>
<p>A prefix is only necessary when it’s not the standard “public” prefix, which is rarely the case in testing helpers. This makes it easier to use testing helpers with the <code>Lite</code> engine.</p>
</li>
<li>
<p>[Testing] Remove <code>prefix</code> segment from <code>assert_enqueued</code> error messages.</p>
<p>Not all engines support a prefix and the assert/refute message in testing helpers is confusing when the prefix is <code>nil</code>.</p>
</li>
</ul>
<h3><a name="p-310724-deprecations-7" class="anchor" href="#p-310724-deprecations-7" aria-label="Heading link" rel="nofollow"></a>Deprecations</h3>
<ul>
<li>[Gossip] The Gossip plugin is no longer needed, and shouldn’t be used, by applications running Oban Web v2.10 or above.</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="310724" data-batch-url="/posts/batch_likers">
                        9
                      </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/289">Post #288</a>
	                </div>
	            </div>
              <div id="likers-container-310724" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="310724"
                     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 #288"></div>
  </section>
</div>
    <div class="postbit" id="335567" data-post-id="335567">
  <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><a href="https://github.com/sorentwo/oban/releases/tag/v2.18.0" rel="noopener nofollow ugc">Oban v2.18</a> is out!</p>
<h2><a name="p-335567-queue-shutdown-telemetry-1" class="anchor" href="#p-335567-queue-shutdown-telemetry-1" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/telescope.png?v=15" title=":telescope:" class="emoji" alt=":telescope:" loading="lazy" width="20" height="20"> Queue Shutdown Telemetry</h2>
<p>A new queue shutdown event, <code>[:oban, :queue, :shutdown]</code>, is emitted by each queue when it terminates. The event originates from the <code>watchman</code> process, which tracks the total ellapsed time from when termination starts to when all jobs complete or the allotted period is exhausted.</p>
<p>Any jobs that take longer than the <code>:shutdown_grace_period</code> (by default 15 seconds) are brutally killed and left as orphans. The ids of jobs left in an executing state are listed in the event’s <code>orphaned</code> meta.</p>
<p>This also adds <code>queue:shutdown</code> logging to the default logger. Only queues that shutdown with orphaned jobs are logged, which makes it easier to detect orphaned jobs and which jobs were affected:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">[
  message: "jobs were orphaned because they didn't finish executing in the allotted time",
  queue: "alpha",
  source: "oban",
  event: "queue:shutdown",
  ellapsed: 500,
  orphaned: [101, 102, 103]
]
</code></pre>
<h2><a name="p-335567-distributed-postgresql-support-2" class="anchor" href="#p-335567-distributed-postgresql-support-2" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/delivery_truck.png?v=15" title=":delivery_truck:" class="emoji" alt=":delivery_truck:" loading="lazy" width="20" height="20"> Distributed PostgreSQL Support</h2>
<p>It’s now possible to run Oban in distributed PostgreSQL databases such as <a href="https://www.yugabyte.com/" rel="noopener nofollow ugc">Yugabyte</a>. This is made possible by a few simple changes to the <code>Basic</code> engine, and a new <code>unlogged</code> migration option.</p>
<p>Some PostgreSQL compatible databases don’t support unlogged tables. Making <code>oban_peers</code> unlogged isn’t a requirement for Oban to operate, so it can be disabled with a migration flag:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule MyApp.Repo.Migrations.AddObanTables do
  use Ecto.Migration

  def up do
    Oban.Migration.up(version: 12, unlogged: false)
  end
end
</code></pre>
<h2><a name="p-335567-job-observability-3" class="anchor" href="#p-335567-job-observability-3" aria-label="Heading link" rel="nofollow"></a><img src="https://forum.elixirforum.com/images/emoji/apple/brain.png?v=15" title=":brain:" class="emoji" alt=":brain:" loading="lazy" width="20" height="20"> Job Observability</h2>
<p>Job <code>stop</code> and <code>exception</code> telemetry now includes the reported memory and total reductions from the job’s process. Values are pulled with <code>Process.info/2</code> after the job executes and safely fall back to <code>0</code> in the event the process has crashed. Reductions are a rough proxy for CPU load, and the new measurements will make it easier to identify computationally expensive or memory hungry jobs.</p>
<p>In addition, thanks to the addition of <code>Process.set_label</code> in recent Elixir versions, the worker name is set as the job’s process label. That makes it possible to identify which job is running in a <code>pid</code> via observer or live dashboard.</p>
<h2><a name="p-335567-v2180-2024-07-26-4" class="anchor" href="#p-335567-v2180-2024-07-26-4" aria-label="Heading link" rel="nofollow"></a>v2.18.0 — 2024-07-26</h2>
<h3><a name="p-335567-enhancements-5" class="anchor" href="#p-335567-enhancements-5" aria-label="Heading link" rel="nofollow"></a>Enhancements</h3>
<ul>
<li>
<p>[Job] Support simple <code>unique: true</code> and <code>unique: false</code> declarations</p>
<p>Uniqueness can now be enabled with <code>unique: true</code> and disabled with <code>unique: false</code> from job options or a worker definition. The <code>unique: true</code> option uses all the standard defaults, but sets the period to <code>:infinity</code> for compatibility with Oban Pro’s new <code>simple</code> unique mode.</p>
</li>
<li>
<p>[Cron] Remove forced uniqueness when inserting scheduled jobs.</p>
<p>Using uniqueness by default prevents being able to use the Cron plugin with databases that don’t support uniqueness because of advisory locks. Luckily, uniqueness hasn’t been necessary for safe cron insertion since leadership was introduced and scheduling changed to top-of-the-minute <em>many</em> versions ago.</p>
</li>
<li>
<p>[Engine] Introduce <code>check_available/1</code> engine callback</p>
<p>The <code>check_available/1</code> callback allows engines to customize the query used to find jobs in the <code>available</code> state. That makes it possible for alternative engines, such Oban Pro’s Smart engine, to check for available jobs in a fraction of the time with large queues.</p>
</li>
<li>
<p>[Peer] Add <code>Oban.Peer.get_leader/2</code> for checking leadership</p>
<p>The <code>get_leader/2</code> function makes it possible to check which node is currently the leader regardless of the Peer implementation, and without having to query the database.</p>
</li>
<li>
<p>[Producer] Log a warning for unhandled producer messages.</p>
<p>Some messages are falling through to the catch-all <code>handle_info/2</code> clause. Previously, they were silently ignored and it degraded producer functionality because inactive jobs with dead pids were still tracked as <code>running</code> in the producer.</p>
</li>
<li>
<p>[Oban] Use structured messages for most logger warnings.</p>
<p>A standard structure for warning logs makes it easier to search for errors or unhandled messages from Oban or a particular module.</p>
</li>
</ul>
<h3><a name="p-335567-bug-fixes-6" class="anchor" href="#p-335567-bug-fixes-6" aria-label="Heading link" rel="nofollow"></a>Bug Fixes</h3>
<ul>
<li>
<p>[Job] Include all fields in the unique section of <code>Job.t/0</code>.</p>
<p>The unique spec lacked types for both <code>keys</code> and <code>timestamp</code> keys.</p>
</li>
<li>
<p>[Basic] Remove <code>materialized</code> option from <code>fetch_jobs/3</code>.</p>
<p>The <code>MATERIALIZED</code> clause for CTEs didn’t make a meaningful difference in job fetching accuracy. In some situations it caused a performance regression (which is why it was removed from Pro’s Smart engine a while ago).</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="335567" data-batch-url="/posts/batch_likers">
                        3
                      </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/290">Post #289</a>
	                </div>
	            </div>
              <div id="likers-container-335567" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="335567"
                     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 #289"></div>
  </section>
</div>
    <div class="postbit" id="336653" data-post-id="336653">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>from where to learn oban</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="336653" 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/291">Post #290</a>
	                </div>
	            </div>
              <div id="likers-container-336653" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="336653"
                     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 #290"></div>
  </section>
</div>
    <div class="postbit" id="336680" data-post-id="336680">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sorenone" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sorenone/120/34656_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sorenone
                  </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>We’ll post this in another thread.<br>
We’re actively working on an Oban 101 training release.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="336680" data-batch-url="/posts/batch_likers">
                        3
                      </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/292">Post #291</a>
	                </div>
	            </div>
              <div id="likers-container-336680" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="336680"
                     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 #291"></div>
  </section>
</div>
    <div class="postbit" id="336750" data-post-id="336750">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>any existing resources? that will be too late.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="336750" 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/293">Post #292</a>
	                </div>
	            </div>
              <div id="likers-container-336750" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="336750"
                     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 #292"></div>
  </section>
</div>
    <div class="postbit" id="340715" data-post-id="340715">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hey <a class="mention" href="/u/sorentwo" rel="nofollow">@sorentwo</a> I would like to know if there is a way to test job cancellation in unit tests.</p>
<p>I want to know if I can trap the <code>{:EXIT, pid, :shutdown}</code> message  from a <code>perform/1</code> callback to execute some code becore calling <code>exit(:shutdown)</code>.</p>
<p>Problem is that if I keep <code>config :my_app, Oban, testing: :manual</code> in the test config (which is useful for a lot of tests), calling <code>Oban.start_queue/1</code> and/or <code>Oban.resume_queue/1</code> in the test setup and <code>Oban.stop_queue/1</code> in the <code>on_exit</code> callback do not seem to have effect. The queue does not seem to run. Should it ?</p>
<p>I tried to check with <code>Oban.check_queue</code> but I get a <code>:noproc</code> error on <code>gen_server:call</code>.</p>
<p>Is there a way to test trapping the cancellation ?</p>
<p>Thank you.</p>
<p>edit: I guess I’ll just send a fake <code>{:EXIT, pid, :shutdown}</code> message for now.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="340715" 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/294">Post #293</a>
	                </div>
	            </div>
              <div id="likers-container-340715" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="340715"
                     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 #293"></div>
  </section>
</div>
    <div class="postbit" id="340733" data-post-id="340733">
  <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="lud" data-post="294" 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/lud/48/14382_2.png" class="avatar"> lud:</div>
<blockquote>
<p>I guess I’ll just send a fake <code>{:EXIT, pid, :shutdown}</code> message for now.</p>
</blockquote>
</aside>
<p>Sending an exit message manually is what I’d recommend for OSS. If your goal is to trap it to log, or run some side effect, and you have access to Pro then I recommend using a <a href="https://oban.pro/docs/pro/1.5.0-rc.3/Oban.Pro.Worker.html#module-worker-hooks" rel="noopener nofollow ugc">worker hook</a> instead.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="340733" data-batch-url="/posts/batch_likers">
                        2
                      </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/295">Post #294</a>
	                </div>
	            </div>
              <div id="likers-container-340733" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="340733"
                     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 #294"></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=30">Load more posts (21 remaining)</a>
</div></template></turbo-stream>