Skip to content

Commit

Permalink
Basic RabbitMQ comms from ClinicManagement to FrontDesk working
Browse files Browse the repository at this point in the history
  • Loading branch information
ardalis committed Mar 11, 2021
1 parent e1ff830 commit 63b241d
Show file tree
Hide file tree
Showing 20 changed files with 290 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -142,22 +142,22 @@
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.1" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="9.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Core" Version="1.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.3">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.9" />
<PackageReference Include="MediatR" Version="9.0.0" />
<PackageReference Include="PluralsightDdd.SharedKernel" Version="1.1.3" />
<PackageReference Include="PluralsightDdd.SharedKernel" Version="1.1.4" />
<PackageReference Include="RabbitMQ.Client" Version="6.2.1" />
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.0.2" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.0.2" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.2" />
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.4" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using AutoMapper;
using BlazorShared.Models.Doctor;
using ClinicManagement.Core.Aggregates;
using ClinicManagement.Core.Interfaces;
using Microsoft.AspNetCore.Mvc;
using PluralsightDdd.SharedKernel.Interfaces;
using Swashbuckle.AspNetCore.Annotations;
Expand All @@ -16,11 +17,15 @@ public class Create : BaseAsyncEndpoint
{
private readonly IRepository<Doctor> _repository;
private readonly IMapper _mapper;
private readonly IMessagePublisher _messagePublisher;

public Create(IRepository<Doctor> repository, IMapper mapper)
public Create(IRepository<Doctor> repository,
IMapper mapper,
IMessagePublisher messagePublisher)
{
_repository = repository;
_mapper = mapper;
_messagePublisher = messagePublisher;
}

[HttpPost("api/doctors")]
Expand All @@ -40,7 +45,28 @@ public override async Task<ActionResult<CreateDoctorResponse>> HandleAsync(Creat
var dto = _mapper.Map<DoctorDto>(toAdd);
response.Doctor = dto;

var appEvent = new EntityCreatedEvent(_mapper.Map<NamedEntity>(toAdd));
_messagePublisher.Publish(appEvent);

return Ok(response);
}
}

public class EntityCreatedEvent : IApplicationEvent
{
public string EventType => "Doctor-Created";
public NamedEntity Entity { get; set; }

public EntityCreatedEvent(NamedEntity entity)
{
Entity = entity;
}
}

public class NamedEntity
{
public int Id { get; set; }
public string Name { get; set; }
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using AutoMapper;
using BlazorShared.Models.Room;
using ClinicManagement.Core.Aggregates;
using ClinicManagement.Core.Interfaces;
using ClinicManagement.Core.Specifications;
using Microsoft.AspNetCore.Mvc;
using PluralsightDdd.SharedKernel.Interfaces;
Expand All @@ -19,7 +20,8 @@ public class List : BaseAsyncEndpoint
private readonly IRepository<Room> _repository;
private readonly IMapper _mapper;

public List(IRepository<Room> repository, IMapper mapper)
public List(IRepository<Room> repository,
IMapper mapper)
{
_repository = repository;
_mapper = mapper;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using AutoMapper;
using BlazorShared.Models.Doctor;
using ClinicManagement.Api.DoctorEndpoints;
using ClinicManagement.Core.Aggregates;

namespace ClinicManagement.Api.MappingProfiles
Expand All @@ -16,6 +17,7 @@ public DoctorProfile()
CreateMap<UpdateDoctorRequest, Doctor>()
.ForMember(dto => dto.Id, options => options.MapFrom(src => src.DoctorId));
CreateMap<DeleteDoctorRequest, Doctor>();
CreateMap<Doctor, NamedEntity>();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"dotnetRunMessages": "true",
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:5101;http://localhost:5100",
"applicationUrl": "https://localhost:6101;http://localhost:6100",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
Expand Down
35 changes: 17 additions & 18 deletions ClinicManagement/src/ClinicManagement.Api/RabbitMQService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using PluralsightDdd.SharedKernel;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;

Expand All @@ -17,9 +18,9 @@ public class RabbitMQService : IHostedService
private const string hostname = "localhost"; // when running in VS, no docker, rabbitmq running on localhost / or in a container
//private const string hostname = "host.docker.internal"; // rabbit running on machine; app running in docker
//private const string hostname = "rabbit1"; // everything in docker via docker-compose
private const string queuein = "cm-queue-in";
private const string queueout = "fd-queue-in";
private const string exchangeName = "frontdesk-clinicmanagement";
private const string exchangeName = MessagingConstants.Exchanges.FRONTDESK_CLINICMANAGEMENT_EXCHANGE;
private const string queuein = MessagingConstants.Queues.FDCM_CLINICMANAGEMENT_IN;
private const string queueout = MessagingConstants.Queues.FDCM_FRONTDESK_IN;

// Manually Run RabbitMQ
// docker run --rm -it --hostname ddd-sample-rabbit -p 15672:15672 -p 5672:5672 rabbitmq:3-management
Expand All @@ -34,8 +35,8 @@ private void Run()
HostName = hostname,
// port = 5672, default value
VirtualHost = "/",
UserName = "guest",
Password = "guest"
UserName = MessagingConstants.Credentials.DEFAULT_USERNAME,
Password = MessagingConstants.Credentials.DEFAULT_PASSWORD
};

this.connection = factory.CreateConnection();
Expand Down Expand Up @@ -89,28 +90,26 @@ public Task StopAsync(CancellationToken cancellationToken)
return Task.CompletedTask;
}

// Publish a received message with "reply:" prefix
private void OnMessageReceived(object model, BasicDeliverEventArgs args)
{
var body = args.Body.ToArray();
var message = Encoding.UTF8.GetString(body);
Console.WriteLine(" [x] Received {0}", message);

int dots = message.Split('.').Length - 1;
//int dots = message.Split('.').Length - 1;

// Publish a response
string outMessage = "reply:" + message;
body = Encoding.UTF8.GetBytes(outMessage);
//// Publish a response
//string outMessage = "reply:" + message;
//body = Encoding.UTF8.GetBytes(outMessage);

this.channel.BasicPublish(exchange: exchangeName,
routingKey: "out",
basicProperties: this.channel.CreateBasicProperties(),
body: body);
Console.WriteLine(" [x] Sent {0}", outMessage);
//this.channel.BasicPublish(exchange: exchangeName,
// routingKey: "out",
// basicProperties: this.channel.CreateBasicProperties(),
// body: body);
//Console.WriteLine(" [x] Sent {0}", outMessage);

Console.WriteLine(" [x] Done");
this.channel.BasicAck(deliveryTag: args.DeliveryTag, multiple: false);
//Console.WriteLine(" [x] Done");
//this.channel.BasicAck(deliveryTag: args.DeliveryTag, multiple: false);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": "true",
"applicationUrl": "https://localhost:5001;http://localhost:5000"
"applicationUrl": "https://localhost:6001;http://localhost:6000"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"baseUrls": {
"apiBase": "https://localhost:5101/api/",
"apiBase": "https://localhost:6101/api/",
"webBase": "https://localhost:5401/"
},
"Logging": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<PackageReference Include="Ardalis.Result" Version="3.1.0" />
<PackageReference Include="MediatR" Version="9.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="PluralsightDdd.SharedKernel" Version="1.1.3" />
<PackageReference Include="PluralsightDdd.SharedKernel" Version="1.1.4" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
<PackageReference Include="Autofac" Version="6.1.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.1.0" />
<PackageReference Include="Ardalis.EFCore.Extensions" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" PrivateAssets="all" Version="5.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.2" />
<PackageReference Include="PluralsightDdd.SharedKernel" Version="1.1.3" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" PrivateAssets="all" Version="5.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.4" />
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="5.0.4" />
<PackageReference Include="PluralsightDdd.SharedKernel" Version="1.1.4" />
<PackageReference Include="RabbitMQ.Client" Version="6.2.1" />
<PackageReference Include="SQLite" Version="3.13.0" />
<PackageReference Include="NETStandard.Library" Version="2.0.3" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
using ClinicManagement.Core.Aggregates;
using ClinicManagement.Core.Interfaces;
using ClinicManagement.Infrastructure.Data;
using ClinicManagement.Infrastructure.Messaging;
using MediatR;
using MediatR.Pipeline;
using Microsoft.Extensions.ObjectPool;
using PluralsightDdd.SharedKernel.Interfaces;
using RabbitMQ.Client;
using Module = Autofac.Module;

namespace ClinicManagement.Infrastructure
Expand Down Expand Up @@ -79,6 +82,17 @@ private void RegisterCommonDependencies(ContainerBuilder builder)
.InstancePerLifetimeScope();

builder.RegisterType<AppDbContextSeed>().InstancePerLifetimeScope();

// register RabbitMQ types
builder.RegisterType<RabbitMessagePublisher>()
.As<IMessagePublisher>()
.SingleInstance();
builder.RegisterType<DefaultObjectPoolProvider>()
.As<ObjectPoolProvider>()
.SingleInstance();
builder.RegisterType<RabbitModelPooledObjectPolicy>()
.As<IPooledObjectPolicy<IModel>>()
.SingleInstance();
}

private void RegisterDevelopmentOnlyDependencies(ContainerBuilder builder)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System;
using System.Text;
using Ardalis.GuardClauses;
using ClinicManagement.Core.Interfaces;
using PluralsightDdd.SharedKernel.Interfaces;
using Microsoft.Extensions.ObjectPool;
using RabbitMQ.Client;
using System.Text.Json;
using PluralsightDdd.SharedKernel;

namespace ClinicManagement.Infrastructure.Messaging
{
public class RabbitMessagePublisher : IMessagePublisher
{
private readonly DefaultObjectPool<IModel> _objectPool;

public RabbitMessagePublisher(IPooledObjectPolicy<IModel> objectPolicy)
{
_objectPool = new DefaultObjectPool<IModel>(objectPolicy, Environment.ProcessorCount * 2);
}

public void Publish(IApplicationEvent applicationEvent)
{
Guard.Against.Null(applicationEvent, nameof(applicationEvent));

var channel = _objectPool.Get();

object message = (object)applicationEvent;
try
{
string exchangeName = MessagingConstants.Exchanges.FRONTDESK_CLINICMANAGEMENT_EXCHANGE;
channel.ExchangeDeclare(exchangeName, "direct", true, false, null);

var sendBytes = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(message));

var properties = channel.CreateBasicProperties();
properties.Persistent = true;

channel.BasicPublish(
exchange: exchangeName,
routingKey: "entity-changes",
basicProperties: properties,
body: sendBytes);
}
catch (Exception ex)
{
throw ex;
}
finally
{
_objectPool.Return(channel);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using Microsoft.Extensions.ObjectPool;
using RabbitMQ.Client;
using PluralsightDdd.SharedKernel;

namespace ClinicManagement.Infrastructure.Messaging
{
// source: https://www.c-sharpcorner.com/article/publishing-rabbitmq-message-in-asp-net-core/
public class RabbitModelPooledObjectPolicy : IPooledObjectPolicy<IModel>
{
private readonly IConnection _connection;

public RabbitModelPooledObjectPolicy()
{
_connection = GetConnection();
}

private IConnection GetConnection()
{
var factory = new ConnectionFactory()
{
HostName = "localhost", // TODO: Read from config
UserName = MessagingConstants.Credentials.DEFAULT_USERNAME,
Password = MessagingConstants.Credentials.DEFAULT_PASSWORD,
Port = 5672,
VirtualHost = "/",
};

return factory.CreateConnection();
}

public IModel Create()
{
return _connection.CreateModel();
}

public bool Return(IModel obj)
{
if (obj.IsOpen)
{
return true;
}
else
{
obj?.Dispose();
return false;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.1" />
<PackageReference Include="Moq" Version="4.16.0" />
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
Loading

0 comments on commit 63b241d

Please sign in to comment.