Skip to content

Commit

Permalink
Release 0.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
adamw committed Jul 9, 2024
1 parent d22c4e4 commit c730d3f
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 7 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ the project!
To test Ox, use the following dependency, using either [sbt](https://www.scala-sbt.org):

```scala
"com.softwaremill.ox" %% "core" % "0.2.2"
"com.softwaremill.ox" %% "core" % "0.3.0"
```

Or [scala-cli](https://scala-cli.virtuslab.org):

```scala
//> using dep "com.softwaremill.ox::core:0.2.2"
//> using dep "com.softwaremill.ox::core:0.3.0"
```

Documentation is available at [https://ox.softwaremill.com](https://ox.softwaremill.com), ScalaDocs can be browsed at [https://javadoc.io](https://www.javadoc.io/doc/com.softwaremill.ox).
Expand Down
4 changes: 2 additions & 2 deletions generated-doc/out/basics/start-here.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

```scala
// sbt dependency
"com.softwaremill.ox" %% "core" % "0.2.2"
"com.softwaremill.ox" %% "core" % "0.3.0"

// scala-cli dependency
//> using dep "com.softwaremill.ox::core:0.2.2"
//> using dep "com.softwaremill.ox::core:0.3.0"
```

## Scope of the Ox project
Expand Down
20 changes: 20 additions & 0 deletions generated-doc/out/channels/transforming-sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,23 @@ When dealing with Sources with chunks of bytes or Strings, you can leverage foll
* `decodeStringUtf8` to decode a `Source[Chunk[Byte]]` into a `Source[String]`, without handling line breaks, just processing input bytes as UTF-8 characters, even if a multi-byte character is divided into two chunks.

Such operations may be useful when dealing with I/O like files, `InputStream`, etc.. See [examples here](io.md).

## Logging

Ox does not have any integrations with logging libraries, but it provides a simple way to log elements flowing through channels
using the `.tap` (eagerly evaluated) or `.tapAsView` (lazily evaluated) methods.

```scala
import ox.supervised
import ox.channels.Source

supervised {
Source.fromValues(1, 2, 3)
.tap(n => println(s"Received: $n")) // prints as soon as the element is sent from the source
.toList

Source.fromValues(1, 2, 3)
.tapAsView(n => println(s"Received: $n")) // prints when the element is consumed by `toList`
.toList
}
```
1 change: 1 addition & 0 deletions generated-doc/out/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ In addition to this documentation, ScalaDocs can be browsed at [https://javadoc.
:maxdepth: 2
:caption: Resiliency, I/O & utilities
oxapp
io
retries
resources
Expand Down
4 changes: 2 additions & 2 deletions generated-doc/out/io.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ To use the plugin, add the following settings to your sbt configuration:

```scala
autoCompilerPlugins := true
addCompilerPlugin("com.softwaremill.ox" %% "plugin" % "0.2.2")
addCompilerPlugin("com.softwaremill.ox" %% "plugin" % "0.3.0")
```

For scala-cli:

```scala
//> using plugin com.softwaremill.ox:::plugin:0.2.2
//> using plugin com.softwaremill.ox:::plugin:0.3.0
```

With the plugin enabled, the following code won't compile:
Expand Down
2 changes: 1 addition & 1 deletion generated-doc/out/kafka.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Dependency:

```scala
"com.softwaremill.ox" %% "kafka" % "0.2.2"
"com.softwaremill.ox" %% "kafka" % "0.3.0"
```

`Source`s which read from a Kafka topic, mapping stages and drains which publish to Kafka topics are available through
Expand Down
92 changes: 92 additions & 0 deletions generated-doc/out/oxapp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# OxApp

Ox provides a way to define application entry points in the "Ox way" using `OxApp` trait. Starting the app this way comes
with the benefit of the main `run` function being executed on a virtual thread, with a root `Ox` scope provided,
and application interruption handling built-in. The latter is handled using `Runtime.addShutdownHook` and will interrupt
the main virtual thread, should the app receive, for example, a SIGINT due to Ctrl+C being issued by the user.
Here's an example:

```scala
import ox.*
import scala.concurrent.duration.*

object MyApp extends OxApp:
def run(args: Vector[String])(using Ox): ExitCode =
forkUser {
sleep(500.millis)
println("Fork finished!")
}
println(s"Started app with args: ${args.mkString(", ")}!")
ExitCode.Success
```

The `run` function receives command line arguments as a `Vector` of `String`s, a given `Ox` capability and has to
return an `ox.ExitCode` value which translates to the exit code returned from the program. `ox.ExitCode` is defined as:

```scala
enum ExitCode(val code: Int):
case Success extends ExitCode(0)
case Failure(exitCode: Int = 1) extends ExitCode(exitCode)
```

There's also a simplified variant of `OxApp` for situations where you don't care about command line arguments.
The `run` function doesn't take any arguments beyond the root `Ox` scope capability, expects no `ExitCode` and will
handle any exceptions thrown by printing a stack trace and returning an exit code of `1`:

```scala
import ox.*

object MyApp extends OxApp.Simple:
def run(using Ox): Unit = println("All done!")
```

`OxApp` has also a variant that integrates with [either](basics/error-handling.md#boundary-break-for-eithers)
blocks for direct-style error handling called `OxApp.WithEitherErrors[E]`. Here, `E` is the type of errors from the
`run` function that you want to handle. The interesting bit is that `run` function in `OxApp.WithEitherErrors` receives
an `either` block token of type `EitherError[E]` (which itself is an alias for `Label[Either[E, ExitCode]]` as `either`
operates on boundary/break mechanism). Therefore, it's possible to use `.ok()` combinators directly in the `run`
function scope. `OxApp.WithEitherErrors` requires that one implements a function that translates application errors
into `ExitCode` instances. Here's an example that always fails and exits with exit code `23`:

```scala
import ox.*
import ox.either.*

sealed trait MyAppError
case class ComputationError(msg: String) extends Exception(msg) with MyAppError

object MyApp extends OxApp.WithEitherErrors[MyAppError]:
def doWork(): Either[MyAppError, Unit] = Left(ComputationError("oh no"))

def handleError(myAppError: MyAppError): ExitCode = myAppError match {
case ComputationError(_) => ExitCode.Failure(23)
}

def run(args: Vector[String])(using Ox, EitherError[MyAppError]): ExitCode =
doWork().ok() // will close the scope with MyAppError as `doWork` returns a Left
ExitCode.Success
```

## Additional configuration

All `ox.OxApp` instances can be configured by overriding the `def settings: AppSettings` method. For now `AppSettings`
contains only the `gracefulShutdownExitCode` setting that allows one to decide what exit code should be returned by
the application once it gracefully shutdowns after it was interrupted (for example Ctrl+C was pressed by the user).

By default `OxApp` will exit in such scenario with exit code `0` meaning successful graceful shutdown, but it can be
overridden:

```scala
import ox.*
import scala.concurrent.duration.*
import OxApp.AppSettings

object MyApp extends OxApp:
override def settings: AppSettings = AppSettings(
gracefulShutdownExitCode = ExitCode.Failure(130)
)

def run(args: Vector[String])(using Ox): ExitCode =
sleep(60.seconds)
ExitCode.Success
```

0 comments on commit c730d3f

Please sign in to comment.