Package ratpack.exec

Class Blocking


  • public abstract class Blocking
    extends Object
    Facilitates working with code that blocks (e.g. synchronous IO)
    • Method Detail

      • get

        public static <T> Promise<T> get​(Factory<T> factory)
        Performs a blocking operation on a separate thread, returning a promise for its value.

        This method should be used to perform blocking IO, or to perform any operation that synchronously waits for something to happen. The given factory function will be executed on a thread from a special pool for such operations (i.e. not a thread from the main compute event loop).

        The operation should do as little computation as possible. It should just perform the blocking operation and immediately return the result. Performing computation during the operation will degrade performance.

        Type Parameters:
        T - the type of value created by the operation
        Parameters:
        factory - the operation that blocks
        Returns:
        a promise for the return value of the given blocking operation
      • on

        public static <T> T on​(Promise<T> promise)
                        throws Exception
        Blocks execution waiting for this promise to complete and returns the promised value.

        This method allows the use of asynchronous API, by synchronous API. This may occur when integrating with other libraries that are not asynchronous. The following example simulates using a library that takes a callback that is expected to produce a value synchronously, but where the production of the value is actually asynchronous.

        
         import ratpack.test.exec.ExecHarness;
         import ratpack.exec.ExecResult;
         import ratpack.exec.Blocking;
         import ratpack.exec.Promise;
         import ratpack.func.Factory;
        
         import static org.junit.jupiter.api.Assertions.assertEquals;
        
         public class Example {
           static <T> T produceSync(Factory<? extends T> factory) throws Exception {
             return factory.create();
           }
        
           public static void main(String... args) throws Exception {
             ExecResult<String> result = ExecHarness.yieldSingle(e ->
               Blocking.get(() ->
                 produceSync(() ->
                   Blocking.on(Promise.value("foo")) // block and wait for the promised value
                 )
               )
             );
        
             assertEquals("foo", result.getValue());
           }
         }
         

        Important: this method can only be used inside a Blocking function. That is, it can only be used from a Ratpack managed blocking thread. If it is called on a non Ratpack managed blocking thread it will immediately throw an ExecutionException.

        When this method is called, the promise will be subscribed to on a compute thread while the blocking thread waits. When the promised value has been produced, and the compute thread segment has completed, the value will be returned allowing execution to continue on the blocking thread. The following example visualises this flow by capturing the sequence of events via an ExecInterceptor.

        
         import ratpack.test.exec.ExecHarness;
         import ratpack.exec.Blocking;
         import ratpack.exec.Promise;
         import ratpack.exec.ExecResult;
         import ratpack.exec.ExecInterceptor;
        
         import java.util.List;
         import java.util.ArrayList;
         import java.util.Arrays;
        
         import static org.junit.jupiter.api.Assertions.assertEquals;
        
         public class Example {
           public static void main(String... args) throws Exception {
             List<String> events = new ArrayList<>();
        
             ExecHarness.yieldSingle(
               r -> r.add(ExecInterceptor.class, (execution, execType, continuation) -> {
                 events.add(execType + "-start");
                 try {
                   continuation.execute();
                 } finally {
                   events.add(execType + "-stop");
                 }
               }),
               e -> Blocking.get(() -> Blocking.on(Promise.value("foo")))
             );
        
             List<String> actualEvents = Arrays.asList(
               "COMPUTE-start",
               "COMPUTE-stop",
                 "BLOCKING-start",
                   "COMPUTE-start",
                   "COMPUTE-stop",
                 "BLOCKING-stop",
               "COMPUTE-start",
               "COMPUTE-stop"
             );
        
             assertEquals(actualEvents, events);
           }
         }
         
        Type Parameters:
        T - the type of value returned by the promise
        Parameters:
        promise - the promise to block on
        Returns:
        the promised value
        Throws:
        ExecutionException - if not called on a Ratpack managed blocking thread
        Exception - any thrown while producing the value
      • exec

        public static void exec​(Block block)