Added support for delaying feature initialisation
This commit is contained in:
parent
d4ab9f87d1
commit
d4cc061955
9
.readthedocs.yaml
Normal file
9
.readthedocs.yaml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
version 2
|
||||||
|
|
||||||
|
build
|
||||||
|
os ubuntu-22.04
|
||||||
|
tools
|
||||||
|
python 3.12
|
||||||
|
|
||||||
|
sphinx
|
||||||
|
configuration docs/conf.py
|
@ -17,7 +17,10 @@ namespace Tapeti.Config
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Various Tapeti features which can be turned on or off.
|
/// Various Tapeti features which can be turned on or off.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ITapetiConfigFeatues Features { get; }
|
/// <remarks>
|
||||||
|
/// Calling this method will freeze the feature set if <see cref="ITapetiConfigBuilder.DelayFeatures"/> is used.
|
||||||
|
/// </remarks>
|
||||||
|
ITapetiConfigFeatures GetFeatures();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides access to the different kinds of registered middleware.
|
/// Provides access to the different kinds of registered middleware.
|
||||||
@ -34,7 +37,7 @@ namespace Tapeti.Config
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Various Tapeti features which can be turned on or off.
|
/// Various Tapeti features which can be turned on or off.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITapetiConfigFeatues
|
public interface ITapetiConfigFeatures
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether 'publisher confirms' are used. This RabbitMQ features allows Tapeti to
|
/// Determines whether 'publisher confirms' are used. This RabbitMQ features allows Tapeti to
|
||||||
|
@ -53,6 +53,40 @@ namespace Tapeti.Config
|
|||||||
void RegisterBinding(IBinding binding);
|
void RegisterBinding(IBinding binding);
|
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc cref="ITapetiConfigFeaturesBuilder.DisablePublisherConfirms"/>
|
||||||
|
ITapetiConfigBuilder DisablePublisherConfirms();
|
||||||
|
|
||||||
|
/// <inheritdoc cref="ITapetiConfigFeaturesBuilder.SetPublisherConfirms"/>
|
||||||
|
ITapetiConfigBuilder SetPublisherConfirms(bool enabled);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="ITapetiConfigFeaturesBuilder.EnableDeclareDurableQueues"/>
|
||||||
|
ITapetiConfigBuilder EnableDeclareDurableQueues();
|
||||||
|
|
||||||
|
/// <inheritdoc cref="ITapetiConfigFeaturesBuilder.SetDeclareDurableQueues"/>
|
||||||
|
ITapetiConfigBuilder SetDeclareDurableQueues(bool enabled);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="ITapetiConfigFeaturesBuilder.DisableVerifyDurableQueues"/>
|
||||||
|
ITapetiConfigBuilder DisableVerifyDurableQueues();
|
||||||
|
|
||||||
|
/// <inheritdoc cref="ITapetiConfigFeaturesBuilder.SetVerifyDurableQueues"/>
|
||||||
|
ITapetiConfigBuilder SetVerifyDurableQueues(bool enabled);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows the core features to be determine on-demand when first required by the connection instead
|
||||||
|
/// of before <see cref="TapetiConnection"/> is constructed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="onBuild">Called when the feature set is required. From that moment on the feature set is frozen.</param>
|
||||||
|
ITapetiConfigBuilder DelayFeatures(Action<ITapetiConfigFeaturesBuilder> onBuild);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Configures Tapeti core features. Every method returns the builder instance for method chaining.
|
||||||
|
/// </summary>
|
||||||
|
public interface ITapetiConfigFeaturesBuilder
|
||||||
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disables 'publisher confirms'. This RabbitMQ features allows Tapeti to be notified if a message
|
/// Disables 'publisher confirms'. This RabbitMQ features allows Tapeti to be notified if a message
|
||||||
/// has no route, and guarantees delivery for request-response style messages and those marked with
|
/// has no route, and guarantees delivery for request-response style messages and those marked with
|
||||||
@ -62,7 +96,7 @@ namespace Tapeti.Config
|
|||||||
/// and disables Tapeti.Flow from verifying if a request/response can be routed. This may
|
/// and disables Tapeti.Flow from verifying if a request/response can be routed. This may
|
||||||
/// result in never-ending flows. Only disable if you can accept those consequences.
|
/// result in never-ending flows. Only disable if you can accept those consequences.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ITapetiConfigBuilder DisablePublisherConfirms();
|
ITapetiConfigFeaturesBuilder DisablePublisherConfirms();
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -74,7 +108,7 @@ namespace Tapeti.Config
|
|||||||
/// and disables Tapeti.Flow from verifying if a request/response can be routed. This may
|
/// and disables Tapeti.Flow from verifying if a request/response can be routed. This may
|
||||||
/// result in never-ending flows. Only disable if you can accept those consequences.
|
/// result in never-ending flows. Only disable if you can accept those consequences.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ITapetiConfigBuilder SetPublisherConfirms(bool enabled);
|
ITapetiConfigFeaturesBuilder SetPublisherConfirms(bool enabled);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -84,7 +118,7 @@ namespace Tapeti.Config
|
|||||||
/// Note that access to the RabbitMQ Management plugin's REST API is required for this
|
/// Note that access to the RabbitMQ Management plugin's REST API is required for this
|
||||||
/// feature to work, since AMQP does not provide a way to query existing bindings.
|
/// feature to work, since AMQP does not provide a way to query existing bindings.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
ITapetiConfigBuilder EnableDeclareDurableQueues();
|
ITapetiConfigFeaturesBuilder EnableDeclareDurableQueues();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Configures the automatic creation of durable queues and updating of their bindings.
|
/// Configures the automatic creation of durable queues and updating of their bindings.
|
||||||
@ -93,7 +127,7 @@ namespace Tapeti.Config
|
|||||||
/// Note that access to the RabbitMQ Management plugin's REST API is required for this
|
/// Note that access to the RabbitMQ Management plugin's REST API is required for this
|
||||||
/// feature to work, since AMQP does not provide a way to query existing bindings.
|
/// feature to work, since AMQP does not provide a way to query existing bindings.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
ITapetiConfigBuilder SetDeclareDurableQueues(bool enabled);
|
ITapetiConfigFeaturesBuilder SetDeclareDurableQueues(bool enabled);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -102,7 +136,7 @@ namespace Tapeti.Config
|
|||||||
/// exchange, which do not correspond to Tapeti's configuration, as these will cause an error
|
/// exchange, which do not correspond to Tapeti's configuration, as these will cause an error
|
||||||
/// while verifying.
|
/// while verifying.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ITapetiConfigBuilder DisableVerifyDurableQueues();
|
ITapetiConfigFeaturesBuilder DisableVerifyDurableQueues();
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -111,7 +145,7 @@ namespace Tapeti.Config
|
|||||||
/// exchange, which do not correspond to Tapeti's configuration, as these will cause an error
|
/// exchange, which do not correspond to Tapeti's configuration, as these will cause an error
|
||||||
/// while verifying.
|
/// while verifying.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ITapetiConfigBuilder SetVerifyDurableQueues(bool enabled);
|
ITapetiConfigFeaturesBuilder SetVerifyDurableQueues(bool enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ namespace Tapeti.Connection
|
|||||||
DeclareExchange(channel, exchange);
|
DeclareExchange(channel, exchange);
|
||||||
|
|
||||||
// The delivery tag is lost after a reconnect, register under the new tag
|
// The delivery tag is lost after a reconnect, register under the new tag
|
||||||
if (config.Features.PublisherConfirms)
|
if (config.GetFeatures().PublisherConfirms)
|
||||||
{
|
{
|
||||||
lastDeliveryTag++;
|
lastDeliveryTag++;
|
||||||
|
|
||||||
@ -848,7 +848,7 @@ namespace Tapeti.Connection
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (config.Features.PublisherConfirms)
|
if (config.GetFeatures().PublisherConfirms)
|
||||||
{
|
{
|
||||||
lastDeliveryTag = 0;
|
lastDeliveryTag = 0;
|
||||||
|
|
||||||
|
@ -125,9 +125,9 @@ namespace Tapeti.Connection
|
|||||||
|
|
||||||
CustomBindingTarget bindingTarget;
|
CustomBindingTarget bindingTarget;
|
||||||
|
|
||||||
if (config.Features.DeclareDurableQueues)
|
if (config.GetFeatures().DeclareDurableQueues)
|
||||||
bindingTarget = new DeclareDurableQueuesBindingTarget(clientFactory, routingKeyStrategy, exchangeStrategy, cancellationToken);
|
bindingTarget = new DeclareDurableQueuesBindingTarget(clientFactory, routingKeyStrategy, exchangeStrategy, cancellationToken);
|
||||||
else if (config.Features.VerifyDurableQueues)
|
else if (config.GetFeatures().VerifyDurableQueues)
|
||||||
bindingTarget = new PassiveDurableQueuesBindingTarget(clientFactory, routingKeyStrategy, exchangeStrategy, cancellationToken);
|
bindingTarget = new PassiveDurableQueuesBindingTarget(clientFactory, routingKeyStrategy, exchangeStrategy, cancellationToken);
|
||||||
else
|
else
|
||||||
bindingTarget = new NoVerifyBindingTarget(clientFactory, routingKeyStrategy, exchangeStrategy, cancellationToken);
|
bindingTarget = new NoVerifyBindingTarget(clientFactory, routingKeyStrategy, exchangeStrategy, cancellationToken);
|
||||||
|
@ -135,7 +135,7 @@ namespace Tapeti
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ITapetiConfigBuilder DisablePublisherConfirms()
|
public ITapetiConfigBuilder DisablePublisherConfirms()
|
||||||
{
|
{
|
||||||
GetConfig().SetPublisherConfirms(false);
|
GetConfig().GetFeaturesBuilder().DisablePublisherConfirms();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ namespace Tapeti
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ITapetiConfigBuilder SetPublisherConfirms(bool enabled)
|
public ITapetiConfigBuilder SetPublisherConfirms(bool enabled)
|
||||||
{
|
{
|
||||||
GetConfig().SetPublisherConfirms(enabled);
|
GetConfig().GetFeaturesBuilder().SetPublisherConfirms(enabled);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ namespace Tapeti
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ITapetiConfigBuilder EnableDeclareDurableQueues()
|
public ITapetiConfigBuilder EnableDeclareDurableQueues()
|
||||||
{
|
{
|
||||||
GetConfig().SetDeclareDurableQueues(true);
|
GetConfig().GetFeaturesBuilder().EnableDeclareDurableQueues();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ namespace Tapeti
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ITapetiConfigBuilder SetDeclareDurableQueues(bool enabled)
|
public ITapetiConfigBuilder SetDeclareDurableQueues(bool enabled)
|
||||||
{
|
{
|
||||||
GetConfig().SetDeclareDurableQueues(enabled);
|
GetConfig().GetFeaturesBuilder().SetDeclareDurableQueues(enabled);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +167,7 @@ namespace Tapeti
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ITapetiConfigBuilder DisableVerifyDurableQueues()
|
public ITapetiConfigBuilder DisableVerifyDurableQueues()
|
||||||
{
|
{
|
||||||
GetConfig().SetVerifyDurableQueues(false);
|
GetConfig().GetFeaturesBuilder().DisablePublisherConfirms();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +175,15 @@ namespace Tapeti
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ITapetiConfigBuilder SetVerifyDurableQueues(bool enabled)
|
public ITapetiConfigBuilder SetVerifyDurableQueues(bool enabled)
|
||||||
{
|
{
|
||||||
GetConfig().SetVerifyDurableQueues(enabled);
|
GetConfig().GetFeaturesBuilder().SetVerifyDurableQueues(enabled);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ITapetiConfigBuilder DelayFeatures(Action<ITapetiConfigFeaturesBuilder> onBuild)
|
||||||
|
{
|
||||||
|
GetConfig().GetFeaturesBuilder().DelayFeatures(onBuild);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,12 +229,13 @@ namespace Tapeti
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
internal class Config : ITapetiConfig
|
internal class Config : ITapetiConfig
|
||||||
{
|
{
|
||||||
private readonly ConfigFeatures features = new();
|
private ConfigFeaturesBuilder? featuresBuilder = new();
|
||||||
|
private ITapetiConfigFeatures? features;
|
||||||
|
|
||||||
private readonly ConfigMiddleware middleware = new();
|
private readonly ConfigMiddleware middleware = new();
|
||||||
private readonly ConfigBindings bindings = new();
|
private readonly ConfigBindings bindings = new();
|
||||||
|
|
||||||
public IDependencyResolver DependencyResolver { get; }
|
public IDependencyResolver DependencyResolver { get; }
|
||||||
public ITapetiConfigFeatues Features => features;
|
|
||||||
public ITapetiConfigMiddleware Middleware => middleware;
|
public ITapetiConfigMiddleware Middleware => middleware;
|
||||||
public ITapetiConfigBindings Bindings => bindings;
|
public ITapetiConfigBindings Bindings => bindings;
|
||||||
|
|
||||||
@ -237,6 +246,17 @@ namespace Tapeti
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ITapetiConfigFeatures GetFeatures()
|
||||||
|
{
|
||||||
|
if (features != null)
|
||||||
|
return features;
|
||||||
|
|
||||||
|
features = featuresBuilder!.Build();
|
||||||
|
featuresBuilder = null;
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Lock()
|
public void Lock()
|
||||||
{
|
{
|
||||||
bindings.Lock();
|
bindings.Lock();
|
||||||
@ -260,24 +280,17 @@ namespace Tapeti
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void SetPublisherConfirms(bool enabled)
|
internal ConfigFeaturesBuilder GetFeaturesBuilder()
|
||||||
{
|
{
|
||||||
features.PublisherConfirms = enabled;
|
if (featuresBuilder == null)
|
||||||
}
|
throw new InvalidOperationException("Tapeti features are already frozen");
|
||||||
|
|
||||||
public void SetDeclareDurableQueues(bool enabled)
|
return featuresBuilder;
|
||||||
{
|
|
||||||
features.DeclareDurableQueues = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetVerifyDurableQueues(bool enabled)
|
|
||||||
{
|
|
||||||
features.VerifyDurableQueues = enabled;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal class ConfigFeatures : ITapetiConfigFeatues
|
internal class ConfigFeatures : ITapetiConfigFeatures
|
||||||
{
|
{
|
||||||
public bool PublisherConfirms { get; internal set; } = true;
|
public bool PublisherConfirms { get; internal set; } = true;
|
||||||
public bool DeclareDurableQueues { get; internal set; }
|
public bool DeclareDurableQueues { get; internal set; }
|
||||||
@ -285,6 +298,66 @@ namespace Tapeti
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal class ConfigFeaturesBuilder : ITapetiConfigFeaturesBuilder
|
||||||
|
{
|
||||||
|
private bool publisherConfirms = true;
|
||||||
|
private bool declareDurableQueues;
|
||||||
|
private bool verifyDurableQueues = true;
|
||||||
|
private Action<ITapetiConfigFeaturesBuilder>? onBuild;
|
||||||
|
|
||||||
|
|
||||||
|
public ITapetiConfigFeaturesBuilder DisablePublisherConfirms()
|
||||||
|
{
|
||||||
|
return SetPublisherConfirms(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITapetiConfigFeaturesBuilder SetPublisherConfirms(bool enabled)
|
||||||
|
{
|
||||||
|
publisherConfirms = enabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITapetiConfigFeaturesBuilder EnableDeclareDurableQueues()
|
||||||
|
{
|
||||||
|
return SetDeclareDurableQueues(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITapetiConfigFeaturesBuilder SetDeclareDurableQueues(bool enabled)
|
||||||
|
{
|
||||||
|
declareDurableQueues = enabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITapetiConfigFeaturesBuilder DisableVerifyDurableQueues()
|
||||||
|
{
|
||||||
|
return SetVerifyDurableQueues(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITapetiConfigFeaturesBuilder SetVerifyDurableQueues(bool enabled)
|
||||||
|
{
|
||||||
|
verifyDurableQueues = enabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReSharper disable once ParameterHidesMember
|
||||||
|
public void DelayFeatures(Action<ITapetiConfigFeaturesBuilder> onBuild)
|
||||||
|
{
|
||||||
|
this.onBuild = onBuild;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITapetiConfigFeatures Build()
|
||||||
|
{
|
||||||
|
onBuild?.Invoke(this);
|
||||||
|
return new ConfigFeatures
|
||||||
|
{
|
||||||
|
DeclareDurableQueues = declareDurableQueues,
|
||||||
|
PublisherConfirms = publisherConfirms,
|
||||||
|
VerifyDurableQueues = verifyDurableQueues
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
internal class ConfigMiddleware : ITapetiConfigMiddleware
|
internal class ConfigMiddleware : ITapetiConfigMiddleware
|
||||||
{
|
{
|
||||||
private readonly List<IMessageMiddleware> messageMiddleware = new();
|
private readonly List<IMessageMiddleware> messageMiddleware = new();
|
||||||
|
Loading…
Reference in New Issue
Block a user