Skip to content

Commit

Permalink
RabbitMQ support (#144)
Browse files Browse the repository at this point in the history
  • Loading branch information
duracellko authored Aug 18, 2024
2 parents aec497d + f8b38a6 commit 66c6a82
Show file tree
Hide file tree
Showing 18 changed files with 1,309 additions and 61 deletions.
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<PackageVersion Include="Moq" Version="4.20.70" />
<PackageVersion Include="MSTest.TestAdapter" Version="3.5.2" />
<PackageVersion Include="MSTest.TestFramework" Version="3.5.2" />
<PackageVersion Include="RabbitMQ.Client" Version="6.8.1" />
<PackageVersion Include="RichardSzalay.MockHttp" Version="7.0.0" />
<PackageVersion Include="StackExchange.Redis" Version="2.8.0" />
<PackageVersion Include="System.Linq.Async" Version="6.0.1" />
Expand Down
14 changes: 14 additions & 0 deletions PlanningPokerCore.sln
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ApplicationIntegrationSimul
test\ApplicationIntegrationSimulator\README.md = test\ApplicationIntegrationSimulator\README.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duracellko.PlanningPoker.RabbitMQ", "src\Duracellko.PlanningPoker.RabbitMQ\Duracellko.PlanningPoker.RabbitMQ.csproj", "{811F62DE-C15B-4A90-887C-22F68B17EE2A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duracellko.PlanningPoker.RabbitMQ.Test", "test\Duracellko.PlanningPoker.RabbitMQ.Test\Duracellko.PlanningPoker.RabbitMQ.Test.csproj", "{9D21ABE1-B43C-4FD7-82D8-A4BA7AAF7991}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -106,6 +110,14 @@ Global
{EDD1B4E6-C1DE-45F6-A86A-ABEA17C30CEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EDD1B4E6-C1DE-45F6-A86A-ABEA17C30CEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EDD1B4E6-C1DE-45F6-A86A-ABEA17C30CEE}.Release|Any CPU.Build.0 = Release|Any CPU
{811F62DE-C15B-4A90-887C-22F68B17EE2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{811F62DE-C15B-4A90-887C-22F68B17EE2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{811F62DE-C15B-4A90-887C-22F68B17EE2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{811F62DE-C15B-4A90-887C-22F68B17EE2A}.Release|Any CPU.Build.0 = Release|Any CPU
{9D21ABE1-B43C-4FD7-82D8-A4BA7AAF7991}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9D21ABE1-B43C-4FD7-82D8-A4BA7AAF7991}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D21ABE1-B43C-4FD7-82D8-A4BA7AAF7991}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9D21ABE1-B43C-4FD7-82D8-A4BA7AAF7991}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -125,6 +137,8 @@ Global
{B5F7A7A3-C1F5-4497-98FE-6659932DDBCF} = {9BE135A3-3D75-40BD-BA92-5961167FD719}
{EDD1B4E6-C1DE-45F6-A86A-ABEA17C30CEE} = {6620FD4B-0154-46A5-A929-8326DB18769F}
{11DAA9C8-F593-4B97-95DC-25341AC22E98} = {6620FD4B-0154-46A5-A929-8326DB18769F}
{811F62DE-C15B-4A90-887C-22F68B17EE2A} = {9BE135A3-3D75-40BD-BA92-5961167FD719}
{9D21ABE1-B43C-4FD7-82D8-A4BA7AAF7991} = {6620FD4B-0154-46A5-A929-8326DB18769F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C22E21A9-E10B-4324-BD51-350342EA8627}
Expand Down
45 changes: 6 additions & 39 deletions docker/test/RunTests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@ Param (

$projectPath = $PSScriptRoot
$pesterVersion = '5.6.1'
$redisVersion = '7.4'
$rabbitmqVersion = '3.13'

$imageTag = 'local-test'
if (![string]::IsNullOrEmpty($PlanningPokerImageTag)) {
$imageTag = $PlanningPokerImageTag
}

$composeProjectName = 'planningpoker'
$redisAppPassword = (New-Guid).ToString()
$redisAdminPassword = (New-Guid).ToString()
$rabbitmqPassword = (New-Guid).ToString()
$applicationPorts = @(5001, 5002, 5003)

function RandomizeApplicationPorts() {
Expand All @@ -31,45 +30,15 @@ function SetupEnvironmentVariables() {
[Parameter(Mandatory = $true)]
[int[]] $ApplicationPorts,
[Parameter(Mandatory = $true)]
[string] $AppPassword
[string] $RabbitMQPassword
)

$env:PLANNINGPOKER_IMAGENAME = 'duracellko/planningpoker:' + $AppImageTag
$env:PLANNINGPOKER_APP1_PORT = $ApplicationPorts[0]
$env:PLANNINGPOKER_APP2_PORT = $ApplicationPorts[1]
$env:PLANNINGPOKER_APP3_PORT = $ApplicationPorts[2]
$env:PLANNINGPOKER_APP_REDIS_PASSWORD = $AppPassword
$env:PLANNINGPOKER_REDIS_VERSION = $redisVersion
}

function PrepareRedisConfiguration() {
param (
[Parameter(Mandatory = $true)]
[string] $AppPassword,
[Parameter(Mandatory = $true)]
[string] $AdminPassword
)

$configurationPath = Join-Path -Path $projectPath -ChildPath 'redis.conf'
$configuration = Get-Content -Path $configurationPath -Raw
$configuration = $configuration.Replace('${PLANNINGPOKER_ADMIN_PASSWORD}', $AdminPassword)
$configuration = $configuration.Replace('${PLANNINGPOKER_APP_PASSWORD}', $AppPassword)
Set-Content -Path $configurationPath -Value $configuration -NoNewline
}

function RevertRedisConfiguration() {
param (
[Parameter(Mandatory = $true)]
[string] $AppPassword,
[Parameter(Mandatory = $true)]
[string] $AdminPassword
)

$configurationPath = Join-Path -Path $projectPath -ChildPath 'redis.conf'
$configuration = Get-Content -Path $configurationPath -Raw
$configuration = $configuration.Replace($AdminPassword, '${PLANNINGPOKER_ADMIN_PASSWORD}')
$configuration = $configuration.Replace($AppPassword, '${PLANNINGPOKER_APP_PASSWORD}')
Set-Content -Path $configurationPath -Value $configuration -NoNewline
$env:PLANNINGPOKER_APP_RABBITMQ_PASSWORD = $RabbitMQPassword
$env:PLANNINGPOKER_RABBITMQ_VERSION = $rabbitmqVersion
}

function ComposeDockerUp() {
Expand Down Expand Up @@ -118,8 +87,7 @@ $composeFilePath = Join-Path -Path $projectPath -ChildPath 'compose.yml'

try {
RandomizeApplicationPorts
SetupEnvironmentVariables -AppImageTag $imageTag -ApplicationPorts $applicationPorts -AppPassword $redisAppPassword
PrepareRedisConfiguration -AppPassword $redisAppPassword -AdminPassword $redisAdminPassword
SetupEnvironmentVariables -AppImageTag $imageTag -ApplicationPorts $applicationPorts -RabbitMQPassword $rabbitmqPassword

ComposeDockerUp -ComposePath $composeFilePath -ProjectName $composeProjectName

Expand Down Expand Up @@ -157,6 +125,5 @@ try {
}
}
finally {
RevertRedisConfiguration -AppPassword $redisAppPassword -AdminPassword $redisAdminPassword
ComposeDockerDown -ComposePath $composeFilePath -ProjectName $composeProjectName
}
35 changes: 21 additions & 14 deletions docker/test/compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ services:
planningpoker-r1:
image: ${PLANNINGPOKER_IMAGENAME:-duracellko/planningpoker:local-test}
depends_on:
- redis
rabbitmq:
condition: service_healthy
environment:
PlanningPoker__ServiceBusConnectionString: "REDIS:redis,user=planningpoker,password=${PLANNINGPOKER_APP_REDIS_PASSWORD}"
PlanningPoker__ServiceBusConnectionString: "RABBITMQ:amqp://planningpoker:${PLANNINGPOKER_APP_RABBITMQ_PASSWORD}@rabbitmq/"
PlanningPoker__InitializationMessageTimeout: 3
PlanningPokerClient__UseHttpClient: true
ports:
Expand All @@ -13,9 +14,10 @@ services:
planningpoker-r2:
image: ${PLANNINGPOKER_IMAGENAME:-duracellko/planningpoker:local-test}
depends_on:
- redis
rabbitmq:
condition: service_healthy
environment:
PlanningPoker__ServiceBusConnectionString: "REDIS:redis,user=planningpoker,password=${PLANNINGPOKER_APP_REDIS_PASSWORD}"
PlanningPoker__ServiceBusConnectionString: "RABBITMQ:amqp://planningpoker:${PLANNINGPOKER_APP_RABBITMQ_PASSWORD}@rabbitmq/"
PlanningPoker__InitializationMessageTimeout: 3
PlanningPokerClient__UseHttpClient: true
ports:
Expand All @@ -24,19 +26,24 @@ services:
planningpoker-r3:
image: ${PLANNINGPOKER_IMAGENAME:-duracellko/planningpoker:local-test}
depends_on:
- redis
rabbitmq:
condition: service_healthy
environment:
PlanningPoker__ServiceBusConnectionString: "REDIS:redis,user=planningpoker,password=${PLANNINGPOKER_APP_REDIS_PASSWORD}"
PlanningPoker__ServiceBusConnectionString: "RABBITMQ:amqp://planningpoker:${PLANNINGPOKER_APP_RABBITMQ_PASSWORD}@rabbitmq/"
PlanningPoker__InitializationMessageTimeout: 3
PlanningPokerClient__UseHttpClient: true
ports:
- "${PLANNINGPOKER_APP3_PORT:-5003}:8080"

redis:
image: redis:${PLANNINGPOKER_REDIS_VERSION:-latest}
volumes:
- type: bind
source: ./redis.conf
target: /usr/local/etc/redis/redis.conf
read_only: true
command: [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
rabbitmq:
image: rabbitmq:${PLANNINGPOKER_RABBITMQ_VERSION:-latest}
environment:
RABBITMQ_DEFAULT_USER: planningpoker
RABBITMQ_DEFAULT_PASS: ${PLANNINGPOKER_APP_RABBITMQ_PASSWORD}
healthcheck:
test: "rabbitmq-diagnostics -q check_running && rabbitmq-diagnostics -q check_local_alarms && rabbitmq-diagnostics -q check_port_listener 5672"
interval: 30s
timeout: 10s
retries: 3
start_period: 20s
start_interval: 2s
3 changes: 0 additions & 3 deletions docker/test/redis.conf

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)'=='Release'">
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="RabbitMQ.Client" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Duracellko.PlanningPoker.Azure\Duracellko.PlanningPoker.Azure.csproj" />
</ItemGroup>

<ItemGroup>
<Compile Update="Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>

<ItemGroup>
<EmbeddedResource Update="Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>

</Project>
41 changes: 41 additions & 0 deletions src/Duracellko.PlanningPoker.RabbitMQ/IMessageConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using Duracellko.PlanningPoker.Azure;

namespace Duracellko.PlanningPoker.RabbitMQ;

/// <summary>
/// When implemented, then object is able to convert messages of type <see cref="T:NodeMessage"/> to RabbitMQ message and vice versa.
/// </summary>
public interface IMessageConverter
{
/// <summary>
/// Gets headers of RabbitMQ message converted from <see cref="T:NodeMessage"/>.
/// </summary>
/// <param name="message">The message to convert.</param>
/// <returns>Headers of the message.</returns>
IDictionary<string, object> GetMessageHeaders(NodeMessage message);

/// <summary>
/// Gets body of RabbitMQ message converted from <see cref="T:NodeMessage"/>.
/// </summary>
/// <param name="message">The message to convert.</param>
/// <returns>Body of the message.</returns>
ReadOnlyMemory<byte> GetMessageBody(NodeMessage message);

/// <summary>
/// Converts RabbitMQ message headers and body to <see cref="T:NodeMessage"/> object.
/// </summary>
/// <param name="headers">Headers of the message to convert.</param>
/// <param name="body">Body of the message to convert.</param>
/// <returns>Converted message of NodeMessage type.</returns>
NodeMessage GetNodeMessage(IDictionary<string, object> headers, ReadOnlyMemory<byte> body);

/// <summary>
/// Gets decoded value of Rabbit MQ message header with specified key.
/// </summary>
/// <param name="headers">The collection of header key-value pairs.</param>
/// <param name="key">The key to get header value for.</param>
/// <returns>Value header with specified key.</returns>
string? GetHeader(IDictionary<string, object> headers, string key);
}
Loading

0 comments on commit 66c6a82

Please sign in to comment.