package io.trane.future; import java.util.Collection; /** * Interrupts provide a way to send signals to the current * pending `Promise` given a `Future` composition. It is a * mechanism that enables cancellations. For instance, * given this composition that involves an async boundary * (`userService.get`) and a continuation (`.map`): * * ```java * Future<String> username = * userService.get(userId).map(user -> user.username); * ``` * * It is possible to raise an interrupt that is received * by the `userService.get` `Promise`: * * ```java * username.raise(new TimeoutException); * ``` * * The `Promise` created by `userService.get` can define a * custom handler that performs an action in case an interrupt * is received. * * `Promise.apply` has overloaded methods that allow the user * to set the interrupt handler. This mechanism can be used * to cancel requests to remote systems, as Finagle does. * * The method `interruptible` is a shortcut to fail the * `Promise` if it receives any interrupt signal: * * ```java * Future<String> username = * userService.get(userId).interruptible().map(user -> user.username); * * username.raise(new TimeoutException); * ``` * * In this case, even if `userService.get` does not handle * interrupts, the `Promise` is satisfied with the interrupt * exception. * * The interrupt propagation happens through pointers from * each continuation to its parent that are created automatically * by the library. In the previous example, the `map` continuation * has a pointer to the `Promise` that is pending. */ @FunctionalInterface public interface InterruptHandler { /** * Creates an interrupt handle that calls multiple handlers. * * @param handlers list of handlers to be called. * @return the aggregate interrupt handler. */ public static InterruptHandler apply(final Collection<? extends InterruptHandler> handlers) { return ex -> { for (final InterruptHandler handler : handlers) handler.raise(ex); }; } /** * Creates an interrupt handler that calls to other handlers. * * @param h1 first handler to be called. * @param h2 second handler to be called. * @return the aggregate interrupt handler. */ public static InterruptHandler apply(final InterruptHandler h1, final InterruptHandler h2) { return ex -> { h1.raise(ex); h2.raise(ex); }; } /** * Raises an interrupt. * * @param ex the interrupt exception. */ void raise(Throwable ex); }