-
Notifications
You must be signed in to change notification settings - Fork 595
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
Track publisher confirmations automatically #1687
Conversation
I wonder if an enum wouldn't be better, something like |
The current API is ONLY to facilitate removal of @danielmarbach / @bording - how should we coordinate work on this feature? |
@lukebakken what was your plan with this PR? Was your idea to get this going and then eventually get reviews etc from our end? Regarding the options, I think it might be best to have something like @Tornhoof mentioned to better represent the states of options that are possible if the current configurability needs to be preserved. Since it is nowhere explicitly stated, I wanted to ask if you and your team have discussed why confirms and tracking should be individual options or even allowed to be turned off? Assuming confirms is the default, why would someone then not want to have tracking enabled? Is it purely to preserve options that allow to opt in to not so safe options to get more speed? |
Yes, that's it. I'll get started on this today. |
I can see allowing publisher confirms to be enabled or not, but I would argue that once you've enabled them, the client should just handle tracking them for you now that the async API allows for that to be done in a per-message way. |
@lukebakken how do you intend to expose the number of outstanding confirms? Or is this something you want to follow up in another PR? |
🤷 I'm just now switching gears from working on our AMQP 1.0 Go client 😵💫 |
Looking at all the things required to pass at channel creation I think it might be better to have a channel creation options type/class similar to Azure SDK options types to configure various client types. Adding more overloads with primitive types seems to burry things and make the usage unnecessary complex |
@lukebakken I pushed the options type as a small contribution since you thumbed that up Regarding
What is the relationship of You wrote something about the publish starting throwing an exception. Why not simply let them wait until new slots are available? A cancellation token passed to the publish would allow enforcing some sort of timeout anyway? Or does it have to be more sophisticated? |
@danielmarbach - thanks for taking a look and contributing. I have been sidelined by RabbitMQ support this week.
I haven't thought this through all the way but that sounds right.
A wait with a timeout sounds great to me. If a token isn't passed to |
Why is that? In the world of cooperative cancellation, the notion of a timeout is usually expressed by passing a token that is attached to a token source that enforces the timeout. Then everything is in the hand of the caller. If you introduce another arbitrary way of setting a timeout you need to deal with different overloads of the method. Or is the intent to build a similar API to |
Ah, OK. We have places in the API where a |
We shouldn't be depending on any polyfill, specially when there are more than one known to exist, because it can create conflicts for users.. The compiler depends only on fully qualified names (that's why those libraries can exist) and the types don't even need to be We can just grab the source of whatever types we need and add them as That being said, But it's not that hard to use create these kind of types with mandatory constructor parameters. |
Those statements seem to contradict each other. The polyfil libraries I linked are source only dependencies and by default are internal. There is no clash with public types and effectively the copying is no longer necessary because that has already been done by the authors of the polyfil libraries in a considerate and consumable way. I'm not saying copying is not an option. In fact I mentioned that on the issue I opened. I'm commenting directly on the points you brought up as a counter argument to not take a Dependency. There are other downsides of taking a Dependency to those source packages that are worth discussing though. FYI following through your reasoning it would also be necessary to remove the private assets only NuGet Dependency to Nullable which the client takes a Dependency on today |
I think there are valid reasons for timeouts when the underlying mechanism uses / enforces timeouts like HTTP, TCP etc. In the example with publisher confirms it feels forced but again I might be misunderstanding things |
Sorry, I assumed they were libs, without checking. Polyfill looks like an all or nothing with the only option being making the code I haven't tested Polysharp, but if it works as advertised, looks good. |
@danielmarbach @paulomorgado we won't be adding any polyfill libraries to this project unless they are absolutely necessary for a feature. I hope to continue with this PR soon. Thanks! |
Those are not libraries (that was my mistake). They are tools. Polyfill adds everything as source: The downside there, as I see it, is that it requires C" 12.0. Polysharp generates the polyfills: And can be used with C# 10.0. But, in the end, all we need is: namespace System.Runtime.CompilerServices
{
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
internal static class IsExternalInit
{
}
} With a few lines of MSBuild it's possible to remove the extra files from either tool |
"init only members" seems like a "nice to have" code feature, and not a "must have". |
760febe
to
e65c6fb
Compare
628ca72
to
857cbde
Compare
@danielmarbach @bording I've just committed support for I'd appreciate a review, thanks! This API is not ideal for a library user, because it's up to them to correlate publishes with the associated Thoughts? Leave that up to users? |
@lukebakken I see what I can do tomorrow before going on vacation for a week. Today it's already a bit late for me to review things |
@danielmarbach no rush! Enjoy your time off 🌴 |
@lukebakken I have submitted a different approach which I think would be way more usable #1698. This is not done done because of my limited time but a start I guess |
A few more generic comments:
|
@danielmarbach thank you!
Yes, I agree. I was just about to pull all the confirm-related code into its own class to at least keep everything in the same place.
I'll check your new PR
I wasn't 100% sure of the best way to create a buffer to write the sequence number to use that method.
Yes, that is exactly when it is added - in all cases when confirms are enabled, whether or not tracking is enabled.
Yes, I think you're correct. |
It seems though it opts out when the activity is null |
When activity is null and confirmations are disabled. Yes, the logic is confusing so I'll add a comment. |
I always knew I would fail any job interview when being presented with bool flags 😂 |
A-men! I got it wrong the first time... "Why aren't my headers being added???" ... I used |
a11e32d
to
04c2aaf
Compare
Fixes #1682 * Remove `ConfirmSelectAsync` from `IChannel` * Add parameters to enable confirmations on `IConnection.CreateChannelAsync` * Remove / comment out all use of `WaitForConfirms...` methods. * Dispose -> DisposeAsync * Implement confirmation tracking and await-ing in `BasicPublishAsync` * Ensure exceptions make into inner exception for `HardProtocolException` * Remove commented-out code related to `WaitForConfirms...` methods. * Unblock so that `CloseAsync` can succeed. * Introduce channel creation options * Allow cancellation of final await for publisher confirmation in `BasicPublishAsync` * Fix `dotnet format` verification error * Make `ConfirmSelectAsync` `private` and assume that semaphore is held. * Track sequence number for basic.return * Implement `basic.return` support. * Fix the code that adds OTel and publish sequence number headers. * Add publish sequence number as long as `_publisherConfirmationsEnabled` is true * Fix the `PublisherConfirms` test program * Add license headers * Enable publisher confirms * Spike an exception based approach (misses removing the bool value return type) * Extend the use of `_confirmSemaphore` to the duration of when exceptions could be caught. * Restore how @danielmarbach serialized the publish sequence number. * Fix bug in how headers are added to `BasicProperties` that don't already have them. * Use `ValueTask` as the `BasicPublishAsync` return value. --------- Co-authored-by: Daniel Marbach <[email protected]> Co-authored-by: Luke Bakken <[email protected]> * Add `PublishException` class. * Test that non-routable messages result in `PublishException` with `IsReturn = true` * Code documentation Simplify code.
d7e618d
to
e93adfa
Compare
@danielmarbach I'm planning to make the code more readable before the final release, at least by moving the publisher confirmation related code to a partial class or its own class. I also haven't begun work on blocking publishers when there are too many outstanding confirms. |
We are using rc.13 in our pre-production environment and having some thoughts about current confirms implementation. We have limited queues with 'overflow-reject' behavior, so in 99% of time we retry Nacks. In current implementation, instead of getting bool (true - Ack, false - Nack) we have to catch exceptions. We catch thousands of exceptions before publishing continue (tiny delay between retries for performance reasons). FYI guys to consider this scenario. Thanks! |
@bpolitaiev thanks for testing the latest pre-release versions. Unless an extremely severe performance penalty can be demonstrated with the current API, it won't change. The API is designed to force users to deal with unexpected scenarios, and not require any checking in the normal case, which is a successful publish with confirmation. RC 14 is available, with very minor changes to Your other option is to set |
Hey @lukebakken, thanks for the quick response. My point is that Nack is not unexpected scenario, as overflow | reject-publish is the only way to wait when queue is full. |
@bpolitaiev I am going to take our conversation to a dedicated discussion. In general, following-up on a closed issue or PR isn't a good idea on GitHub. |
Fixes #1682
ConfirmSelectAsync
fromIChannel
IConnection.CreateChannelAsync