=== Execution Model

Jooby is a flexible, performant micro-framework that provides both blocking and non-blocking APIs for building web applications in Java and Kotlin.

In this chapter, we will cover the Jooby execution model, specifically:

* Executing code on the **event loop**.
* Safely executing **blocking code**.
* Working with **non-blocking types** like `CompletableFuture`, Reactive Streams, and Kotlin Coroutines.

==== Mode

===== Event Loop

The javadoc:ExecutionMode[EVENT_LOOP] mode allows you to run route handlers directly on the event loop (a.k.a. non-blocking mode).

.Java
[source,java,role="primary"]
----
import static io.jooby.ExecutionMode.EVENT_LOOP;
import static io.jooby.Jooby.runApp;

public class App extends Jooby {
  {
    get("/", ctx -> "I'm non-blocking!");
  }

  public static void main(String[] args) {
    runApp(args, EVENT_LOOP, App::new);
  }
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
import io.jooby.ExecutionMode.EVENT_LOOP
import io.jooby.kt.runApp

fun main(args: Array<String>) {
  runApp(args, EVENT_LOOP) {
    get("/") { "I'm non-blocking!" }
  }
}
----

The javadoc:ExecutionMode[EVENT_LOOP] mode is an advanced execution model that requires careful application design, because **BLOCKING IS STRICTLY FORBIDDEN** on the event loop thread.

**What if you need to block?**

The javadoc:Router[dispatch, java.lang.Runnable] operator shifts execution to a worker executor, which safely allows blocking calls (like database queries or remote service calls):

.Java
[source,java,role="primary"]
----
import static io.jooby.ExecutionMode.EVENT_LOOP;
import static io.jooby.Jooby.runApp;

public class App extends Jooby {
  {
    get("/", ctx -> "I'm non-blocking!");
  
    dispatch(() -> {
      // All routes defined inside this block are allowed to block:
      get("/db-list", ctx -> {
        // Safe to block!
        Object result = fetchFromDatabase(); 
        return result;
      });
    });
  }

  public static void main(String[] args) {
    runApp(args, EVENT_LOOP, App::new);
  }
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
import io.jooby.ExecutionMode.EVENT_LOOP
import io.jooby.kt.runApp

fun main(args: Array<String>) {
  runApp(args, EVENT_LOOP) {
    get("/") { "I'm non-blocking!" }
  
    dispatch {
      // All routes defined inside this block are allowed to block:
      get("/db-list") {
        // Safe to block!
        val result = fetchFromDatabase() 
        result
      }
    }
  }
}
----

By default, the `dispatch` operator moves execution to the default worker executor provided by the underlying web server.

However, you can provide your own custom worker executor at the application level or specifically for a single dispatch block:

.Java
[source,java,role="primary"]
----
import static io.jooby.ExecutionMode.EVENT_LOOP;
import static io.jooby.Jooby.runApp;
import java.util.concurrent.Executors;

public class App extends Jooby {
  {
    // Application-level executor
    worker(Executors.newCachedThreadPool());
  
    // Dispatches to the application-level executor (the cached thread pool)
    dispatch(() -> {
      // ...
    });
    
    // Dispatches to an explicit, custom executor
    var cpuIntensive = Executors.newSingleThreadExecutor();
    dispatch(cpuIntensive, () -> {
      // ...
    });
  }

  public static void main(String[] args) {
    runApp(args, EVENT_LOOP, App::new);
  }
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
import io.jooby.ExecutionMode.EVENT_LOOP
import io.jooby.kt.runApp
import java.util.concurrent.Executors

fun main(args: Array<String>) {
  runApp(args, EVENT_LOOP) {
  
    // Application-level executor
    worker(Executors.newCachedThreadPool())
  
    // Dispatches to the application-level executor (the cached thread pool)
    dispatch {
      // ...
    }
    
    // Dispatches to an explicit, custom executor
    val cpuIntensive = Executors.newSingleThreadExecutor()
    dispatch(cpuIntensive) {
      // ...
    }
  }
}
----

===== Worker

The javadoc:ExecutionMode[WORKER] mode allows you to make blocking calls from *any* route handler (a.k.a. blocking mode). You can write code sequentially without worrying about blocking the server.

.Java
[source, java,role="primary"]
----
import static io.jooby.ExecutionMode.WORKER;
import static io.jooby.Jooby.runApp;

public class App extends Jooby {
  {
    get("/", ctx -> {
      // Safe to block!
      Object result = fetchFromDatabase(); 
      return result;
    });
  }

  public static void main(String[] args) {
    runApp(args, WORKER, App::new);
  }
}
----

.Kotlin
[source, kotlin,role="secondary"]
----
import io.jooby.ExecutionMode.WORKER
import io.jooby.kt.runApp

fun main(args: Array<String>) {
  runApp(args, WORKER) {
    get("/") {
      // Safe to block!
      val result = fetchFromDatabase()
      result
    }
  }
}
----

Just like in `EVENT_LOOP` mode, you can override the default server worker and provide your own custom executor:

.Java
[source,java,role="primary"]
----
import static io.jooby.ExecutionMode.WORKER;
import static io.jooby.Jooby.runApp;
import java.util.concurrent.Executors;

public class App extends Jooby {
  {
    worker(Executors.newCachedThreadPool());
        
    get("/", ctx -> {
      // Safe to block! Handled by the cached thread pool.
      Object result = fetchFromDatabase(); 
      return result;
    });
  }

  public static void main(String[] args) {
    runApp(args, WORKER, App::new);
  }
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
import io.jooby.ExecutionMode.WORKER
import io.jooby.kt.runApp
import java.util.concurrent.Executors

fun main(args: Array<String>) {
  runApp(args, WORKER) {
    worker(Executors.newCachedThreadPool())
  
    get("/") {
      // Safe to block! Handled by the cached thread pool.
      val result = fetchFromDatabase()
      result
    }
  }
}
----

[NOTE]
====
When running in `WORKER` mode, Jooby implicitly applies a dispatch call to the worker executor for every route.
====

===== Default

The javadoc:ExecutionMode[DEFAULT] execution mode is a smart hybrid between the `WORKER` and `EVENT_LOOP` modes. As the name implies, **this is the default execution mode in Jooby**.

Jooby analyzes the return type of your route handler to determine which execution mode fits best.
If the response type is non-blocking, it executes on the event loop. Otherwise, it dispatches to the worker executor.

A response type is considered **non-blocking** if the route handler produces:

* A `CompletableFuture`
* An RxJava type (e.g., `Single`, `Flowable`)
* A Reactor type (e.g., `Mono`, `Flux`)
* A Kotlin Coroutine

.Java
[source, java,role="primary"]
----
import static io.jooby.Jooby.runApp;
import java.util.concurrent.CompletableFuture;

public class App extends Jooby {
  {
    get("/non-blocking", ctx -> {
      return CompletableFuture
          .supplyAsync(() -> "I'm non-blocking!"); // <1>    
    });
  
    get("/blocking", ctx -> {
      return "I'm blocking";                       // <2>
    });
  }

  public static void main(String[] args) {
    runApp(args, App::new);
  }
}
----

.Kotlin
[source, kotlin,role="secondary"]
----
import io.jooby.kt.runApp
import java.util.concurrent.CompletableFuture

fun main(args: Array<String>) {
  runApp(args) {
    get("/non-blocking") {
      CompletableFuture
          .supplyAsync { "I'm non-blocking!" }    // <1>    
    }
  
    get("/blocking") {
      "I'm blocking"                              // <2>
    }
  }
}
----

<1> `CompletableFuture` is a non-blocking type; this route executes directly on the **event loop**.
<2> `String` is a blocking type; this route is dispatched to the **worker executor**.

[TIP]
====
You are free to return non-blocking types while running in explicit `WORKER` or `EVENT_LOOP` modes. Non-blocking response types are not exclusive to `DEFAULT` mode; all `DEFAULT` mode does is dynamically decide whether to dispatch to a worker based on that return type.
====

==== Worker Executor

This section details the default worker executors provided by the underlying web servers. The worker executor is used when:

* The application mode is set to `WORKER` (or `DEFAULT` returning a blocking type).

* The application mode is set to `EVENT_LOOP` and an explicit `dispatch` block is used.

Each web server provides its own default worker executor tuning:

* **Netty:** The javadoc:netty.NettyServer[text=Netty server, artifact=jooby-netty] implementation multiplies the number of available processors (with a minimum of 2) by 8.
----
workerThreads = Math.max(Runtime.getRuntime().availableProcessors(), 2) * 8
----

* **Undertow:** The javadoc:undertow.UndertowServer[text=Undertow server, artifact=jooby-undertow] implementation multiplies the number of available processors by 8.
----
workerThreads = Runtime.getRuntime().availableProcessors() * 8
----

* **Jetty:** The javadoc:jetty.JettyServer[text=Jetty server, artifact=jooby-jetty] implementation uses a default configuration of **200** worker threads.

These are sensible defaults provided by the server implementations. If you need to increase or decrease the number of worker threads globally, you can configure the server:

.Java
[source,java,role="primary"]
----
{
  configureServer(server -> {
    server.setWorkerThreads(100);
  });
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  configureServer { server ->
    server.setWorkerThreads(100)
  }
}
----
