public interface Execution extends MutableRegistry
Ratpack is non blocking.
This requires that IO and other blocking operations are performed asynchronously.
In completely synchronous execution, the thread and the call stack serve as the representation of a stream of execution,
with the execution being bound to a single thread exclusively for its entire duration.
The Execution
concept in Ratpack brings some of the characteristics of the traditional single-thread exclusive model
to the asynchronous, non-exclusive, environment.
A well understood example of a logical stream of execution in the web application environment is the handling of a request. This can be thought of as a single logical operation; the request comes in and processing happens until the response is sent back. Many web application frameworks exclusively assign a thread to such a stream of execution, from a large thread pool. If a blocking operation is performed during the execution, the thread sits waiting until it can continue (e.g. the IO completes, or the contended resource becomes available). Thereby the segments of the execution are serialized and the call stack provides execution context. Ratpack supports the non-blocking model, where threads do not wait. Instead of threads waiting for IO or some future event, they are returned to the “pool” to be used by other executions (and therefore the pool can be smaller). When the IO completes or the contended resource becomes available, execution continues with a new call stack and possibly on a different thread.
The execution object underpins an entire logical operation, even when that operation may be performed by multiple threads.
Importantly, it also serializes execution segments by way of the Promise.of(Upstream)
method.
These methods are fundamentally asynchronous in that they facilitate performing operations where the result will arrive later without waiting for the result,
but are synchronous in the operations the perform are serialized and not executed concurrently or in parallel.
Crucially, this means that state that is local to an execution does not need to be thread safe.
The execution object actually underpins the Context
objects that are used when handling requests.
It is rarely used directly when request handling, except when concurrency or parallelism is required to process data via the fork()
method.
Moreover, it provides its own error handling and completion mechanisms.
Modifier and Type | Method and Description |
---|---|
default <O> Execution |
add(Class<? super O> type,
O object)
Adds a registry entry that is available by the given type.
|
default Execution |
add(Object object)
Adds a registry entry.
|
default <O> Execution |
add(TypeToken<? super O> type,
O object)
Adds a registry entry that is available by the given type.
|
void |
addInterceptor(ExecInterceptor execInterceptor,
Block continuation)
Adds an interceptor that wraps the rest of the current execution segment and all future segments of this execution.
|
default <O> Execution |
addLazy(Class<O> type,
Supplier<? extends O> supplier)
Adds a lazily created entry to the registry.
|
<O> Execution |
addLazy(TypeToken<O> type,
Supplier<? extends O> supplier)
Adds a lazily created entry to the registry.
|
static Execution |
current()
Provides the currently execution execution.
|
static ExecBuilder |
fork() |
ExecController |
getController()
The execution controller that this execution is associated with.
|
EventLoop |
getEventLoop() |
void |
onCleanup(AutoCloseable autoCloseable) |
remove, remove
backedBy, builder, empty, first, first, get, get, getAll, getAll, join, maybeGet, maybeGet, of, single, single, single
addLazyAsync, addLazyAsync, with
static Execution current() throws UnmanagedThreadException
This method will fail when called outside of a Ratpack compute thread as it relies on ExecController.require()
.
UnmanagedThreadException
static ExecBuilder fork() throws UnmanagedThreadException
UnmanagedThreadException
ExecController getController()
EventLoop getEventLoop()
void onCleanup(AutoCloseable autoCloseable)
default <O> Execution add(Class<? super O> type, O object)
add
in interface RegistrySpec
O
- the public type of the registry entrytype
- the public type of the registry entryobject
- the actual registry entrydefault <O> Execution add(TypeToken<? super O> type, O object)
add
in interface RegistrySpec
O
- the public type of the registry entrytype
- the public type of the registry entryobject
- the actual registry entrydefault Execution add(Object object)
add
in interface RegistrySpec
object
- the object to add to the registrydefault <O> Execution addLazy(Class<O> type, Supplier<? extends O> supplier)
The supplier will be invoked exactly once, when a query is made to the registry of a compatible type of the given type.
addLazy
in interface RegistrySpec
O
- the public type of the registry entrytype
- the public type of the registry entrysupplier
- the supplier for creating the object when needed<O> Execution addLazy(TypeToken<O> type, Supplier<? extends O> supplier)
The supplier will be invoked exactly once, when a query is made to the registry of a compatible type of the given type.
addLazy
in interface RegistrySpec
O
- the public type of the registry entrytype
- the public type of the registry entrysupplier
- the supplier for creating the object when neededvoid addInterceptor(ExecInterceptor execInterceptor, Block continuation) throws Exception
The given action is executed immediately (i.e. as opposed to being queued to be executed as the next execution segment). Any code executed after a call to this method in the same execution segment WILL NOT be intercepted. Therefore, it is advisable to not execute any code after calling this method in a given execution segment.
See ExecInterceptor
for example use of an interceptor.
execInterceptor
- the execution interceptor to addcontinuation
- the rest of the code to be executedException
- any thrown by continuation
ExecInterceptor