This is an automated email from the ASF dual-hosted git repository.
git-site-role pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/groovy-dev-site.git
The following commit(s) were added to refs/heads/asf-site by this push:
new e6f56df 2026/04/07 07:54:39: Generated dev website from
groovy-website@981616d
e6f56df is described below
commit e6f56df93d34770de32b42adafff76b850ff0b0f
Author: jenkins <[email protected]>
AuthorDate: Tue Apr 7 07:54:39 2026 +0000
2026/04/07 07:54:39: Generated dev website from groovy-website@981616d
---
blog/groovy-async-await.html | 102 ++++++++++++++++++++++++++++++++++++-------
search/search-index.json | 2 +-
2 files changed, 88 insertions(+), 16 deletions(-)
diff --git a/blog/groovy-async-await.html b/blog/groovy-async-await.html
index de7c63c..6b9f2f2 100644
--- a/blog/groovy-async-await.html
+++ b/blog/groovy-async-await.html
@@ -131,17 +131,23 @@ inside-out.</p>
<div class="paragraph">
<p>Variables are declared at the point of use. The return value is obvious.
No callbacks, no lambdas, no chained combinators. The method is a
-regular method — the caller decides whether to run it asynchronously:</p>
+regular method and called in the regular way:</p>
</div>
<div class="listingblock">
<div class="content">
-<pre class="prettyprint highlight"><code data-lang="groovy">// Run
asynchronously:
-def quest = await async { loadHeroQuest(token) }
-
-// Or call directly (blocking — fine on virtual threads):
+<pre class="prettyprint highlight"><code data-lang="groovy">// Call directly
(blocking — fine on virtual threads):
def quest = loadHeroQuest(token)</code></pre>
</div>
</div>
+<div class="paragraph">
+<p>The caller can choose to run it asynchronously if they want:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="prettyprint highlight"><code data-lang="groovy">// Or run
asynchronously:
+def quest = await async { loadHeroQuest(token) }</code></pre>
+</div>
+</div>
</div>
<div class="sect2">
<h3 id="_exception_handling_just_trycatch">Exception handling — just
<code>try</code>/<code>catch</code></h3>
@@ -186,7 +192,7 @@ the villain — all in parallel:</p>
var inventory = async { fetchInventory(heroId) }
var villain = async { fetchVillain(visibleVillainId) }
- var (s, inv, v) = await Awaitable.all(stats, inventory, villain)
+ var (s, inv, v) = await stats, inventory, villain
return new BattleScreen(s, inv, v)
}</code></pre>
</div>
@@ -265,6 +271,51 @@ with <code>success</code>, <code>value</code>, and
<code>error</code> fields.</p
</ul>
</div>
</div>
+<div class="sect2">
+<h3 id="_combinator_summary">Combinator summary</h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 14.2857%;">
+<col style="width: 28.5714%;">
+<col style="width: 28.5714%;">
+<col style="width: 28.5715%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top">Combinator</th>
+<th class="tableblock halign-left valign-top">Completes when</th>
+<th class="tableblock halign-left valign-top">On failure</th>
+<th class="tableblock halign-left valign-top">Use case</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p
class="tableblock"><code>Awaitable.all</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">All
succeed</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Fails
immediately on first failure (fail-fast)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Gather
results from independent tasks</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p
class="tableblock"><code>Awaitable.allSettled</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">All
complete (success or fail)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Never
throws; failures captured in <code>AwaitResult</code> list</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Inspect
every outcome, e.g. partial-success reporting</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p
class="tableblock"><code>Awaitable.any</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">First task
completes (success or failure)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Propagates
the first completion’s result or error</p></td>
+<td class="tableblock halign-left valign-top"><p
class="tableblock">Latency-sensitive races, fastest-response wins</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p
class="tableblock"><code>Awaitable.first</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">First task
succeeds, or all fail</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Throws
only when every source fails (aggregate error)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Hedged
requests, graceful degradation with fallbacks</p></td>
+</tr>
+</tbody>
+</table>
+</div>
</div>
</div>
<div class="sect1">
@@ -289,23 +340,40 @@ and the hero fights them as they arrive:</p>
}
def runDungeon(hero, dungeonId) {
- for await (wave in generateWaves(dungeonId)) {
+ for (wave in generateWaves(dungeonId)) {
wave.each { villain -> hero.fight(villain) }
}
}</code></pre>
</div>
</div>
<div class="paragraph">
-<p>The producer yields each wave on demand. The consumer pulls with
-<code>for await</code>. Natural <strong>back-pressure</strong> — the producer
blocks on each
+<p>The producer yields each wave on demand. The consumer pulls with a normal
for loop.
+Natural <strong>back-pressure</strong> — the producer blocks on each
<code>yield return</code> until the consumer is ready. No queues, signals, or
synchronization.</p>
</div>
<div class="paragraph">
-<p>Since generators return a standard <code>Iterable</code>, regular
<code>for</code> loops
-and Groovy collection methods (<code>collect</code>, <code>findAll</code>,
<code>take</code>) also
-work — <code>for await</code> is optional for generators but required for
-reactive types (Flux, Observable).</p>
+<p>Since generators return a standard <code>Iterable</code>, regular
<code>for</code> loops as shown above
+and other Groovy collection methods (<code>collect</code>,
<code>findAll</code>, <code>take</code>) also work.</p>
+</div>
+<div class="paragraph">
+<p>Other reactive libraries have different mechanisms for returning streaming
results.
+You can always use their native methods but Groovy’s <code>for
await</code> provides some
+syntactic sugar to make it more seamless:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="prettyprint highlight"><code data-lang="groovy">def
runDungeon(hero, dungeonId) {
+ for await (wave in generateWaves(dungeonId)) {
+ wave.each { villain -> hero.fight(villain) }
+ }
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The consumer pulls with <code>for await</code> instead of <code>for</code>
but no other changes are required.
+You can optionally use <code>for await</code> with the builtin generators, but
it’s required for
+other reactive types (Flux, Observable) if you want the Groovy async friendly
experience.</p>
</div>
</div>
</div>
@@ -595,8 +663,12 @@ asynchronous, with language-level support for streams,
cleanup,
structured concurrency, and framework bridging.</p>
</div>
<div class="paragraph">
-<p>Both approaches benefit from virtual threads on JDK 21+, and
-both can coexist in the same codebase.</p>
+<p>GPars' <code>callAsync()</code> and <code>asyncFun()</code> return futures
that work
+naturally with <code>await</code> and the <code>Awaitable</code> combinators,
so you
+can mix and match both styles in the same codebase.</p>
+</div>
+<div class="paragraph">
+<p>Both approaches benefit from virtual threads on JDK 21+.</p>
</div>
</div>
</div>
diff --git a/search/search-index.json b/search/search-index.json
index b0023da..f6ca838 100644
--- a/search/search-index.json
+++ b/search/search-index.json
@@ -261,7 +261,7 @@
{
"id": "blog/groovy-async-await.html",
"title": "The Apache Groovy programming language - Blogs - Async/await
for Groovy™",
- "content": "The Apache Groovy programming language - Blogs -
Async/await for Groovy™ Socialize Discuss on the mailing list Groovy on X
Groovy on Bluesky Groovy on Mastodon Groovy on LinkedIn Events and conferences
Source code on GitHub Report issues in Jira Stack Overflow questions Slack
Community You are using an outdated browser. Please upgrade your browser to
improve your experience. Apache Groovy™ Learn Documentation Download
Support Contribute Ecosystem Blog post [...]
+ "content": "The Apache Groovy programming language - Blogs -
Async/await for Groovy™ Socialize Discuss on the mailing list Groovy on X
Groovy on Bluesky Groovy on Mastodon Groovy on LinkedIn Events and conferences
Source code on GitHub Report issues in Jira Stack Overflow questions Slack
Community You are using an outdated browser. Please upgrade your browser to
improve your experience. Apache Groovy™ Learn Documentation Download
Support Contribute Ecosystem Blog post [...]
"url": "blog/groovy-async-await.html",
"site": "dev"
},