Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ It follows the Clean Architecture Principles and built on Domain-Driven-Design.
This tool is usefull to increases productivity on developing your next microservices.

----
[![Build Status](https://travis-ci.com/Genocs/clean-architecture-template.svg?branch=master)](https://travis-ci.com/genocs/clean-architecture-template) <a href="https://www.nuget.org/packages/Genocs.CleanArchitectureTemplate/" rel="Genocs.CleanCode">![NuGet](https://buildstats.info/nuget/genocs.cleanarchitecturetemplate)</a> [![Gitter](https://img.shields.io/badge/chat-on%20gitter-blue.svg)](https://gitter.im/genocs/)

[![Build Status](https://travis-ci.com/genocs/clean-architecture-template.svg?branch=master)](https://travis-ci.com/genocs/clean-architecture-template) <a href="https://www.nuget.org/packages/Genocs.CleanArchitectureTemplate/" rel="Genocs.CleanCode">![NuGet](https://buildstats.info/nuget/genocs.cleanarchitecturetemplate)</a> [![Gitter](https://img.shields.io/badge/chat-on%20gitter-blue.svg)](https://gitter.im/genocs/)


## How to create a project

Expand Down
6 changes: 3 additions & 3 deletions src/Genocs.CleanArchitectureTemplate.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata minClientVersion="5.0.0">
<id>Genocs.CleanArchitectureTemplate</id>
<version>1.0.1</version>
<version>1.1.0</version>
<authors>Nocco Giovanni Emanuele</authors>
<owners>[Genocs] Nocco Giovanni Emanuele</owners>
<projectUrl>https://github.com/Genocs/clean-architecture-template</projectUrl>
Expand All @@ -12,11 +12,11 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<title>The clean code template by Genocs</title>
<summary>
It generates a .NET Solution following the Clean Architecture Style, DDD and Separation of Concerns in Domain, Application, Infrastructure and UI.
A .NET template following the Clean Architecture Style, DDD and Separation of Concerns in Domain, Application, Infrastructure and UI. Separated WebApi host and enterprice service bus host
</summary>
<description>
Install the package:
$ dotnet new -i Genocs.CleanArchitectureTemplate::1.0.1
$ dotnet new -i Genocs.CleanArchitectureTemplate::1.1.0

The full clean project:
$ dotnet new cleanarchitecture
Expand Down
6 changes: 3 additions & 3 deletions src/template/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /app
COPY . .
RUN dotnet publish src/Genocs.MicroserviceLight.Template.WebApi -c release -o out

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
FROM mcr.microsoft.com/dotnet/aspnet:5.0
WORKDIR /app
COPY --from=build /app/out .
ENV ASPNETCORE_URLS http://*:80
ENV ASPNETCORE_ENVIRONMENT docker
ENV ASPNETCORE_ENVIRONMENT Docker
ENTRYPOINT dotnet Genocs.MicroserviceLight.Template.WebApi.dll
10 changes: 10 additions & 0 deletions src/template/Dockerfile.bus
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /app
COPY . .
RUN dotnet publish src/Genocs.MicroserviceLight.Template.BusHost -c release -o out

FROM mcr.microsoft.com/dotnet/aspnet:5.0
WORKDIR /app
COPY --from=build /app/out .
ENV ASPNETCORE_ENVIRONMENT Docker
ENTRYPOINT dotnet Genocs.MicroserviceLight.Template.BusHost.dll
1 change: 1 addition & 0 deletions src/template/Genocs.MicroserviceLight.Template.sln
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1BDA405C-FB8F-4259-9A2D-3C5EBFC6855F}"
ProjectSection(SolutionItems) = preProject
Dockerfile = Dockerfile
Dockerfile.bus = Dockerfile.bus
..\Genocs.CleanArchitectureTemplate.nuspec = ..\Genocs.CleanArchitectureTemplate.nuspec
EndProjectSection
EndProject
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
using Microsoft.Azure.ServiceBus;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Genocs.MicroserviceLight.Template.BusHost.HostServices
{
using Configurations;
using Shared.Commands;
using Microsoft.Extensions.Logging;

internal class AzureBusService : IHostedService
{
private readonly JsonSerializer _serializer;
private readonly ILogger<AzureBusService> _logger;
private readonly Infrastructure.AzureServiceBus.AzureServiceBusConfiguration _options;

private readonly Func<Infrastructure.AzureServiceBus.AzureServiceBusConfiguration, IQueueClient> _createQueueClient;

private IQueueClient _busClient;

public AzureBusService(IOptions<Infrastructure.AzureServiceBus.AzureServiceBusConfiguration> options, ILogger<AzureBusService> logger)
: this(options, logger, CreateQueueClient)
{ }

public AzureBusService(IOptions<Infrastructure.AzureServiceBus.AzureServiceBusConfiguration> options, ILogger<AzureBusService> logger,
Func<Infrastructure.AzureServiceBus.AzureServiceBusConfiguration, IQueueClient> createQueueClient)
{
_options = options.Value;

if (_options == null)
{
throw new NullReferenceException("options cannot be null");
}

_logger = logger;
_createQueueClient = createQueueClient;

_serializer = new JsonSerializer();
}

private static IQueueClient CreateQueueClient(Infrastructure.AzureServiceBus.AzureServiceBusConfiguration options)
{
ServiceBusConnectionStringBuilder connectionStringBuilder = new ServiceBusConnectionStringBuilder
{
Endpoint = options.QueueEndpoint,
EntityPath = options.QueueName,
SasKeyName = options.QueueAccessPolicyName,
SasKey = options.QueueAccessPolicyKey,
TransportType = TransportType.Amqp
};

return new QueueClient(connectionStringBuilder)
{
PrefetchCount = options.PrefetchCount
};
}

public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Starting...");
_busClient = _createQueueClient(_options);

_busClient.RegisterMessageHandler(
ProcessMessageAsync,
new MessageHandlerOptions(ProcessMessageExceptionAsync)
{
AutoComplete = false,
MaxConcurrentCalls = _options.MaxConcurrency
});

_logger.LogInformation("Started");
return Task.CompletedTask;
}

public async Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Stopping...");
await _busClient?.CloseAsync();

_logger.LogInformation("Stopped");
}

private async Task ProcessMessageAsync(Message message, CancellationToken ct)
{
_logger.LogInformation("Processing message {messageId}", message.MessageId);

if (TryGetStringMessage(message, out var messageContent))
{
_logger.LogInformation($"Received message with id '{message.MessageId}'. The content is '{messageContent}'. The message will be removed from queue");
return;
}

try
{
await _busClient.DeadLetterAsync(message.SystemProperties.LockToken);
}
catch (Exception e)
{
_logger.LogError(e, "Error moving message {messageId} to dead letter queue", message.MessageId);
}

return;
}

private Task ProcessMessageExceptionAsync(ExceptionReceivedEventArgs exceptionEvent)
{
_logger.LogError(exceptionEvent.Exception, "Exception processing message");

return Task.CompletedTask;
}

private bool TryGetSimpleMessage(Message incomingMessage, out SimpleMessage outcomingMessage)
{
outcomingMessage = null;
try
{
if (incomingMessage.Body != null && incomingMessage.Body.Length > 0)
{
using (var payloadStream = new MemoryStream(incomingMessage.Body, false))
using (var streamReader = new StreamReader(payloadStream, Encoding.UTF8))
using (var jsonReader = new JsonTextReader(streamReader))
{
// Please change the SimpleMessage objct with your own message type
outcomingMessage = _serializer.Deserialize<SimpleMessage>(jsonReader);
}
}

return true;
}
catch (Exception e)
{
_logger.LogError(e, "Cannot parse payload from message {messageId}", incomingMessage.MessageId);
}
return false;
}

private bool TryGetStringMessage(Message incomingMessage, out string outcomingMessage)
{
outcomingMessage = null;
try
{
if (incomingMessage.Body != null && incomingMessage.Body.Length > 0)
{
using (var payloadStream = new MemoryStream(incomingMessage.Body, false))
using (var streamReader = new StreamReader(payloadStream, Encoding.UTF8))
using (var jsonReader = new JsonTextReader(streamReader))
{
// Read the data as string
outcomingMessage = jsonReader.ReadAsString();
}
}

return true;
}
catch (Exception e)
{
_logger.LogError(e, "Cannot parse payload from message {messageId}", incomingMessage.MessageId);
}
return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System.Threading;
using System.Threading.Tasks;

namespace Genocs.MicroserviceLight.Template.BusHost.HostServices
{
using Handlers;
using Microsoft.Extensions.Logging;
using Rebus.Activation;
using Rebus.Bus;
using Rebus.Config;
using Shared.Events;
using System;

internal class RebusService : IHostedService
{
private readonly JsonSerializer _serializer;
private readonly ILogger<RebusService> _logger;
private readonly Infrastructure.RebusServiceBus.RebusBusOptions _options;


private BuiltinHandlerActivator _activator;
private IBus _bus;


public RebusService(IOptions<Infrastructure.RebusServiceBus.RebusBusOptions> options, ILogger<RebusService> logger)
{
_options = options.Value;

if (_options == null)
{
throw new NullReferenceException("options cannot be null");
}

_logger = logger;

_serializer = new JsonSerializer();

}

public async Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Starting...");

_activator = new BuiltinHandlerActivator();

_activator.Register(() => new Handler());

_bus = Configure.With(_activator)
.Logging(l => l.ColoredConsole(minLevel: Rebus.Logging.LogLevel.Debug))
.Transport(t => t.UseRabbitMq(_options.TransportConnection, _options.QueueName))
.Options(o => o.SetMaxParallelism(1))
.Start();


_activator.Bus.Subscribe<EventOccurred>().Wait();

_logger.LogInformation("Started");
await Task.CompletedTask;
}

public async Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Stopping...");
await Task.CompletedTask;
_logger.LogInformation("Stopped");
}
}
}
Loading