Interface AsyncScope

All Superinterfaces:
AutoCloseable
All Known Implementing Classes:
DefaultAsyncScope

public interface AsyncScope extends AutoCloseable
A structured concurrency scope that ensures all child tasks complete (or are cancelled) before the scope exits.

AsyncScope provides a bounded lifetime for async tasks, following the structured concurrency model. Unlike fire-and-forget async { ... }, tasks launched within a scope are guaranteed to complete before the scope closes. This prevents:

  • Orphaned tasks that outlive their logical parent
  • Resource leaks from uncollected async work
  • Silent failures from unobserved exceptions

By default, the scope uses a fail-fast policy: when any child task completes exceptionally, all sibling tasks are cancelled immediately. The first failure becomes the primary exception; subsequent failures are added as suppressed exceptions.


 def results = AsyncScope.withScope { scope ->
     def userTask  = scope.async { fetchUser(id) }
     def orderTask = scope.async { fetchOrders(id) }
     return [user: await(userTask), orders: await(orderTask)]
 }
 // Both tasks guaranteed complete here
 
Since:
6.0.0
See Also:
  • Method Summary

    Modifier and Type
    Method
    Description
    <T> Awaitable<T>
    async(Closure<T> body)
    Launches a child task within this scope.
    <T> Awaitable<T>
    async(Supplier<T> supplier)
    Launches a child task using a Supplier for Java interop.
    void
    Cancels all child tasks.
    void
    Closes the scope, waiting for all child tasks to complete.
    static AsyncScope
    Creates a new scope with the default executor and fail-fast enabled.
    static AsyncScope
    create(Executor executor)
    Creates a new scope with the given executor and fail-fast enabled.
    static AsyncScope
    create(Executor executor, boolean failFast)
    Creates a new scope with the given executor and failure policy.
    static AsyncScope
    Returns the scope currently bound to this thread, or null.
    int
    Returns the number of tracked child tasks (including completed ones that have not yet been pruned).
    static <T> T
    withCurrent(AsyncScope scope, Supplier<T> supplier)
    Executes the supplier with the given scope installed as current, restoring the previous binding afterwards.
    static <T> T
    withScope(Closure<T> body)
    Creates a scope, executes the closure within it, and ensures the scope is closed on exit.
    static <T> T
    withScope(Executor executor, Closure<T> body)
    Creates a scope with the given executor, executes the closure, and ensures the scope is closed on exit.
  • Method Details

    • async

      <T> Awaitable<T> async(Closure<T> body)
      Launches a child task within this scope. The task's lifetime is bound to the scope: when the scope is closed, all incomplete child tasks are cancelled.
      Type Parameters:
      T - the result type
      Parameters:
      body - the async body to execute
      Returns:
      an Awaitable representing the child task
      Throws:
      IllegalStateException - if the scope has already been closed
    • async

      <T> Awaitable<T> async(Supplier<T> supplier)
      Launches a child task using a Supplier for Java interop.
    • getChildCount

      int getChildCount()
      Returns the number of tracked child tasks (including completed ones that have not yet been pruned).
    • cancelAll

      void cancelAll()
      Cancels all child tasks.
    • close

      void close()
      Closes the scope, waiting for all child tasks to complete. If any child failed and fail-fast is enabled, remaining children are cancelled and the first failure is rethrown.
      Specified by:
      close in interface AutoCloseable
    • current

      static AsyncScope current()
      Returns the scope currently bound to this thread, or null.
    • withCurrent

      static <T> T withCurrent(AsyncScope scope, Supplier<T> supplier)
      Executes the supplier with the given scope installed as current, restoring the previous binding afterwards.
    • withScope

      static <T> T withScope(@ClosureParams(value=SimpleType.class,options="groovy.concurrent.AsyncScope") Closure<T> body)
      Creates a scope, executes the closure within it, and ensures the scope is closed on exit. The closure receives the scope as its argument for launching child tasks.
      
       def result = AsyncScope.withScope { scope ->
           def a = scope.async { computeA() }
           def b = scope.async { computeB() }
           return [await(a), await(b)]
       }
       
    • withScope

      static <T> T withScope(Executor executor, @ClosureParams(value=SimpleType.class,options="groovy.concurrent.AsyncScope") Closure<T> body)
      Creates a scope with the given executor, executes the closure, and ensures the scope is closed on exit.
    • create

      static AsyncScope create()
      Creates a new scope with the default executor and fail-fast enabled.
    • create

      static AsyncScope create(Executor executor)
      Creates a new scope with the given executor and fail-fast enabled.
    • create

      static AsyncScope create(Executor executor, boolean failFast)
      Creates a new scope with the given executor and failure policy.