-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Java interop doc update #556
base: main
Are you sure you want to change the base?
Conversation
Async[F].delay { | ||
val jContext: JContext = ctx.underlying | ||
val _ = jContext.makeCurrent() | ||
}.flatMap(_ => k(cb)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is problematic because there's no guarantee that delay and the subsequent flatMap are executed together. Any ideas?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we can use evalOn
with a custom ExecutonContext
:
def tracedContext(ctx: JContext): ExecutionContext =
new ExecutionContext {
def execute(runnable: Runnable): Unit = {
val scope = ctx.makeCurrent()
try {
runnable.run()
} finally {
scope.close()
}
}
def reportFailure(cause: Throwable): Unit =
cause.printStackTrace()
}
def asyncWithContext[F[_]: Async, A](k: (Either[Throwable, A] => Unit) => F[Option[F[Unit]]])(implicit L: Local[F, Context]): F[A] =
Local[F, Context].ask.flatMap { ctx =>
Async[F].evalOn(
Async[F].async[A](cb => k(cb)),
tracedContext(ctx.underlying)
)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But implications on performance are unknown :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
evalOn
is applicable for all scenarios, actually. But again, it may (and highly likely will) affect the performance.
def evalWithJContext[F[_]: Async, A](fa: F[A])(implicit L: Local[F, Context]): F[A] =
Local[F, Context].ask.flatMap { ctx =>
Async[F].evalOn(fa, tracedContext(ctx.underlying))
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea :) Why do you think it'll affect performance (assuming fa
pretty much immediately calls the async API instead of doing a bunch of CPU work)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK context shifts may be costly.
The current implementation of the tracedContext
is basically a same-thread execution.
Here is the logic for the evalOn
in the CE: https://github.com/typelevel/cats-effect/blob/3cf97ae4fd643f333febb4554af2fb603ed2c9d2/core/shared/src/main/scala/cats/effect/IOFiber.scala#L976-L988.
If I get it right, fa
will be executed right within the fiber's loop.
@armanbilge perhaps you have some insides?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added your suggestion for now. I'm thinking that a typical async API involves using another threadpool so context shift isn't avoidable in that case. (But yeah will be good if an additional context shift can be avoided)
createOtel4s[IO].flatMap(otel4s => program(otel4s)) | ||
def run: IO[Unit] = | ||
OtelJava.autoConfigured[IO]() { otel4s => | ||
implicit val local: Local[IO, Context] = otel4s.localContext |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
implicit val local: Local[IO, Context] = otel4s.localContext | |
import otel4s.localContext |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Seems like one of the builds had an OOM. If someone can help me retrigger it it should pass 🤞 |
def tracedContext(ctx: JContext): ExecutionContext = | ||
new ExecutionContext { | ||
def execute(runnable: Runnable): Unit = { | ||
val scope = ctx.makeCurrent() | ||
try { | ||
runnable.run() | ||
} finally { | ||
scope.close() | ||
} | ||
} | ||
def reportFailure(cause: Throwable): Unit = | ||
cause.printStackTrace() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, just getting caught up ...
Hmm, I'm concerned by this. If I'm reading correctly you have effectively implemented a ParasiticExecutionContext
. If you run arbitrary effects on this you may stackoverflow and/or dead-lock.
Rough draft for now. Any feedback/nitpick welcome :)