<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Adrian Studio]]></title><description><![CDATA[Adrian Studio]]></description><link>https://adrianstudio3.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>Adrian Studio</title><link>https://adrianstudio3.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sat, 03 Oct 2026 12:39:59 GMT</lastBuildDate><atom:link href="https://adrianstudio3.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[A notification timeout can hide a successful send]]></title><description><![CDATA[Disclosure: I sell the Notification Failure Lab linked below. This article was drafted with AI and checked against the lab’s published scope.
A notification worker can time out after the provider has ]]></description><link>https://adrianstudio3.hashnode.dev/a-notification-timeout-can-hide-a-successful-send</link><guid isPermaLink="true">https://adrianstudio3.hashnode.dev/a-notification-timeout-can-hide-a-successful-send</guid><category><![CDATA[Java]]></category><category><![CDATA[spring-boot]]></category><category><![CDATA[Testing]]></category><category><![CDATA[distributed systems]]></category><dc:creator><![CDATA[Adrian Studio]]></dc:creator><pubDate>Fri, 02 Oct 2026 08:32:35 GMT</pubDate><content:encoded><![CDATA[<p>Disclosure: I sell the Notification Failure Lab linked below. This article was drafted with AI and checked against the lab’s published scope.</p>
<p>A notification worker can time out after the provider has already accepted its request. If the worker treats every timeout as a confirmed failure, its next attempt can create a duplicate.</p>
<p>A useful test begins with the order of events:<br />1. The provider records acceptance.<br />2. The response does not reach the worker.<br />3. The worker must decide what to do with an uncertain result.</p>
<p>A fake that throws before acceptance tests a different failure. To expose the duplicate risk, make acceptance happen first.</p>
<p>Track three observations separately: calls made to the provider, effects accepted by the provider, and the worker’s recorded state. An exception describes what the caller observed. It does not establish what happened remotely.</p>
<p>Next, compare two retry policies.</p>
<p>With a provider that supports the required idempotency contract, use one stable identity for the logical notification. Keep that identity and the notification content unchanged across attempts. A newly generated identity on every retry makes it harder for the provider to recognize the same intended operation.</p>
<p>That guarantee remains conditional. Check the provider’s identity scope, retention period and behavior when a key is reused with different content. In a persistent worker, recovery also needs to preserve the operation’s identity.</p>
<p>Without a usable idempotency guarantee, an automatic resend after an ambiguous result may duplicate the effect. Preserve the uncertainty and keep it out of the ordinary resend path until stronger evidence or an explicit duplicate-risk policy resolves it.</p>
<p>Provider acceptance and final delivery should remain separate states. Acceptance alone does not prove that the recipient received the notification.</p>
<p>The same review should extend beyond the timeout:<br />- After committed work is recovered, can two workers compete for it safely under the implementation’s tested conditions?<br />- Can a duplicate receipt repeat a transition?<br />- Can a stale receipt move state backward?<br />- What evidence actually allows an uncertain outcome to become confirmed?</p>
<p>For a runnable first experiment, try the free Java sample: <a href="https://adrianstudio3.itch.io/notification-timeout-lab-free-java-sample">https://adrianstudio3.itch.io/notification-timeout-lab-free-java-sample</a>. It is a separate MIT-licensed, single-scenario Java 21 lab with seven checks against an in-process fake provider. It requires no third-party dependencies, database, Docker or network. All state is in memory; provider acceptance is not actual delivery.</p>
<p>Notification Failure Lab for Spring Boot packages these questions into educational Java and SQL source, synthetic fixtures, an intentionally broken baseline, a reference implementation and automated tests. It covers persisted-work recovery, accepted-request timeouts, and duplicate or out-of-order receipts.</p>
<p>The documented local run used PostgreSQL 16.15 through Testcontainers: 15 tests passed, with none skipped. Three passing baseline tests demonstrate intentional defects; twelve exercise reference behavior. A green suite therefore requires reading what the tests assert.</p>
<p>The kit is source-only and requires JDK 21, Docker and initial dependency/image downloads. It uses an in-process fake provider. Recovery reconstructs a store after commit; it does not terminate and restart a JVM. External fencing, authenticated receipt adapters, retry budgets, operational reconciliation tooling and multi-tenant isolation are outside its scope. It does not certify production readiness or universal exactly-once delivery.</p>
<p>The Notification Failure Lab <a href="https://adrianstudio3.gumroad.com/l/iqwjwr">https://adrianstudio3.gumroad.com/l/iqwjwr</a> is USD29 once for one named purchaser.</p>
]]></content:encoded></item></channel></rss>