# Execution

Source: https://libtmux.org/en/scala/latest/guides/execution/

> Execution: io.github.libtmux:libtmux-scala_3 documentation.

The direct-style facade runs operations immediately. The Cats facade
constructs lazy effects: creating a read or mutation effect performs no tmux
I/O, and evaluating it again repeats the operation. Both delegate commands and
transport behavior to Java. Choose the [direct-style server][server] for
ordinary synchronous code or the [Cats server][cats-server] inside a managed
effect scope.

Here `config` is a Java [`ServerConfig`](<https://libtmux.org/en/java/latest/reference/io-github-libtmux-serverconfig-serverconfig/>) for an existing tmux server. The same
read effect observes the value present at each evaluation:

<!-- snippet: scala-io: execution-repeats-a-read -->
```scala
import _root_.cats.effect.IO
import io.github.libtmux.scaladsl.cats.{config => _, *}
import io.github.libtmux.scaladsl.cats.{Server => ScalaServer}

ScalaServer.resource[IO](config).use { server =>
  val name = "scala-guide-session"
  val read = server.hasSession(name)
  for {
    before <- read
    _ <- server.newSession(name)
    after <- read
    _ <- IO {
      assert(!before)
      assert(after)
    }
  } yield ()
}
```

Captured `info`, session windows, window panes, and client attachments are pure
reads: generated as plain values in both layers, never wrapped in `F` on the
Cats side, since the catalog marks them [`CAPTURED`](<https://libtmux.org/en/java/latest/reference/io-github-libtmux-catalog-kind-kind-captured/>). A captured accessor that
answers a tmux subsystem instead — [`Server.hooks`](<https://libtmux.org/en/scala/latest/reference/io-github-libtmux-scaladsl-server-hooks/>), [`Pane.options`](<https://libtmux.org/en/scala/latest/reference/io-github-libtmux-scaladsl-pane-options/>),
[`Server.shell`](<https://libtmux.org/en/scala/latest/reference/io-github-libtmux-scaladsl-server-shell/>), and the rest — is CAPTURED for the same reason, its own
construction touches no tmux state, but on the Cats side it answers that
subsystem's own wrapper class rather than the raw Java handle direct style
still returns; the subsystem's own reads and mutations then run through `F`
exactly as every other operation does. Filtering their immutable collections
does not refresh them. Listing, refresh, format expansion, pane mode
inspection, and mutation perform I/O. [`Pane.awaitText`](<https://libtmux.org/en/scala/latest/reference/io-github-libtmux-scaladsl-pane-awaittext/>) polls captured text.

## Admission and blocking work

Cats operations run through an [interruptible blocking boundary][execution],
including a server or control client's own acquisition step and every
subsystem operation reached through [`Server.hooks`](<https://libtmux.org/en/scala/latest/reference/io-github-libtmux-scaladsl-server-hooks/>), [`Pane.options`](<https://libtmux.org/en/scala/latest/reference/io-github-libtmux-scaladsl-pane-options/>), and the
rest. An owned server
accepts `maxConcurrentCalls` from one through four. A borrowed server accepts
a positive bound, but that bound covers only calls through that facade. Its
owner must account for other users and the underlying transport's capacity.

[`Pane.awaitText`](<https://libtmux.org/en/scala/latest/reference/io-github-libtmux-scaladsl-pane-awaittext/>) and [`Pane.await`](<https://libtmux.org/en/scala/latest/reference/io-github-libtmux-scaladsl-pane-await/>) reserve one facade call for work that can
release the wait (`Execution.waiting`), and require capacity of at least two.
[`Pane.run`](<https://libtmux.org/en/scala/latest/reference/io-github-libtmux-scaladsl-pane-run/>) uses ordinary admission: its private completion channel is normally
signalled by the pane's shell.

This bounds admitted calls; it does not make Java I/O thread-free. Waiting
operations occupy blocking workers, and process transport uses its own workers
to service child processes. The limit does not bound the number of fibers a
caller may queue. Use bounded effect traversal when submitting a large
collection. Ordered traversal preserves result order, while concurrent tmux
mutations can still reach the daemon in a different order.

Prompt cancellation depends on a borrowed transport honoring interruption and
completing its cleanup.

Command timeouts start when Java receives the operation, after Scala admission.
An effect timeout can bound admission and execution together, but cancellation
still waits for the operation's cleanup. A timeout is not a promise that a
dispatched mutation had no effect.

## Failures and cancellation

Ordinary failures preserve Java's exception and dispatch certainty: the sealed
[`LibTmuxException`](<https://libtmux.org/en/java/latest/reference/io-github-libtmux-exception-libtmuxexception-libtmuxexception/>) tree matches directly from Scala (see
[errors](https://github.com/libtmux/libtmux-java/blob/f56392b5d9bc7f1f9c1631842333fb90f3d82d40/docs/guide/scala.md)), and `DispatchException#safeToRetry`
answers the question a caller usually has without a catalog lookup. A
[`NOT_DISPATCHED`](<https://libtmux.org/en/java/latest/reference/io-github-libtmux-transport-dispatchoutcome-dispatchoutcome-not_dispatched/>) transport failure differs from `UNKNOWN`: the latter may have
changed tmux. Raw [`Server.cmd`](<https://libtmux.org/en/scala/latest/reference/io-github-libtmux-scaladsl-server-cmd/>) returns Java's own [`transport.CommandResult`](<https://libtmux.org/en/java/latest/reference/io-github-libtmux-transport-commandresult-commandresult/>), so
a nonzero exit remains data with its stdout and stderr.

Cats cancellation interrupts local work, waits for owned cleanup, and ends in
`Outcome.Canceled` whether or not the command reached tmux. Cancellation carries
no error, so the facade does not turn it into one. To learn whether a canceled
command was dispatched, set an [`OperationObserver`](<https://libtmux.org/en/java/latest/reference/io-github-libtmux-transport-operationobserver-operationobserver/>) on the Java [`ServerConfig`](<https://libtmux.org/en/java/latest/reference/io-github-libtmux-serverconfig-serverconfig/>):
the process transport reports `UNKNOWN` for a command it interrupted after
starting. Treat a canceled mutation as possibly dispatched; the facade does not
retry it, roll it back, or switch transports. A daemon-side shell job can
continue after its requesting client is canceled. Closing a borrowed transport
from its owner can instead produce an ordinary Java `UNKNOWN` failure.

## Control replies

[`Control.acknowledge`](<https://libtmux.org/en/scala/latest/reference/io-github-libtmux-scaladsl-cats-control-acknowledge/>) reports a [protocol reply][control]. [`accepted`](<https://libtmux.org/en/scala/latest/reference/io-github-libtmux-scaladsl-cats-control-ack-accepted/>) means a
successful reply frame arrived; deferred tmux work can still be running. Use a
separate completion signal for that work. Canceling an active control request
can close its attachment and affect queued requests and observations, so use
separate attachments when their lifetimes must be independent.

[`Control.isAlive`](<https://libtmux.org/en/scala/latest/reference/io-github-libtmux-scaladsl-cats-control-isalive/>) reports whether that process is still running.
[`Control.standardError`](<https://libtmux.org/en/scala/latest/reference/io-github-libtmux-scaladsl-cats-control-standarderror/>) is the text that process wrote to its error stream,
at most 4096 bytes. [`standardErrorTruncated`](<https://libtmux.org/en/scala/latest/reference/io-github-libtmux-scaladsl-cats-control-standarderrortruncated/>) says the stream continued past
that bound. [`Control.watch`](<https://libtmux.org/en/scala/latest/reference/io-github-libtmux-scaladsl-cats-control-watch/>) asks tmux to push a format when its value
changes, and [`unwatch`](<https://libtmux.org/en/scala/latest/reference/io-github-libtmux-scaladsl-cats-control-unwatch/>) removes that name. A target that is not a pane or
window id watches the attached session.

[server]: https://github.com/libtmux/libtmux-java/blob/f56392b5d9bc7f1f9c1631842333fb90f3d82d40/libtmux-scala/src/main/scala/io/github/libtmux/scaladsl/Server.scala
[cats-server]: https://github.com/libtmux/libtmux-java/blob/f56392b5d9bc7f1f9c1631842333fb90f3d82d40/libtmux-scala-cats/src/main/scala/io/github/libtmux/scaladsl/cats/Server.scala
[execution]: https://github.com/libtmux/libtmux-java/blob/f56392b5d9bc7f1f9c1631842333fb90f3d82d40/libtmux-scala-cats/src/main/scala/io/github/libtmux/scaladsl/cats/Execution.scala
[control]: https://github.com/libtmux/libtmux-java/blob/f56392b5d9bc7f1f9c1631842333fb90f3d82d40/libtmux-scala-cats/src/main/scala/io/github/libtmux/scaladsl/cats/Control.scala
