public interface Execution extends MutableRegistry
In a synchronous environment, a logical operation is typically given exclusive access to a thread for its duration. The use of thread local variables for operation global state and try/catch as a global error handling strategy rely on this. The execution construct provides mechanisms to emulate constructs of synchronous programming that cannot be achieved the same way in asynchronous programming.
Almost all work that occurs as part of a running Ratpack application happens during an execution.
Ratpack APIs such as Promise
, Blocking
etc. can only be used within an execution.
Request processing is always within an execution.
When initiating other work (e.g. background processing), an execution can be created via fork()
The term “execution segment” (sometimes just “segment”) is used to refer to a unit of work within an execution.
An execution segment has exclusive access to a thread.
All executions start with the segment given to the ExecStarter.start(Action)
method.
If the initial execution segment does not use any asynchronous APIs, the execution will be comprised of that single segment.
When an asynchronous API is used, via Promise.of(Upstream)
, the resumption of work when the result becomes available is within a new execution segment.
During any execution segment, the current()
method will return the current execution, giving global access to the execution object.
Segments of an execution are never executed concurrently.
Each execution is a MutableRegistry
.
Objects can be added to this registry and then later retrieved at any time during the execution.
The registry storage can be leveraged via an ExecInterceptor
to manage thread local storage for execution segments.
When starting an execution, a global error handler can be specified via ExecStarter.onError(Action)
.
The default error handler simply logs the error to a logger named ratpack.exec.Execution
.
The error handler for request processing executions forwards the exception to Context.error(Throwable)
.
The onComplete(AutoCloseable)
method can be used to register actions to invoke or resources to close when the execution completes.
ExecInterceptor
,
ExecInitializer
,
ExecController
,
Promise
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 executing execution.
|
static ExecStarter |
fork()
Used to create a new execution.
|
ExecController |
getController()
The execution controller that this execution is associated with.
|
EventLoop |
getEventLoop()
The specific event loop that this execution is using for compute operations.
|
static boolean |
isBlockingThread() |
static boolean |
isComputeThread() |
static boolean |
isManagedThread() |
void |
onComplete(AutoCloseable closeable)
Registers a closeable that will be closed when the execution completes.
|
remove, remove
backedBy, builder, empty, first, first, get, get, getAll, getAll, join, maybeGet, maybeGet, of, single, single, single, singleLazy
with
static Execution current() throws UnmanagedThreadException
UnmanagedThreadException
- if called from outside of an executionstatic ExecStarter fork() throws UnmanagedThreadException
This method obtains the thread bound ExecController
and simply calls ExecController.fork()
.
UnmanagedThreadException
- if there is no thread bound execution controller (i.e. this was called on a thread that is not managed by the Ratpack application)static boolean isManagedThread()
static boolean isComputeThread()
static boolean isBlockingThread()
ExecController getController()
EventLoop getEventLoop()
When integrating with asynchronous API that allows an executor to be specified that should be used to schedule the receipt of the value, use this executor.
void onComplete(AutoCloseable closeable)
Where possible, care should be taken to have the given closeable not throw exceptions. Any that are thrown will be logged and ignored.
closeable
- the resource to close when the execution completesdefault <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. 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.
It is generally preferable to register the interceptor in the server registry, or execution registry when starting, than using this method. That way, the interceptor can interceptor all of the execution.
execInterceptor
- the execution interceptor to addcontinuation
- the rest of the code to be executedException
- any thrown by continuation
ExecInterceptor