Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/christopherdavenport/linebacker
Finally Tagless Blocking Implementation
https://github.com/christopherdavenport/linebacker
Last synced: 14 days ago
JSON representation
Finally Tagless Blocking Implementation
- Host: GitHub
- URL: https://github.com/christopherdavenport/linebacker
- Owner: ChristopherDavenport
- License: mit
- Created: 2018-03-27T14:50:14.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2022-05-24T22:19:08.000Z (over 2 years ago)
- Last Synced: 2024-10-23T08:54:36.866Z (23 days ago)
- Language: Scala
- Homepage: https://christopherdavenport.github.io/linebacker
- Size: 1.08 MB
- Stars: 94
- Watchers: 6
- Forks: 7
- Open Issues: 31
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# Linebacker [![Build Status](https://travis-ci.org/ChristopherDavenport/linebacker.svg?branch=master)](https://travis-ci.org/ChristopherDavenport/linebacker) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.chrisdavenport/linebacker_2.12/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.chrisdavenport/linebacker_2.12) [![Gitter chat](https://badges.gitter.im/christopherdavenport/linebacker.png)](https://gitter.im/christopherdavenport/linebacker)
Enabling Functional Blocking where you need it.
## Quick Start
To use linebacker in an existing SBT project with Scala 2.11 or a later version, add the following dependency to your
`build.sbt`:```scala
libraryDependencies += "io.chrisdavenport" %% "linebacker" % ""
```## Why Linebacker
Concurrency is hard.
## No Seriously, Why Linebacker
Generally threading models have to deal with the idea that in java/scala some of our fundamental calls
are still blocking. Looking at you JDBC! In order to handle this we generally utilize Executors or
ExecutionContexts. Additionally many libraries now utilize implicit execution contexts for their shifting.
This puts us in a position where we need to manually and explicitly pass around two contexts raising one
explicitly where appropriate and then shifting work back and forth from the pools as appropriate.Here is where we attempt to make these patterns easier. This library provides abstractions for managing
pools and shifting behavior between your pools.Why should you care? Let us propose you have a single pool on 5 threads and you receive 5 requests that
require communicating with a database. What happens if a 6th call comes in when all these CPU bound threads
are blocked on network IO? Obviously we are waiting for threads.Some additional resources for why this is important:
Thread pool best practices.
— Impure Pics (@impurepics) April 21, 2018
For more info, see @djspiewak & @alexelcu posts:https://t.co/pr6McpU3tHhttps://t.co/Vz617IMjRB pic.twitter.com/gJgzZI6yGJ- [Thread Pools](https://gist.github.com/djspiewak/46b543800958cf61af6efa8e072bfd5c) by Daniel Spiewak
- [Best Practice: Should Not Block Threads](https://monix.io/docs/3x/best-practices/blocking.html) by Alexandru Nedelcu/Monix## Examples
First some imports
```tut:silent
import scala.concurrent.ExecutionContext.global
import cats.effect._
import cats.implicits._
import io.chrisdavenport.linebacker.Linebacker
import io.chrisdavenport.linebacker.contexts.Executors
```Creating And Evaluating Pool Behavior
```tut
val getThread = IO(Thread.currentThread().getName)val checkRun = {
Executors.unbound[IO] // Create Executor
.map(Linebacker.fromExecutorService[IO](_)) // Create Linebacker From Executor
.use{ implicit linebacker => // Raise Implicitly
implicit val cs = IO.contextShift(global)
Linebacker[IO].blockCS(getThread) // Block On Linebacker Pool Not Global
.flatMap(threadName => IO(println(threadName))) >>
getThread // Running On Global
.flatMap(threadName => IO(println(threadName)))
}
}checkRun.unsafeRunSync
```Dual Contexts Are Also Very Useful
```tut
import scala.concurrent.ExecutionContext
import io.chrisdavenport.linebacker.DualContextExecutors.unbound[IO].map(blockingExecutor =>
DualContext.fromContexts[IO](IO.contextShift(global), ExecutionContext.fromExecutorService(blockingExecutor))
)
```