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
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
because it's not actually using ThreadLocal, but TaskLocal: there are (possibly many) more Task/IO running on one thread
it should be possible to do it via other means though (e.g. Kleisli)
Mark de Jong
@Fristi
I see
Hmm but introducing Kleisli would have a penalty in terms of performance right?
Fabio Labella
@SystemFw
yes
but so will introducing TaskLocal (although not as big I will imagine)
two things:
  • actually check that the performance penalty matters for your use case: a couple of network calls and it stops being that important
  • you can try something akin to passing the correlation Id implicitly but putting it behind a Correlation[F] algebra
Mark de Jong
@Fristi
Good points will have a look :-)
Mark de Jong
@Fristi
Wonder if I could decorate ContextShiftto propagate the right MDC context as seen in http://code.hootsuite.com/logging-contextual-info-in-an-asynchronous-scala-application/
Alexandru Nedelcu
@alexandru

@Fristi in Monix you can use a TracingScheduler, out of which you can build the proper ContextShift, for IO too, however it gets tricky — and the reason for why the logic for Monix's TaskLocal resides in the Task run-loop itself.

For instance all it takes to screw your locals is something like this and your special ContextSwitch won't help 😉

IO.async { cb =>
  new Thread(() -> cb(Right(()))).start()
}