-
Notifications
You must be signed in to change notification settings - Fork 18
Don't unsafely run effect from Producer's send callback #240
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
base: master
Are you sure you want to change the base?
Don't unsafely run effect from Producer's send callback #240
Conversation
…roducer's send callback
…roducer's send callback
Pull Request Test Coverage Report for Build 1841127528
💛 - Coveralls |
| def block(record: ProducerRecordJ[Bytes, Bytes]) = { | ||
|
|
||
| def callbackOf(deferred: Deferred[F, Either[Throwable, RecordMetadataJ]]): Callback = { | ||
| def callbackOf(promise: Promise[RecordMetadataJ]): Callback = { |
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.
why do you think that this is anyhow faster?
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 haven't measured it of course, it just intuitively feels more lightweight, but I don't have any strong arguments in this regard.
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'd recommend keep using deferred but call toFuture instead of toTry and deprecate API requiring ToTry
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 how is ToFuture better than ToTry, don't they both call unsafeRunSync in implementation?
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 how is ToFuture better than ToTry, don't they both call unsafeRunSync in implementation?
- less construction requirements
ToFutureusesunsafeToFuture, and truly saying both are ok in this case
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.
So if I change ToTry to ToFuture what do I do with the resulting Future? Do I await inside the Callback or just ignore it? TBH I don't like any of these options and would rather leave ToTry then.
btw, what's the reason you are against using Promise here? To me it seems cleaner that materialising an effect in any manner
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.
Do I await inside the Callback or just ignore it?
Just ignore it, as executed code is private and you exactly know what is being executed
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.
the reason you are against using Promise here
Because that combination of Promise/Future adds more overhead than you might think of comparing to native, it is also not a cancellable thing.
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 this particular use case is not cancellable either way, is it? Even if you cancel the resulting effect the producer's callback will still be executed
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 mean cancelling the "inner" effect resulting from Deferred#get
| } | ||
|
|
||
| def of[F[_]: ToTry: Async]( | ||
| def of[F[_]: Async]( |
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.
breaks backward compatibility
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 though it might break it, but MiMa checks passing kinda convinced me otherwise.
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.
Or do you mean source compatibility?
| } | ||
|
|
||
| @deprecated("Use of(ProducerConfig)", since = "12.0.1") | ||
| def of[F[_]: ToTry: Async]( |
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.
breaks backward compatibility
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 how does MiMa check pass then?
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 how does MiMa check pass then?
good question, should not pass
Even though semantically the behaviour is the same, I think it is a bit cleaner when we don't "unsafely" run the effect (completing
Deferred) viaToTryinProducer#sendcallback.Also as the docs state the
Callbackis generally executed in the I/O thread of the producer, so it should be as fast as possible. To me it seems that completing aPromiseis more lightweight than executing an effect of completingDeferred.