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 14:43
    @typelevel-bot banned @jdegoes
  • Jan 31 21:17
    codecov-io commented #484
  • Jan 31 21:08
    scala-steward opened #484
  • Jan 31 18:19
    andywhite37 commented #189
  • Jan 31 02:41
    kamilongus starred typelevel/cats-effect
  • Jan 30 00:01
    codecov-io commented #483
  • Jan 29 23:51
    deniszjukow opened #483
  • Jan 29 23:37
  • Jan 29 23:22
  • Jan 29 20:26
    Rui-L starred typelevel/cats-effect
  • Jan 29 18:01
    jdegoes commented #480
  • Jan 29 17:04
    thomaav starred typelevel/cats-effect
  • Jan 28 17:43
    asachdeva starred typelevel/cats-effect
  • Jan 28 07:12
    alexandru commented #480
  • Jan 28 05:45
    codecov-io commented #482
  • Jan 28 05:35
    daron666 opened #482
  • Jan 27 13:56
    codecov-io commented #481
  • Jan 27 13:46
    lrodero opened #481
  • Jan 27 05:47
    codecov-io commented #460
  • Jan 27 05:37
    codecov-io commented #460
Arnau Abella
@monadplus
How do you handle situation where you fork then cancelled (e.g. the resource is not available) but there is a join afterwards ?
Fabio Labella
@SystemFw
you are going to have to be a bit more specific
that use of the word "cancelled" doesn't necessarily map to what I would think in the context of a fork
i.e. it's unclear if you are talking about some logical notion of "I don't want to do this anymore", or actual fiber interruption
Arnau Abella
@monadplus
Fiber interruption (e.g. Fiber.cancel)
I mean I dont want to do that anymore as .cancel
Fabio Labella
@SystemFw
who cancels? the thing that would do the join otherwise or something else?
Arnau Abella
@monadplus
The thread you forked from with .start
Fabio Labella
@SystemFw
and who joins?
I think it would be better if you could sketch an actual example. This can be tricky so it's easier that way
Arnau Abella
@monadplus
  (for {
    fiber <- readFile(new File("data/lore.txt")).start
    _     <- IO.sleep(100.millis) *> fiber.cancel
    lore  <- fiber.join // blocks
  } yield lore).map { println(_) }.unsafeRunSync()
@SystemFw
Fabio Labella
@SystemFw
well, that's kinda contrived given that this specific control flow doesn't really make a lot of sense, you alwasy join after cancel has happened
there are three things I'd say
if you just want to put a timeout on something
you should just readFile.timeout(5.seconds) (assuming that your readfile implementation is cancelable)
number 2 would be to only call .join if you haven't called cancel. In the simplest case this is an if, in more complicated cases you might need some coordination between the interrupter and the joiner
number 3 would be to put the result in a Ref + Deferred thing (in this case a simple Deferred), which has some form of default, this simplest case of which would be Deferred[Option[Thing]]
then you need to bracketCase or guaranteeCase the started operation so that it puts None on that Deferred when it gets cancelled
thoughts?
Arnau Abella
@monadplus
All three points are clear
nothing to add
John A. De Goes
@jdegoes
@monadplus Instead of fiber.join, call fiber.await. Join says, "the outcome of the fiber will be my outcome", await says, "just let me know what happened".
Arnau Abella
@monadplus
1.5.0 cats.effect.fiber does only expose cancel and join
Fabio Labella
@SystemFw
a quickly sketched prototype might look like this (requires testing ofc)
def await[F[_]: Concurrent, A](fa: F[A]): F[(F[Option[Either[Throwable, A]]], F[Unit])] =
  Deferred[F, Option[Either[Throwable, A]]].flatMap { result =>
       val action = {
          fa.attempt.flatMap(r => result.complete(r.some).uncancelable)
       }.guaranteeCase {
          case ExitCase.Canceled => result.complete(None)
          case _ => ().pure[F]
      }

      action.start.bracketCase(fiber => result.get.pure[F] -> fiber.cancel){
         case (fiber, ExitCase.Canceled) => fiber.cancel
         case (_, _) => ().pure[F]
      }
    }
obviously with a proper datatype instead of that monstrosity, and after testing (this isn't really the sort of code you want to sketch on gitter in 5 mins)
John A. De Goes
@jdegoes
@monadplus I sketched it in the design for Cats Effect 2.0. Until then you can get it in ZIO or with a patch like the above ^^^
Jakub Kozłowski
@kubukoz
I'm trying to implement Async for slick's DBIO, not passing one law now (bracket release is called on Completed or Error)... can someone roughly explain what the implementation needs to care about in the context of that law?
I have a rough idea that it means release should not be possible to cancel, but I'm not sure how to ensure that
Gavin Bisesi
@Daenyth
@kubukoz how did you encode Sync?
Jakub Kozłowski
@kubukoz
duude
you're going to love this
Gavin Bisesi
@Daenyth
the from(future) is strict in its argument
so I couldn't figure how to do Sync
Jakub Kozłowski
@kubukoz
behold delay(thunk): DBIO.successful(()).flatMap(_ => thunk)
Gavin Bisesi
@Daenyth
:ok_hand:
Jakub Kozłowski
@kubukoz
and it's even stack safe since 3.2.2
I'll try to get Async soon, and in any case submit something to slickcats
Gavin Bisesi
@Daenyth
nice :)
Jakub Kozłowski
@kubukoz

anyway, my bracket looks like this

      override def bracketCase[A, B](acquire: DBIO[A])(
        use: A => DBIO[B]
      )(release: (A, ExitCase[Throwable]) => DBIO[Unit]): DBIO[B] = {
        acquire.flatMap { a =>
          rethrow {
            flatTap(attempt(use(a))) {
              case Right(_) => release(a, ExitCase.complete)
              case Left(e)  => release(a, ExitCase.error(e))
            }
          }
        }
      }

if you ask why I'm not using syntax, I'll answer because it's 1am and I have a pretty dirty file with all this

async:
override def async[A](
  k: (Either[Throwable, A] => Unit) => Unit
): DBIO[A] = suspend {
  val promise = Promise[A]()
  k {
    case Right(a) => promise.success(a)
    case Left(t)  => promise.failure(t)
  }

  DBIO.from(promise.future)
}
anything that stands out?
Gavin Bisesi
@Daenyth
hmm
I'd be concerned about future memoizing
try to increment an atomicint using async
Jakub Kozłowski
@kubukoz
it's suspended, I don't think it memoizes
Jakub Kozłowski
@kubukoz
I'll try that tomorrow
Mark de Jong
@Fristi
A while ago there was a blog (https://blog.softwaremill.com/correlation-ids-in-scala-using-monix-3aa11783db81) about using ThreadLocal for storing a correlationId. This is useful for scoping log entries (via MDC). This was however bound to Monix, is there such a thing for cats-effect IO ?
I know there is http4s-tracer as well, but I think it’s a bit heavy solution
Fabio Labella
@SystemFw
@Fristi no such thing for IO. That thread local thing requires specific support in the interpreter