Comments (5)
According to the docs, use
:
Allocates a resource and supplies it to the given function. The resource is released as soon as the resulting F[B] is completed, whether normally or as a raised error.
This means, the following code:
transactor.use {xa =>
transaction.transact(xa)
}.timeout(1.minute).unsafeRunSync()
allocates a new transactor, calls transact
on it, and releases it every time you call runWithRetryTransaction
.
To make your app to reuse connections, you may want to, for example:
- Refactor
Db
to accept an instance oftransactor
, rather than allocate it every timerunWithRetryTransaction
is called:
class Db(transactor: HikariTransactor[IO]) {
...
}
- Allocate transactor once, at startup, e.g., in
Main
:
object Main extends ResourceApp.Forever {
def run(args: List[String]): Resource[IO, Unit] =
for {
transactor <- createTransactor()
db = new Db(transactor)
... // do stuff with Db
} yield ()
}
from doobie.
I have expanded on the Hikari example. Hope it helps demonstrate how to use cats.effect.Resource as well as how a typical application using doobie is setup.
https://github.com/tpolecat/doobie/pull/2013/files
Note that at no point do I need to call unsafeRunSync since my main object is extending cats.effect.IOApp.Simple
from doobie.
I still recommend structuring your code following the examples to avoid unsafeRunSync. How your code is laid out right now (which forces you to call unsafeRunSync) isn't idiomatic nor ideal and will present problems in the future.
(For example, who calls cleanUp
on your connection pool and when?)
from doobie.
A person named "amumurst" found the problem.
"I can reproduce, and there is some different ways of fixing it.
The issue is kinda contrived and I don't know exactly the details, but it has something to do with something called "delayed init" which the App trait of scala 2 uses (fixed in scala 3 it seems). My best hunch is that the code in the App object is run before the implicit IORuntime has started correctly (or some other initialization order issue), leading to a deadlock.
You can circumvent it by moving the allocation to a lazy val (so other things get to initialize first)
So lazy val (xa, cleanUp): (HikariTransactor[IO], IO[Unit])
"
This is my final solution:
case class DBx(transactor: HikariTransactor[IO]) { all my queries here }
object Foo {
val transactor: Resource[IO, HikariTransactor[IO]] =
for {
hikariConfig <- Resource.pure {
// For the full list of hikari configurations see https://github.com/brettwooldridge/HikariCP#gear-configuration-knobs-baby
val config = new HikariConfig()
config.setMaximumPoolSize(10)
config.setDriverClassName(PostgresDriver)
config.setJdbcUrl(s"jdbc:postgresql://${PostgresHostname}:${PostgresPort}/${PostgresDB}?currentSchema=yeedu")
config.setUsername(PostgresUser)
config.setPassword(PostgresPass)
config.setConnectionTimeout(1000)
config
}
xa <- HikariTransactor.fromHikariConfig[IO](hikariConfig)
} yield xa
lazy val (xa, cleanUp): (HikariTransactor[IO], IO[Unit]) = transactor.allocated.unsafeRunSync()
val db = DBx(xa)
}
Thank you so much
from doobie.
I've refactor my code do to this:
val _db: Resource[IO, DB] = for {
transactor <- System.transactor
db = DB(transactor)
} yield db
val (db,cancel) = _db.allocated.unsafeRunSync() //never returns, get stuck forever
But it's the same problem as before; the 'db.allocated.unsafeRunSync()' never returns.
I can't perform all my tasks inside the 'for' loop; it doesn't make sense. The DB object is used throughout the application.
from doobie.
Related Issues (20)
- doobie with weaver, which package? HOT 1
- "incompatible type in overriding" when overriding ConnectionInterpreter HOT 3
- Multitenant Application in Doobie HOT 2
- Make instances automatically available for Tuples
- Scalafix rule to help migrate to 1.0
- Change code package to `org.typelevel.doobie`
- Transfer to typelevel github org (make sure docs work)
- Remove TimeMeta (was deprecated)
- Enable MiMa
- Optimize compile time by removing anonymous subclass
- Allow running additional PreparedStatement methods before executing
- Bug: prepared statement parameter is not produced for any class or object, "incompatible interpolation" is not thrown HOT 1
- [question] - Meta[Optional[MyType]] not being used HOT 2
- [CVE-2024-1597] PostgresSQL version is shown as having a vulnerability to SQL Injection via line comment generation HOT 2
- How do i set Snapshot isolation level for transaction? HOT 5
- Where is With ZIO Integration? HOT 2
- Transaction Isolation Levels HOT 3
- build.sbt in introduction broken for Scala 3 HOT 2
- Fragment - expose write.set as a PreparedStatementIO
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from doobie.