-
Notifications
You must be signed in to change notification settings - Fork 60
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
Upgrade to core V8 #720
Upgrade to core V8 #720
Conversation
src/NServiceBus.Transport.RabbitMQ.AcceptanceTests/ConfigureEndpointRabbitMQTransport.cs
Outdated
Show resolved
Hide resolved
src/NServiceBus.Transport.RabbitMQ.AcceptanceTests/ConfigureEndpointRabbitMQTransport.cs
Outdated
Show resolved
Hide resolved
src/NServiceBus.Transport.RabbitMQ.AcceptanceTests/When_using_a_custom_message_id_strategy.cs
Outdated
Show resolved
Hide resolved
src/NServiceBus.Transport.RabbitMQ.Tests/ApprovalFiles/APIApprovals.Approve.approved.txt
Show resolved
Hide resolved
src/NServiceBus.Transport.RabbitMQ.Tests/ApprovalFiles/APIApprovals.Approve.approved.txt
Outdated
Show resolved
Hide resolved
...ServiceBus.Transport.RabbitMQ.Tests/ConnectionString/ConnectionConfigurationWithAmqpTests.cs
Outdated
Show resolved
Hide resolved
src/NServiceBus.Transport.RabbitMQ.AcceptanceTests/ConfigurationHelpers.cs
Outdated
Show resolved
Hide resolved
} | ||
public static class RabbitMQTransportOptionsExtensions | ||
{ | ||
public static void UseNonPersistentDeliveryMode(this NServiceBus.PublishOptions options) { } | ||
public static void UseNonPersistentDeliveryMode(this NServiceBus.ReplyOptions options) { } | ||
public static void UseNonPersistentDeliveryMode(this NServiceBus.SendOptions options) { } | ||
} | ||
public static class RabbitMQTransportSettingsExtensions |
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.
shouldn't those be properly obsoleted?
src/NServiceBus.Transport.RabbitMQ/Configuration/AmqpConnectionString.cs
Show resolved
Hide resolved
/// <summary> | ||
/// Specifies if an external authentication mechanism should be used for client authentication. | ||
/// </summary> | ||
public bool UseExternalAuthMechanism { get; set; } = false; |
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.
there seems to be an inconsistency whether the default value is specified or not (I think it would make sense to always explicitly specify it).
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.
Not sure I understand. You mean I should always specifiy default value for bool
properties? I think this is just by accident.
6272e25
to
2b009da
Compare
Bring back UseTLS setting
2b009da
to
175c297
Compare
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.
There is a lot of formatting cleanup that also need to be done, but I didn't call that out specifically anywhere.
Overall, I can follow the reasoning behind some/most of the changes, but the configuration stuff is a big change that I'm not sure I understand the point of just yet.
My initial reaction here is that we've made the configuration code much worse, and the experience is also going to be worse for people using the transport.
|
||
if (delay > DelayInfrastructure.MaxDelayInSeconds) | ||
{ | ||
throw new Exception($"Message cannot be sent with {nameof(DoNotDeliverBefore)} value '{doNotDeliverBefore.At}' because it exceeds the maximum delay value '{TimeSpan.FromSeconds(DelayInfrastructure.MaxDelayInSeconds)}'."); | ||
throw new Exception($"Message cannot set to be delivered at '{dispatchProperties.DoNotDeliverBefore.At}' because the delay exceeds the maximum delay value '{TimeSpan.FromSeconds(DelayInfrastructure.MaxDelayInSeconds)}'."); |
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.
This error message currently isn't a valid sentence. Probably needs something like:
throw new Exception($"Message cannot set to be delivered at '{dispatchProperties.DoNotDeliverBefore.At}' because the delay exceeds the maximum delay value '{TimeSpan.FromSeconds(DelayInfrastructure.MaxDelayInSeconds)}'."); | |
throw new Exception($"Message cannot be delivered at '{dispatchProperties.DoNotDeliverBefore.At}' because the delay exceeds the maximum delay value '{TimeSpan.FromSeconds(DelayInfrastructure.MaxDelayInSeconds)}'."); |
However, I prefer the previous format for the error message. With the current change, it doesn't make it clear that the error is happening because of an invalid DoNotDeliverBefore
on the message. You're now asking them to see a value, and then figure out where the value came from.
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.
👍
|
||
if (delay > DelayInfrastructure.MaxDelayInSeconds) | ||
{ | ||
throw new Exception($"Message cannot be sent with {nameof(DelayDeliveryWith)} value '{delayDeliveryWith.Delay}' because it exceeds the maximum delay value '{TimeSpan.FromSeconds(DelayInfrastructure.MaxDelayInSeconds)}'."); | ||
throw new Exception($"Message cannot be delayed by '{dispatchProperties.DelayDeliveryWith.Delay}' because it exceeds the maximum delay value '{TimeSpan.FromSeconds(DelayInfrastructure.MaxDelayInSeconds)}'."); |
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.
Same comment about this error message. I would prefer to retain the {nameof(DelayDeliveryWith)}
in some way.
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.
👍
@@ -32,15 +29,15 @@ public static void Fill(this IBasicProperties properties, OutgoingMessage messag | |||
properties.Headers[DelayInfrastructure.DelayHeader] = Convert.ToInt32(delay); | |||
} | |||
|
|||
if (deliveryConstraints.TryGet(out DiscardIfNotReceivedBefore timeToBeReceived) && timeToBeReceived.MaxTime < TimeSpan.MaxValue) | |||
if (dispatchProperties.DiscardIfNotReceivedBefore != null && dispatchProperties.DiscardIfNotReceivedBefore.MaxTime < TimeSpan.MaxValue) |
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.
if (dispatchProperties.DiscardIfNotReceivedBefore != null && dispatchProperties.DiscardIfNotReceivedBefore.MaxTime < TimeSpan.MaxValue) | |
if (dispatchProperties.DiscardIfNotReceivedBefore?.MaxTime < TimeSpan.MaxValue) |
@@ -8,40 +10,93 @@ | |||
/// <summary> | |||
/// Route using a static routing convention for routing messages from publishers to subscribers using routing keys. | |||
/// </summary> | |||
class DirectRoutingTopology : IRoutingTopology | |||
public class DirectRoutingTopology : IRoutingTopology |
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.
At the point where I'm writing this comment, I haven't seen the configuration changes yet, but I'm taking an educated guess at how they've changed if you've made this public.
I'm not a fan of changes that make these topology types public.
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 only alternative would be to use enums but this makes is awkward when combined with a custom topology because that would have to be an instance.
In alternative could be some static field e.g. have Topologies
static class with fields for direct and conventional topology. Then the user could do
config.RoutingTopology = Topologies.Direct;
config.RoutingTopology = Topologies.Conventional;
config.RoutingTopology = new MyCustomTopology();
config.RoutingTopology = new ConventionalRoutingTopology(false, oneConvention, anotherConvention)
but since the most common case of conventional topology is covered by default settings, I think that would be excessive complexity. If a user knows what direct topology is, they can surely be bothered by instantiating a public class.
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.
Hard disagree here. If we are "improving" the transport seam, why is leading to APIs that are worse than what we had before?
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 disagree that this is worse if you take into account all the usage scenarios. The advantage of the new API is that is allows users to inspect the state of the configuration object.
@@ -21,55 +23,101 @@ | |||
/// <item><description>we generate an exchange for each queue so that we can do direct sends to the queue. it is bound as a fanout exchange</description></item> | |||
/// </list> | |||
/// </summary> | |||
class ConventionalRoutingTopology : IRoutingTopology | |||
public class ConventionalRoutingTopology : IRoutingTopology |
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.
Feels like a mistake to be making these public.
type = typeof(object); | ||
} | ||
// Make handlers for IEvent handle all events whether they extend IEvent or not | ||
var typeToSubscribe = type.MessageType != typeof(IEvent) ? type.MessageType : typeof(object); |
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.
This is a somewhat questionable legacy thing to do, and is only still here because changing it would be wire compat break. That being said, I'd prefer:
var typeToSubscribe = type.MessageType != typeof(IEvent) ? type.MessageType : typeof(object); | |
var typeToSubscribe = type.MessageType == typeof(IEvent) ? typeof(object) : type.MessageType; |
|
||
if (settings.UsePublishSubscribe) | ||
{ | ||
Subscriptions = new SubscriptionManager(connectionFactory, routingTopology, settings.ReceiveAddress); |
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.
If the thing that creates a message pump has access to all the things required to create a SubscriptionManager
it seems better to me for it to create one if needed instead. That means you can stop passing in routingTopology
just to be able to create this.
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 point. I'll discuss that with other TF members to make this consistent across transports.
/// <summary> | ||
/// The routing topology to use. If not set the conventional routing topology will be used <seealso cref="ConventionalRoutingTopology"/>. | ||
/// </summary> | ||
public IRoutingTopology RoutingTopology |
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.
Ok, yeah this is what I afraid of when I saw that the topology classes had been made public.. This is a strictly worse configuration experience compared to what we had before. This puts the onus on the caller to have to create a topology class in all instances of using this API.
In the past that would only have been required when they had created their own custom topology 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.
They only need to do it if they chose to select a non-default topology. In this version the conventional topology is made the default. Since very few users use the direct one, I don't this is going to be a major issue for the majority.
{ | ||
class AmqpConnectionString | ||
{ | ||
public static Action<RabbitMQTransport> Parse(string connectionString) |
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.
This is parsing a connection string. The idea that this is returning an entire RabbitMQTransport
instance to do that seems like a major smell to me.
We used to have a ConnectionConfiguration
class for a reason.
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.
It does not return the instance but rather an action that configures that instance. Plus the RabbitMQTransport
is now a configuration object only.
{ | ||
if (connectionString.StartsWith("amqp", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
AmqpConnectionString.Parse(connectionString)(this); |
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.
Having to call Parse and then cast like that? This is not something that should be required to do. Why not keep the ConnectionConfiguration
class and not have all this going on?
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.
case? This is passing the current instance to the configuration action. Why having two classes with exactly same properties, one public and one private?
@bording we discussed the transport config APIs during today's sync and we decided to:
This is definitely not the last TF that is going to be run in scope of the V8 so there is no problem with DevExp making the APIs even more polished. We wanted to focus on getting them consistent while not blocking any existing use cases. |
@SzymonPobiega Reading your response, I'll admit to be being rather disheartened, because I don't really see how much of that addresses the concerns I raised.
This one specifically I really disagree with. There's basically almost nothing you can do with that parameter that leaves you with a correct working system. The only thing you could do would be to use |
@bording I've removed the additional parameter. Should be now good to go. |
Need to push the package to myget for smoke testing
@bording I had to merge it to be able to smoke test the transports. Any further adjustments to the API are going to be done by subsequent task forces, either in Architecture or DevExperience. |
No description provided.