Certainly hard coding transformer or third party library call sites is intractable. Stack frame instrumentation though can ameliorate this issue since you have the thunk class and the full runtime stack, so you have the opportunity to trace up. Also, as I mention in the gist, providing extra frame information is really helpful for when that kind of thing fails and you’re trying to track down an error.
To be clear, I don’t think there’s anything wrong with ZIO’s tracing. It gives information that is very useful in a monomorphic or bijective polymorphic context (like your tagless final example). The problem is it is defeated immediately by something like Stream or even some library usage (tracing through an http4s app is varyingly useful, for example), and it doesn’t work at all with transformers. Again, that’s a fair tradeoff, particularly given the ZIO ecosystem’s focus on a single master effect without induction. I just think it’s possible to improve on that, albeit by accepting a totally different tradeoff (greater complexity in implementing lexical configuration), and given how cats IO is often used, it seems worthwhile to at least explore that direction.
Either way, all of these approaches have some unfortunate caveats. It’s possible to build stellar examples of the strengths of both, and also of the weaknesses of both. I’m not sure there’s ever going to be a silver bullet.
I'm trying to understand a bit more about cats-effect, and thus did some experiments by modifying the example here: https://typelevel.org/cats-effect/concurrency/basics.html#thread-scheduling
what I did to make it have only one ExecutionContext
and ContextShift
and a simple producer/consumer using an MVar
. However, here I stumbled upon a (to me) puzzling behaviour. In my first example using an explicit ExecutionContext
and ContextShift
it works as I expect, it keeps running till I terminate it: https://pastebin.com/EdB2k1Cq
in my second example though, I tried to trim down my application to rely on the default in IOApp, but here my program terminates almost immediately: https://pastebin.com/QuC0Putm
why does this happen? What should I read/see/etc to understand this behavior better?
start
means that you return control immediately, and one fiber keeps going while another is spawn asynchronously
producer.start >> consumer.start >> IO(println("when does this happen"))
start
means "spawn something and keep going without waiting for it"
start, start, end
end
will happen without waiting for the two started things to finish
daemon threads
do not prevent the JVM from shutting down
concurrently