From e25fa5aa5224af63fdd45b301e6ddba99af75524 Mon Sep 17 00:00:00 2001 From: Mark van Renswoude Date: Wed, 2 Jun 2021 20:56:10 +0200 Subject: [PATCH 1/6] Implemented IAsyncDisposable --- Tapeti/Config/IMessageContext.cs | 5 ++--- Tapeti/Connection/TapetiSubscriber.cs | 9 +++++++++ Tapeti/Default/ControllerMessageContext.cs | 13 ++++++++++++- Tapeti/Default/MessageContext.cs | 13 +++++++++++++ Tapeti/IConnection.cs | 3 +-- Tapeti/ISubscriber.cs | 3 +-- Tapeti/Tapeti.csproj | 1 + Tapeti/TapetiConnection.cs | 22 +++++++++++++++++++--- 8 files changed, 58 insertions(+), 11 deletions(-) diff --git a/Tapeti/Config/IMessageContext.cs b/Tapeti/Config/IMessageContext.cs index c3314c4..7c23127 100644 --- a/Tapeti/Config/IMessageContext.cs +++ b/Tapeti/Config/IMessageContext.cs @@ -2,11 +2,10 @@ namespace Tapeti.Config { - /// /// /// Provides information about the message currently being handled. /// - public interface IMessageContext : IDisposable + public interface IMessageContext : IAsyncDisposable, IDisposable { /// /// Provides access to the Tapeti config. @@ -49,7 +48,7 @@ namespace Tapeti.Config /// middleware stages (mostly for IControllerMiddlewareBase descendants). /// /// A unique key. It is recommended to prefix it with the package name which hosts the middleware to prevent conflicts - /// Will be disposed if the value implements IDisposable + /// Will be disposed if the value implements IDisposable or IAsyncDisposable void Store(string key, object value); /// diff --git a/Tapeti/Connection/TapetiSubscriber.cs b/Tapeti/Connection/TapetiSubscriber.cs index 3c207a7..537a030 100644 --- a/Tapeti/Connection/TapetiSubscriber.cs +++ b/Tapeti/Connection/TapetiSubscriber.cs @@ -25,8 +25,17 @@ namespace Tapeti.Connection } + public async ValueTask DisposeAsync() + { + if (consuming) + await Stop(); + } + + public void Dispose() { + if (consuming) + Stop().GetAwaiter().GetResult(); } diff --git a/Tapeti/Default/ControllerMessageContext.cs b/Tapeti/Default/ControllerMessageContext.cs index 92ac61c..3d8fb55 100644 --- a/Tapeti/Default/ControllerMessageContext.cs +++ b/Tapeti/Default/ControllerMessageContext.cs @@ -1,4 +1,5 @@ -using Tapeti.Config; +using System.Threading.Tasks; +using Tapeti.Config; namespace Tapeti.Default { @@ -41,9 +42,19 @@ namespace Tapeti.Default /// public void Dispose() { + // Do not call decoratedContext.Dispose - by design } + /// + public ValueTask DisposeAsync() + { + // Do not call decoratedContext.DisposeAsync - by design + return default; + } + + + /// public void Store(string key, object value) { diff --git a/Tapeti/Default/MessageContext.cs b/Tapeti/Default/MessageContext.cs index 4c9f1a0..9612990 100644 --- a/Tapeti/Default/MessageContext.cs +++ b/Tapeti/Default/MessageContext.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using Tapeti.Config; namespace Tapeti.Default @@ -39,6 +40,18 @@ namespace Tapeti.Default } + /// + public async ValueTask DisposeAsync() + { + foreach (var item in items.Values) + { + if (item is IAsyncDisposable asyncDisposable) + await asyncDisposable.DisposeAsync(); + } + } + + + /// public void Store(string key, object value) { diff --git a/Tapeti/IConnection.cs b/Tapeti/IConnection.cs index 4453362..8aab48a 100644 --- a/Tapeti/IConnection.cs +++ b/Tapeti/IConnection.cs @@ -47,11 +47,10 @@ namespace Tapeti public delegate void DisconnectedEventHandler(object sender, DisconnectedEventArgs e); - /// /// /// Represents a connection to a RabbitMQ server /// - public interface IConnection : IDisposable + public interface IConnection : IAsyncDisposable, IDisposable { /// /// Creates a subscriber to consume messages from the bound queues. diff --git a/Tapeti/ISubscriber.cs b/Tapeti/ISubscriber.cs index 1e7d864..a5e9975 100644 --- a/Tapeti/ISubscriber.cs +++ b/Tapeti/ISubscriber.cs @@ -5,11 +5,10 @@ using System.Threading.Tasks; namespace Tapeti { - /// /// /// Manages subscriptions to queues as configured by the bindings. /// - public interface ISubscriber : IDisposable + public interface ISubscriber : IAsyncDisposable, IDisposable { /// /// Starts consuming from the subscribed queues if not already started. diff --git a/Tapeti/Tapeti.csproj b/Tapeti/Tapeti.csproj index 3a6632e..51630ec 100644 --- a/Tapeti/Tapeti.csproj +++ b/Tapeti/Tapeti.csproj @@ -18,6 +18,7 @@ + diff --git a/Tapeti/TapetiConnection.cs b/Tapeti/TapetiConnection.cs index ff72c3f..f9cb6e5 100644 --- a/Tapeti/TapetiConnection.cs +++ b/Tapeti/TapetiConnection.cs @@ -30,6 +30,8 @@ namespace Tapeti private readonly Lazy client; private TapetiSubscriber subscriber; + private bool disposed; + /// /// Creates a new instance of a TapetiConnection and registers a default IPublisher /// in the IoC container as provided in the config. @@ -97,12 +99,26 @@ namespace Tapeti /// public void Dispose() { - Close().Wait(); - - subscriber?.Dispose(); + if (!disposed) + DisposeAsync().GetAwaiter().GetResult(); } + /// + public async ValueTask DisposeAsync() + { + if (disposed) + return; + + if (subscriber != null) + await subscriber.DisposeAsync(); + + await Close(); + disposed = true; + } + + + private class ConnectionEventListener: IConnectionEventListener { private readonly TapetiConnection owner; From 6acf50f658d35287a1a37a8d5db2eee22a7b3446 Mon Sep 17 00:00:00 2001 From: Mark van Renswoude Date: Thu, 3 Jun 2021 08:13:43 +0200 Subject: [PATCH 2/6] Build NuGet packages with source Testing if that allows for debugging --- appveyor.yml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 44dd9a5..9155506 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,43 +11,43 @@ before_build: after_build: # Tapeti - - cmd: dotnet pack --output output Tapeti\Tapeti.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack --include-source --output output Tapeti\Tapeti.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.%GitVersion_NuGetVersion%.nupkg" # Tapeti.Annotations - - cmd: dotnet pack --output output Tapeti.Annotations\Tapeti.Annotations.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack --include-source --output output Tapeti.Annotations\Tapeti.Annotations.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Annotations.%GitVersion_NuGetVersion%.nupkg" # Tapeti.DataAnnotations - - cmd: dotnet pack --output output Tapeti.DataAnnotations\Tapeti.DataAnnotations.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack --include-source --output output Tapeti.DataAnnotations\Tapeti.DataAnnotations.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.DataAnnotations.%GitVersion_NuGetVersion%.nupkg" # Tapeti.DataAnnotations.Extensions - - cmd: dotnet pack --output output Tapeti.DataAnnotations.Extensions\Tapeti.DataAnnotations.Extensions.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack --include-source --output output Tapeti.DataAnnotations.Extensions\Tapeti.DataAnnotations.Extensions.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.DataAnnotations.Extensions.%GitVersion_NuGetVersion%.nupkg" # Tapeti.Flow - - cmd: dotnet pack --output output Tapeti.Flow\Tapeti.Flow.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack --include-source --output output Tapeti.Flow\Tapeti.Flow.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Flow.%GitVersion_NuGetVersion%.nupkg" # Tapeti.Flow.SQL - - cmd: dotnet pack --output output Tapeti.Flow.SQL\Tapeti.Flow.SQL.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack --include-source --output output Tapeti.Flow.SQL\Tapeti.Flow.SQL.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Flow.SQL.%GitVersion_NuGetVersion%.nupkg" # Tapeti.Transient - - cmd: dotnet pack --output output Tapeti.Transient\Tapeti.Transient.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack --include-source --output output Tapeti.Transient\Tapeti.Transient.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Transient.%GitVersion_NuGetVersion%.nupkg" # Tapeti.Serilog - - cmd: dotnet pack --output output Tapeti.Serilog\Tapeti.Serilog.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack --include-source --output output Tapeti.Serilog\Tapeti.Serilog.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Serilog.%GitVersion_NuGetVersion%.nupkg" # Tapeti.SimpleInjector - - cmd: dotnet pack --output output Tapeti.SimpleInjector\Tapeti.SimpleInjector.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack --include-source --output output Tapeti.SimpleInjector\Tapeti.SimpleInjector.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.SimpleInjector.%GitVersion_NuGetVersion%.nupkg" # Tapeti.Autofac - - cmd: dotnet pack --output output Tapeti.Autofac\Tapeti.Autofac.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack --include-source --output output Tapeti.Autofac\Tapeti.Autofac.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Autofac.%GitVersion_NuGetVersion%.nupkg" # Tapeti.CastleWindsor - - cmd: dotnet pack --output output Tapeti.CastleWindsor\Tapeti.CastleWindsor.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack --include-source --output output Tapeti.CastleWindsor\Tapeti.CastleWindsor.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.CastleWindsor.%GitVersion_NuGetVersion%.nupkg" # Tapeti.Ninject - - cmd: dotnet pack --output output Tapeti.Ninject\Tapeti.Ninject.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack --include-source --output output Tapeti.Ninject\Tapeti.Ninject.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Ninject.%GitVersion_NuGetVersion%.nupkg" # Tapeti.UnityContainer - - cmd: dotnet pack --output output Tapeti.UnityContainer\Tapeti.UnityContainer.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack --include-source --output output Tapeti.UnityContainer\Tapeti.UnityContainer.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.UnityContainer.%GitVersion_NuGetVersion%.nupkg" build: From cea877f50ac1373d19bbc98181e8241b27a2dc63 Mon Sep 17 00:00:00 2001 From: Mark van Renswoude Date: Thu, 3 Jun 2021 08:16:25 +0200 Subject: [PATCH 3/6] Push symbols package --- appveyor.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 9155506..ce74843 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -13,42 +13,55 @@ after_build: # Tapeti - cmd: dotnet pack --include-source --output output Tapeti\Tapeti.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.%GitVersion_NuGetVersion%.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.%GitVersion_NuGetVersion%.symbols.nupkg" # Tapeti.Annotations - cmd: dotnet pack --include-source --output output Tapeti.Annotations\Tapeti.Annotations.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Annotations.%GitVersion_NuGetVersion%.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.Annotations.%GitVersion_NuGetVersion%.symbols.nupkg" # Tapeti.DataAnnotations - cmd: dotnet pack --include-source --output output Tapeti.DataAnnotations\Tapeti.DataAnnotations.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.DataAnnotations.%GitVersion_NuGetVersion%.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.DataAnnotations.%GitVersion_NuGetVersion%.symbols.nupkg" # Tapeti.DataAnnotations.Extensions - cmd: dotnet pack --include-source --output output Tapeti.DataAnnotations.Extensions\Tapeti.DataAnnotations.Extensions.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.DataAnnotations.Extensions.%GitVersion_NuGetVersion%.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.DataAnnotations.Extensions.%GitVersion_NuGetVersion%.symbols.nupkg" # Tapeti.Flow - cmd: dotnet pack --include-source --output output Tapeti.Flow\Tapeti.Flow.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Flow.%GitVersion_NuGetVersion%.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.Flow.%GitVersion_NuGetVersion%.symbols.nupkg" # Tapeti.Flow.SQL - cmd: dotnet pack --include-source --output output Tapeti.Flow.SQL\Tapeti.Flow.SQL.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Flow.SQL.%GitVersion_NuGetVersion%.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.Flow.SQL.%GitVersion_NuGetVersion%.symbols.nupkg" # Tapeti.Transient - cmd: dotnet pack --include-source --output output Tapeti.Transient\Tapeti.Transient.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Transient.%GitVersion_NuGetVersion%.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.Transient.%GitVersion_NuGetVersion%.symbols.nupkg" # Tapeti.Serilog - cmd: dotnet pack --include-source --output output Tapeti.Serilog\Tapeti.Serilog.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Serilog.%GitVersion_NuGetVersion%.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.Serilog.%GitVersion_NuGetVersion%.symbols.nupkg" # Tapeti.SimpleInjector - cmd: dotnet pack --include-source --output output Tapeti.SimpleInjector\Tapeti.SimpleInjector.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.SimpleInjector.%GitVersion_NuGetVersion%.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.SimpleInjector.%GitVersion_NuGetVersion%.symbols.nupkg" # Tapeti.Autofac - cmd: dotnet pack --include-source --output output Tapeti.Autofac\Tapeti.Autofac.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Autofac.%GitVersion_NuGetVersion%.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.Autofac.%GitVersion_NuGetVersion%.symbols.nupkg" # Tapeti.CastleWindsor - cmd: dotnet pack --include-source --output output Tapeti.CastleWindsor\Tapeti.CastleWindsor.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.CastleWindsor.%GitVersion_NuGetVersion%.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.CastleWindsor.%GitVersion_NuGetVersion%.symbols.nupkg" # Tapeti.Ninject - cmd: dotnet pack --include-source --output output Tapeti.Ninject\Tapeti.Ninject.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Ninject.%GitVersion_NuGetVersion%.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.Ninject.%GitVersion_NuGetVersion%.symbols.nupkg" # Tapeti.UnityContainer - cmd: dotnet pack --include-source --output output Tapeti.UnityContainer\Tapeti.UnityContainer.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.UnityContainer.%GitVersion_NuGetVersion%.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.UnityContainer.%GitVersion_NuGetVersion%.symbols.nupkg" build: project: Tapeti.sln From b1aa1feeeac409e26d38dbe88655a55685fad630 Mon Sep 17 00:00:00 2001 From: Mark van Renswoude Date: Thu, 3 Jun 2021 08:23:07 +0200 Subject: [PATCH 4/6] Symbols.nupkg is obsolete, changed to snupkg --- appveyor.yml | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index ce74843..a0da4da 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,57 +11,57 @@ before_build: after_build: # Tapeti - - cmd: dotnet pack --include-source --output output Tapeti\Tapeti.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg --output output Tapeti\Tapeti.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.%GitVersion_NuGetVersion%.nupkg" - - cmd: appveyor PushArtifact "output\Tapeti.%GitVersion_NuGetVersion%.symbols.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.%GitVersion_NuGetVersion%.snupkg" # Tapeti.Annotations - - cmd: dotnet pack --include-source --output output Tapeti.Annotations\Tapeti.Annotations.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg --output output Tapeti.Annotations\Tapeti.Annotations.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Annotations.%GitVersion_NuGetVersion%.nupkg" - - cmd: appveyor PushArtifact "output\Tapeti.Annotations.%GitVersion_NuGetVersion%.symbols.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.Annotations.%GitVersion_NuGetVersion%.snupkg" # Tapeti.DataAnnotations - - cmd: dotnet pack --include-source --output output Tapeti.DataAnnotations\Tapeti.DataAnnotations.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg --output output Tapeti.DataAnnotations\Tapeti.DataAnnotations.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.DataAnnotations.%GitVersion_NuGetVersion%.nupkg" - - cmd: appveyor PushArtifact "output\Tapeti.DataAnnotations.%GitVersion_NuGetVersion%.symbols.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.DataAnnotations.%GitVersion_NuGetVersion%.snupkg" # Tapeti.DataAnnotations.Extensions - - cmd: dotnet pack --include-source --output output Tapeti.DataAnnotations.Extensions\Tapeti.DataAnnotations.Extensions.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg --output output Tapeti.DataAnnotations.Extensions\Tapeti.DataAnnotations.Extensions.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.DataAnnotations.Extensions.%GitVersion_NuGetVersion%.nupkg" - - cmd: appveyor PushArtifact "output\Tapeti.DataAnnotations.Extensions.%GitVersion_NuGetVersion%.symbols.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.DataAnnotations.Extensions.%GitVersion_NuGetVersion%.snupkg" # Tapeti.Flow - - cmd: dotnet pack --include-source --output output Tapeti.Flow\Tapeti.Flow.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg --output output Tapeti.Flow\Tapeti.Flow.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Flow.%GitVersion_NuGetVersion%.nupkg" - - cmd: appveyor PushArtifact "output\Tapeti.Flow.%GitVersion_NuGetVersion%.symbols.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.Flow.%GitVersion_NuGetVersion%.snupkg" # Tapeti.Flow.SQL - - cmd: dotnet pack --include-source --output output Tapeti.Flow.SQL\Tapeti.Flow.SQL.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg --output output Tapeti.Flow.SQL\Tapeti.Flow.SQL.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Flow.SQL.%GitVersion_NuGetVersion%.nupkg" - - cmd: appveyor PushArtifact "output\Tapeti.Flow.SQL.%GitVersion_NuGetVersion%.symbols.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.Flow.SQL.%GitVersion_NuGetVersion%.snupkg" # Tapeti.Transient - - cmd: dotnet pack --include-source --output output Tapeti.Transient\Tapeti.Transient.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg --output output Tapeti.Transient\Tapeti.Transient.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Transient.%GitVersion_NuGetVersion%.nupkg" - - cmd: appveyor PushArtifact "output\Tapeti.Transient.%GitVersion_NuGetVersion%.symbols.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.Transient.%GitVersion_NuGetVersion%.snupkg" # Tapeti.Serilog - - cmd: dotnet pack --include-source --output output Tapeti.Serilog\Tapeti.Serilog.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg --output output Tapeti.Serilog\Tapeti.Serilog.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Serilog.%GitVersion_NuGetVersion%.nupkg" - - cmd: appveyor PushArtifact "output\Tapeti.Serilog.%GitVersion_NuGetVersion%.symbols.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.Serilog.%GitVersion_NuGetVersion%.snupkg" # Tapeti.SimpleInjector - - cmd: dotnet pack --include-source --output output Tapeti.SimpleInjector\Tapeti.SimpleInjector.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg --output output Tapeti.SimpleInjector\Tapeti.SimpleInjector.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.SimpleInjector.%GitVersion_NuGetVersion%.nupkg" - - cmd: appveyor PushArtifact "output\Tapeti.SimpleInjector.%GitVersion_NuGetVersion%.symbols.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.SimpleInjector.%GitVersion_NuGetVersion%.snupkg" # Tapeti.Autofac - - cmd: dotnet pack --include-source --output output Tapeti.Autofac\Tapeti.Autofac.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg --output output Tapeti.Autofac\Tapeti.Autofac.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Autofac.%GitVersion_NuGetVersion%.nupkg" - - cmd: appveyor PushArtifact "output\Tapeti.Autofac.%GitVersion_NuGetVersion%.symbols.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.Autofac.%GitVersion_NuGetVersion%.snupkg" # Tapeti.CastleWindsor - - cmd: dotnet pack --include-source --output output Tapeti.CastleWindsor\Tapeti.CastleWindsor.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg --output output Tapeti.CastleWindsor\Tapeti.CastleWindsor.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.CastleWindsor.%GitVersion_NuGetVersion%.nupkg" - - cmd: appveyor PushArtifact "output\Tapeti.CastleWindsor.%GitVersion_NuGetVersion%.symbols.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.CastleWindsor.%GitVersion_NuGetVersion%.snupkg" # Tapeti.Ninject - - cmd: dotnet pack --include-source --output output Tapeti.Ninject\Tapeti.Ninject.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg --output output Tapeti.Ninject\Tapeti.Ninject.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.Ninject.%GitVersion_NuGetVersion%.nupkg" - - cmd: appveyor PushArtifact "output\Tapeti.Ninject.%GitVersion_NuGetVersion%.symbols.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.Ninject.%GitVersion_NuGetVersion%.snupkg" # Tapeti.UnityContainer - - cmd: dotnet pack --include-source --output output Tapeti.UnityContainer\Tapeti.UnityContainer.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% + - cmd: dotnet pack -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg --output output Tapeti.UnityContainer\Tapeti.UnityContainer.csproj /p:Configuration=Release /p:Version=%GitVersion_NuGetVersion% - cmd: appveyor PushArtifact "output\Tapeti.UnityContainer.%GitVersion_NuGetVersion%.nupkg" - - cmd: appveyor PushArtifact "output\Tapeti.UnityContainer.%GitVersion_NuGetVersion%.symbols.nupkg" + - cmd: appveyor PushArtifact "output\Tapeti.UnityContainer.%GitVersion_NuGetVersion%.snupkg" build: project: Tapeti.sln From bad7abd5bf5f7ffbe6180d7407333ab50590d0b1 Mon Sep 17 00:00:00 2001 From: Mark van Renswoude Date: Thu, 3 Jun 2021 08:28:19 +0200 Subject: [PATCH 5/6] Artifact filter ignored snupkg --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index a0da4da..dc0306a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -78,4 +78,4 @@ deploy: secure: 3WCSZAzan66vEmHZ1q3XzfOfucuAQiA+SiCDChO/gswbxfIXUpiM1eMNASDa3qWH skip_symbols: false - artifact: /.*\.nupkg/ \ No newline at end of file + artifact: /.*(\.|\.s)nupkg/ \ No newline at end of file From a3e3a266e2b055fbc0bd10eb46d65e2e65825c0c Mon Sep 17 00:00:00 2001 From: Mark van Renswoude Date: Fri, 4 Jun 2021 11:51:45 +0200 Subject: [PATCH 6/6] Implemented RoutingKey attribute --- Tapeti.Annotations/RoutingKeyAttribute.cs | 52 +++++++++++++++++++ .../TypeNameRoutingKeyStrategyTests.cs | 51 ++++++++++++++++-- .../Helpers/ConnectionStringParser.cs | 15 +++--- Tapeti.Tests/Tapeti.Tests.csproj | 1 + Tapeti/Default/TypeNameRoutingKeyStrategy.cs | 18 ++++--- Tapeti/Helpers/RoutingKeyHelper.cs | 31 +++++++++++ 6 files changed, 150 insertions(+), 18 deletions(-) create mode 100644 Tapeti.Annotations/RoutingKeyAttribute.cs create mode 100644 Tapeti/Helpers/RoutingKeyHelper.cs diff --git a/Tapeti.Annotations/RoutingKeyAttribute.cs b/Tapeti.Annotations/RoutingKeyAttribute.cs new file mode 100644 index 0000000..7053372 --- /dev/null +++ b/Tapeti.Annotations/RoutingKeyAttribute.cs @@ -0,0 +1,52 @@ +using System; + +namespace Tapeti.Annotations +{ + /// + /// + /// Can be attached to a message class to override or extend the generated routing key. + /// One of the intended scenarios is for versioning messages, where you want to add for example a + /// ".v2" postfix but keep the class name itself the same (in a different namespace of course). + /// + /// + /// The implementation of IRoutingKeyStrategy must explicitly add support for this attribute for it to have effect. + /// The default implementation (TypeNameRoutingKeyStrategy) does, of course. Custom implementations can use + /// the Tapeti.Helpers.RoutingKeyHelper class to add support and keep up-to-date automatically. + /// + /// When using EnableDeclareDurableQueues to automatically generate the queue bindings, both the sender and receiver must + /// use a Tapeti version >= 2.5 to support this attribute or the binding will differ from the sent routing key. + /// + /// The routing keys are no longer used by Tapeti once the message is in the queue, the message handler + /// is instead based on the full message class name (thus including namespace), so if the binding is generated in any + /// other way this remark does not apply and prior versions of Tapeti are compatible. + /// + [AttributeUsage(AttributeTargets.Class)] + public class RoutingKeyAttribute : Attribute + { + /// + /// If specified, the routing key strategy is skipped altogether and this value is used instead. + /// + /// + /// The Prefix and Postfix properties will not have any effect if the Full property is specified. + /// + public string Full { get; set; } + + /// + /// If specified, the value generated by the default routing key strategy is prefixed with this value. + /// No dot will be added after this prefix, if you want to include it add it as part of the value. + /// + /// + /// This property will not have any effect if the Full property is specified. Can be used in combination with Postfix. + /// + public string Prefix { get; set; } + + /// + /// If specified, the value generated by the default routing key strategy is postfixed with this value. + /// No dot will be added before this postfix, if you want to include it add it as part of the value. + /// + /// + /// This property will not have any effect if the Full property is specified. Can be used in combination with Prefix. + /// + public string Postfix { get; set; } + } +} diff --git a/Tapeti.Tests/Default/TypeNameRoutingKeyStrategyTests.cs b/Tapeti.Tests/Default/TypeNameRoutingKeyStrategyTests.cs index ed133fb..26fc423 100644 --- a/Tapeti.Tests/Default/TypeNameRoutingKeyStrategyTests.cs +++ b/Tapeti.Tests/Default/TypeNameRoutingKeyStrategyTests.cs @@ -1,4 +1,6 @@ using System; +using FluentAssertions; +using Tapeti.Annotations; using Tapeti.Default; using Xunit; @@ -60,13 +62,54 @@ namespace Tapeti.Tests.Default AssertRoutingKey("acr.test.mixed.case", typeof(ACRTestMIXEDCaseMESSAGE)); } + + [RoutingKey(Prefix = "prefix.")] + private class PrefixAttributeTestMessage { } + + [Fact] + public void Prefix() + { + AssertRoutingKey("prefix.prefix.attribute.test", typeof(PrefixAttributeTestMessage)); + } + + + [RoutingKey(Postfix = ".postfix")] + private class PostfixAttributeTestMessage { } + + [Fact] + public void Postfix() + { + AssertRoutingKey("postfix.attribute.test.postfix", typeof(PostfixAttributeTestMessage)); + } + + + + [RoutingKey(Prefix = "prefix.", Postfix = ".postfix")] + private class PrefixPostfixAttributeTestMessage { } + + [Fact] + public void PrefixPostfix() + { + AssertRoutingKey("prefix.prefix.postfix.attribute.test.postfix", typeof(PrefixPostfixAttributeTestMessage)); + } + + + [RoutingKey(Full = "andnowforsomethingcompletelydifferent", Prefix = "ignore.", Postfix = ".me")] + private class FullAttributeTestMessage { } + + [Fact] + public void Full() + { + AssertRoutingKey("andnowforsomethingcompletelydifferent", typeof(FullAttributeTestMessage)); + } + + + // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local private static void AssertRoutingKey(string expected, Type messageType) { - if (expected == null) throw new ArgumentNullException(nameof(expected)); - if (messageType == null) throw new ArgumentNullException(nameof(messageType)); - - Assert.Equal(expected, new TypeNameRoutingKeyStrategy().GetRoutingKey(messageType)); + var routingKey = new TypeNameRoutingKeyStrategy().GetRoutingKey(messageType); + routingKey.Should().Be(expected); } } // ReSharper restore InconsistentNaming diff --git a/Tapeti.Tests/Helpers/ConnectionStringParser.cs b/Tapeti.Tests/Helpers/ConnectionStringParser.cs index dfd942f..924f3b5 100644 --- a/Tapeti.Tests/Helpers/ConnectionStringParser.cs +++ b/Tapeti.Tests/Helpers/ConnectionStringParser.cs @@ -1,4 +1,5 @@ -using Tapeti.Helpers; +using FluentAssertions; +using Tapeti.Helpers; using Xunit; namespace Tapeti.Tests.Helpers @@ -185,12 +186,12 @@ namespace Tapeti.Tests.Helpers { var parsed = ConnectionStringParser.Parse(connectionstring); - Assert.Equal(expected.HostName, parsed.HostName); - Assert.Equal(expected.Port, parsed.Port); - Assert.Equal(expected.VirtualHost, parsed.VirtualHost); - Assert.Equal(expected.Username, parsed.Username); - Assert.Equal(expected.Password, parsed.Password); - Assert.Equal(expected.PrefetchCount, parsed.PrefetchCount); + parsed.HostName.Should().Be(expected.HostName); + parsed.Port.Should().Be(expected.Port); + parsed.VirtualHost.Should().Be(expected.VirtualHost); + parsed.Username.Should().Be(expected.Username); + parsed.Password.Should().Be(expected.Password); + parsed.PrefetchCount.Should().Be(expected.PrefetchCount); } } } diff --git a/Tapeti.Tests/Tapeti.Tests.csproj b/Tapeti.Tests/Tapeti.Tests.csproj index cc4c3a6..949f4a3 100644 --- a/Tapeti.Tests/Tapeti.Tests.csproj +++ b/Tapeti.Tests/Tapeti.Tests.csproj @@ -9,6 +9,7 @@ + diff --git a/Tapeti/Default/TypeNameRoutingKeyStrategy.cs b/Tapeti/Default/TypeNameRoutingKeyStrategy.cs index 5b8af1f..f31af08 100644 --- a/Tapeti/Default/TypeNameRoutingKeyStrategy.cs +++ b/Tapeti/Default/TypeNameRoutingKeyStrategy.cs @@ -3,6 +3,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; +using Tapeti.Helpers; namespace Tapeti.Default { @@ -45,15 +46,18 @@ namespace Tapeti.Default /// protected virtual string BuildRoutingKey(Type messageType) { - // Split PascalCase into dot-separated parts. If the class name ends in "Message" leave that out. - var words = SplitPascalCase(messageType.Name); - if (words == null) - return ""; + return RoutingKeyHelper.Decorate(messageType, () => + { + // Split PascalCase into dot-separated parts. If the class name ends in "Message" leave that out. + var words = SplitPascalCase(messageType.Name); + if (words == null) + return ""; - if (words.Count > 1 && words.Last().Equals("Message", StringComparison.InvariantCultureIgnoreCase)) - words.RemoveAt(words.Count - 1); + if (words.Count > 1 && words.Last().Equals("Message", StringComparison.InvariantCultureIgnoreCase)) + words.RemoveAt(words.Count - 1); - return string.Join(".", words.Select(s => s.ToLower())); + return string.Join(".", words.Select(s => s.ToLower())); + }); } diff --git a/Tapeti/Helpers/RoutingKeyHelper.cs b/Tapeti/Helpers/RoutingKeyHelper.cs new file mode 100644 index 0000000..af4c87c --- /dev/null +++ b/Tapeti/Helpers/RoutingKeyHelper.cs @@ -0,0 +1,31 @@ +using System; +using System.Reflection; +using Tapeti.Annotations; + +namespace Tapeti.Helpers +{ + /// + /// Helper class for compositing a routing key with support for the RoutingKey attribute. + /// Should be used by all implementations of IRoutingKeyStrategy unless there is a good reason not to. + /// + public static class RoutingKeyHelper + { + /// + /// Applies the RoutingKey attribute for the specified messageClass. + /// + /// + /// Called when the strategy needs to be applied to the message class to generate a routing key. + /// Will not be called if the Full property is specified on the RoutingKey attribute. + public static string Decorate(Type messageType, Func applyStrategy) + { + var routingKeyAttribute = messageType.GetCustomAttribute(); + if (routingKeyAttribute == null) + return applyStrategy(); + + if (!string.IsNullOrEmpty(routingKeyAttribute.Full)) + return routingKeyAttribute.Full; + + return (routingKeyAttribute.Prefix ?? "") + applyStrategy() + (routingKeyAttribute.Postfix ?? ""); + } + } +}