ResourceScope

Computation block for the Resource type. The Resource allows us to describe resources as immutable values, and compose them together in simple ways. This way you can split the logic of what a Resource is and how it should be closed from how you use them.

  • Using and composing Resource

import arrow.fx.coroutines.continuations.resource
import arrow.fx.coroutines.release

class UserProcessor {
fun start(): Unit = println("Creating UserProcessor")
fun shutdown(): Unit = println("Shutting down UserProcessor")
fun process(ds: DataSource): List<String> =
ds.users().map { "Processed $it" }
}

class DataSource {
fun connect(): Unit = println("Connecting dataSource")
fun users(): List<String> = listOf("User-1", "User-2", "User-3")
fun close(): Unit = println("Closed dataSource")
}

class Service(val db: DataSource, val userProcessor: UserProcessor) {
suspend fun processData(): List<String> = userProcessor.process(db)
}

//sampleStart
val userProcessor = resource {
UserProcessor().also(UserProcessor::start)
} release UserProcessor::shutdown

val dataSource = resource {
DataSource().also { it.connect() }
} release DataSource::close

suspend fun main(): Unit {
resource<Service> {
Service(dataSource.bind(), userProcessor.bind())
}.use { service -> service.processData() }
}
//sampleEnd

Functions

Link copied to clipboard
abstract suspend fun <A> Resource<A>.bind(): A
Link copied to clipboard
abstract suspend fun <A> install(acquire: suspend AcquireStep.() -> A, release: suspend (A, ExitCase) -> Unit): A

Install A into the ResourceScope. It's release function will be called with the appropriate ExitCase if this ResourceScope finishes. It results either in ExitCase.Completed, ExitCase.Cancelled or ExitCase.Failure depending on the terminal state of Resource lambda.

Link copied to clipboard
open infix suspend fun onRelease(release: suspend (ExitCase) -> Unit)
Link copied to clipboard
open infix suspend fun <A> Resource<A>.release(release: suspend (A) -> Unit): A

Composes a release action to a Resource value before binding.

Link copied to clipboard
open infix suspend fun <A> Resource<A>.releaseCase(release: suspend (A, ExitCase) -> Unit): A

Composes a releaseCase action to a Resource value before binding.

Extensions

Link copied to clipboard
suspend fun <A : AutoCloseable> ResourceScope.autoCloseable(closingDispatcher: CoroutineDispatcher = Dispatchers.IO, autoCloseable: suspend () -> A): A

Creates a Resource from an AutoCloseable, which uses AutoCloseable.close for releasing.

Link copied to clipboard
suspend fun <A : Closeable> ResourceScope.closeable(closingDispatcher: CoroutineDispatcher = Dispatchers.IO, closeable: suspend () -> A): A

Creates a Resource from an Closeable, which uses Closeable.close for releasing.

Link copied to clipboard
suspend fun ResourceScope.executor(timeout: Duration = Duration.INFINITE, closingDispatcher: CoroutineDispatcher = Dispatchers.IO, create: suspend () -> ExecutorService): ExecutorCoroutineDispatcher

Creates a single threaded CoroutineContext as a Resource. Upon release an orderly shutdown of the ExecutorService takes place in which previously submitted tasks are executed, but no new tasks will be accepted.

Link copied to clipboard
suspend fun ResourceScope.fixedThreadPoolContext(nThreads: Int, name: String): ExecutorCoroutineDispatcher

Creates a single threaded CoroutineContext as a Resource. Upon release an orderly shutdown of the ExecutorService takes place in which previously submitted tasks are executed, but no new tasks will be accepted.

Link copied to clipboard
suspend fun ResourceScope.singleThreadContext(name: String): ExecutorCoroutineDispatcher

Creates a single threaded CoroutineContext as a Resource. Upon release an orderly shutdown of the ExecutorService takes place in which previously submitted tasks are executed, but no new tasks will be accepted.