Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Sep 05 2019 14:43
    @typelevel-bot banned @jdegoes
  • Jan 31 2019 21:17
    codecov-io commented #484
  • Jan 31 2019 21:08
    scala-steward opened #484
  • Jan 31 2019 18:19
    andywhite37 commented #189
  • Jan 31 2019 02:41
    kamilongus starred typelevel/cats-effect
  • Jan 30 2019 00:01
    codecov-io commented #483
  • Jan 29 2019 23:51
    deniszjukow opened #483
  • Jan 29 2019 23:37
  • Jan 29 2019 23:22
  • Jan 29 2019 20:26
    Rui-L starred typelevel/cats-effect
  • Jan 29 2019 18:01
    jdegoes commented #480
  • Jan 29 2019 17:04
    thomaav starred typelevel/cats-effect
  • Jan 28 2019 17:43
    asachdeva starred typelevel/cats-effect
  • Jan 28 2019 07:12
    alexandru commented #480
  • Jan 28 2019 05:45
    codecov-io commented #482
  • Jan 28 2019 05:35
    daron666 opened #482
  • Jan 27 2019 13:56
    codecov-io commented #481
  • Jan 27 2019 13:46
    lrodero opened #481
  • Jan 27 2019 05:47
    codecov-io commented #460
  • Jan 27 2019 05:37
    codecov-io commented #460
Daniel Spiewak
@djspiewak
@unoexperto worth noting that the reason doobie doesn't support cancelation is jdbc doesn't really support cancelation
without looking at it directly, I can't say whether or not it might be possible to be more aggressive about cancelation than what doobie is right now
but I would guess that a lot of this is just limitations in the underlying API
like how it's not actually async
ruslan
@unoexperto
@djspiewak It's probably DB-specific but PSQL (that I'm using) supports java.sql.Statement.cancel()
Could you guys please tell me what I'm missing in my attempts to cancel running IO ? Here is how I do it
val op: IO[String] = (1 to 100).foldLeft(IO.pure("")) { case (prev, count) =>
  prev.flatMap{ _ =>
    IO.sleep(500 millis) *> IO{
      val msg = s"[${Thread.currentThread().getId}] Count: $count"
      println(msg)
      msg
    }
  }
}.bracketCase(value => IO.pure(value)){ case (str: String, value: ExitCase[Throwable]) =>
  value match {
    case ExitCase.Completed => IO(println("Completed"))
    case ExitCase.Error(ex) => IO(println(s"Error: ${ex.getMessage}"))
    case ExitCase.Canceled => IO(println("Canceled"))
  }
}

println("Starting")
val fiberIO = op.start
fiberIO.unsafeRunAsyncAndForget()
Thread.sleep(2000)
println("Canceling")
fiberIO.flatMap(_.cancel).unsafeRunSync()
Ryan Peters
@sloshy
@unoexperto You need to insert a cancel boundary or shift somewhere in there (maybe after prev.flatMap or inside it)
Piotr Gawryś
@Avasil
acquire (IO on which you call bracket) is always uncancelable
This message was deleted
ruslan
@unoexperto
@sloshy Could you please show how I should do it ? I tried follow and it doesn't work
op.start.flatMap { fiber =>
  IO.sleep(2.seconds).flatMap { _ =>
    println("Canceling")
    fiber.cancel
  }
}.unsafeRunSync()
Piotr Gawryś
@Avasil
In your previous example, you probably don't need bracket and could call guaranteeCase and it will be cancelable
Or put code you want to cancel in use block ( value => ...)
Daniel Spiewak
@djspiewak
so in order to do something like statement.cancel(), you're probably going to need to play the same trick that fs2 plays in eval
which is to say, you need to race an IO against the one which is actually doing the work
where that IO is defined by IO.never with an onCancel that allows you to call things
it's slightly janky, but interrupting synchronous things is most definitely not intended to be a primary use-case
you can't do it reliably, and it's relatively rare that an upstream library defines a deterministic way of doing so without also being asynchronous
ruslan
@unoexperto
@Avasil Trick with guaranteeCase worked. Thanks! Also I didn't realize that value returned from IO on which I call .bracketCase is sort of seed value. Generally I feel like whole thing is much more complicated than it should be. At least compared to zio.
Piotr Gawryś
@Avasil
ZIO works the same way in this regard. The main purpose of bracket is safe acquisition and release of resources, e.g. file handle or database connection. You have (acquire)(use)(release). Neither acquire nor release can be cancelable because we could end up with corrupted state or leak resources
Gavin Bisesi
@Daenyth
it's pretty clear that zio has to work the same way because you can use ZIO with cats-effect Bracket
hmm
Is there any kind of (fa: F[A]).recoverSomeT[E2]( e: E => ???: E2 ) => EitherT[F, E2, A]
John A. De Goes
@jdegoes
@unoexperto Easy-peasy.
ZIO.uninterruptible {
  for {
    statement <- createStatement(query)
    fiber     <- ZIO.interruptible(executeStatement(statement).fork)
    results   <- fiber.join.onInterrupt(cancelStatement(statement)).ensuring {
                   cleanupStatement(statement)
                 }                
  } yield results
}
Be sure to surround the blocking bits by blocking { ... }.
Ross A. Baker
@rossabaker
v2.0.0-RC1 is here: notes, tweet
Gavin Bisesi
@Daenyth
lovely, somehow I deadlocked my IOApp with a lazy val on a parent trait :|
Daniel Spiewak
@djspiewak
@Daenyth yeaaaaaah… the curse of lazy val
Ryan Peters
@sloshy
@djspiewak @Daenyth I'm curious - can you elaborate? Does it have to do with how the laziness from IO/etc is different from the nature of lazy val being more of a memoized def?
Daniel Spiewak
@djspiewak
it's unfortunately more than a memoized def
it's an exactly-once memoized def with support for concurrent access
that implies two things
first, accessing one is a memory barrier, even if it's already been evaluated
second, there's a lock wrapped up inside it which covers the evaluation
Ryan Peters
@sloshy
Well, heck. Good to keep in mind.
Daniel Spiewak
@djspiewak
yeah they're kind of terrible
what I really want is a "deferred evaluation" lazy val
Paul Phillips, ages and ages ago, proposed adding an annotation for this
I would absolutely love that as a feature, but it never made it
Ross A. Baker
@rossabaker
Runar has a library with various lazy semantics. I don't think I'd take it as a dependency, but it's interesting reading on the tradeoffs. There's an SIP out there, too.
Daniel Spiewak
@djspiewak
yeah it's a fun little library
there are some gotchas to it though
Ryan Peters
@sloshy
It sounds like in most cases where I'd want a lazy val I'd be better off structuring my app around Deferred instead.
Daniel Spiewak
@djspiewak
in many cases, yes
the few times I use lazy val intentionally these days are when constructing infinite recursive effects
I could just use def instead but it cuts down on the allocations
Ryan Zeigler
@rzeigler
Related to the concurrent structures. Is there a use case that MVar really excels at. Every time I reach for it, I pause and then find a different primitive fits better for what I want
Daniel Spiewak
@djspiewak
MVar doesn't work well for much of anything. It kind of conflates two concerns in this rather odd way
I've seen people use it as a singleton semaphore for tests
but even that seemed a bit less useful than… Semaphore
Piotr Gawryś
@Avasil
Maybe some producer-consumer scenarios but there is also just 1-element async queue