├── README.md
├── src
├── Sample.Masstransit.Worker
│ ├── Workers
│ │ ├── QueueClientUpdatedConsumer.cs
│ │ ├── QueueSendEmailConsumer.cs
│ │ ├── TimerVideoConsumer.cs
│ │ └── QueueClientInsertedConsumer.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── appsettings.json
│ ├── Sample.Masstransit.Worker.csproj
│ ├── Dockerfile
│ └── Program.cs
├── Sample.Masstransit.WebApi.Core
│ ├── Events
│ │ ├── SendEmailEvent.cs
│ │ ├── ConvertVideoEvent.cs
│ │ ├── ClientUpdatedEvent.cs
│ │ └── ClientInsertedEvent.cs
│ ├── AppSettings.cs
│ ├── Extensions
│ │ ├── ReceiveObserverExtensions.cs
│ │ ├── OpenTelemetryExtension.cs
│ │ ├── MasstransitExtension.cs
│ │ └── SerilogExtensions.cs
│ └── Sample.Masstransit.WebApi.Core.csproj
└── Sample.Masstransit.WebApi
│ ├── appsettings.json
│ ├── Dockerfile
│ ├── Sample.Masstransit.WebApi.csproj
│ ├── Properties
│ └── launchSettings.json
│ ├── Program.cs
│ └── Controllers
│ └── ClientController.cs
├── .dockerignore
├── docker-compose.yml
├── sample-masstransit.sln
└── .gitignore
/README.md:
--------------------------------------------------------------------------------
1 | # sample-masstransit
2 |
3 | - .NET 9.0
4 | - Swashbuckle Swagger
5 | - Serilog
6 | - MassTransit
7 |
8 | https://henriquemauri.net/rabbitmq-com-masstransit-no-net-6/
9 |
--------------------------------------------------------------------------------
/src/Sample.Masstransit.Worker/Workers/QueueClientUpdatedConsumer.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hgmauri/sample-masstransit/HEAD/src/Sample.Masstransit.Worker/Workers/QueueClientUpdatedConsumer.cs
--------------------------------------------------------------------------------
/src/Sample.Masstransit.WebApi.Core/Events/SendEmailEvent.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Sample.Masstransit.WebApi.Core.Events;
3 |
4 | public class SendEmailEvent
5 | {
6 | public string Email { get; set; }
7 | }
--------------------------------------------------------------------------------
/src/Sample.Masstransit.WebApi.Core/Events/ConvertVideoEvent.cs:
--------------------------------------------------------------------------------
1 | namespace Sample.Masstransit.WebApi.Core.Events;
2 |
3 | public class ConvertVideoEvent
4 | {
5 | public string GroupId { get; set; }
6 | public int Index { get; set; }
7 | public int Count { get; set; }
8 | public string Path { get; set; }
9 | }
--------------------------------------------------------------------------------
/src/Sample.Masstransit.WebApi.Core/Events/ClientUpdatedEvent.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Sample.Masstransit.WebApi.Core.Events;
3 |
4 | public class ClientUpdatedEvent
5 | {
6 | public string ClientId { get; set; }
7 | public string Name { get; set; }
8 | public DateTime BirthDate { get; set; }
9 | public DateTime CreatedAt { get; set; }
10 | }
--------------------------------------------------------------------------------
/src/Sample.Masstransit.Worker/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "Sample.Masstransit.Worker": {
4 | "commandName": "Project",
5 | "environmentVariables": {
6 | "DOTNET_ENVIRONMENT": "Development"
7 | },
8 | "dotnetRunMessages": true
9 | },
10 | "Docker": {
11 | "commandName": "Docker"
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Sample.Masstransit.WebApi.Core/Events/ClientInsertedEvent.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Sample.Masstransit.WebApi.Core.Events;
3 |
4 | public class ClientInsertedEvent
5 | {
6 | public string ClientId { get; set; }
7 | public string Name { get; set; }
8 | public string Email { get; set; }
9 | public DateTime BirthDate { get; set; }
10 | public DateTime CreatedAt { get; set; }
11 | }
--------------------------------------------------------------------------------
/src/Sample.Masstransit.WebApi.Core/AppSettings.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Sample.Masstransit.WebApi.Core;
3 | public class AppSettings
4 | {
5 | public DistributedTracingOptions DistributedTracing { get; set; }
6 | }
7 |
8 | public class DistributedTracingOptions
9 | {
10 | public JaegerOptions Jaeger { get; set; }
11 | }
12 |
13 | public class JaegerOptions
14 | {
15 | public string ServiceName { get; set; }
16 | }
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.dockerignore
3 | **/.env
4 | **/.git
5 | **/.gitignore
6 | **/.project
7 | **/.settings
8 | **/.toolstarget
9 | **/.vs
10 | **/.vscode
11 | **/*.*proj.user
12 | **/*.dbmdl
13 | **/*.jfm
14 | **/azds.yaml
15 | **/bin
16 | **/charts
17 | **/docker-compose*
18 | **/Dockerfile*
19 | **/node_modules
20 | **/npm-debug.log
21 | **/obj
22 | **/secrets.dev.yaml
23 | **/values.dev.yaml
24 | LICENSE
25 | README.md
26 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.8"
2 | services:
3 |
4 | rabbitmq:
5 | image: masstransit/rabbitmq
6 | ports:
7 | - 5672:5672
8 | - 15672:15672
9 |
10 | jaeger:
11 | image: jaegertracing/all-in-one:latest
12 | ports:
13 | - "5775:5775/udp"
14 | - "6831:6831/udp"
15 | - "6832:6832/udp"
16 | - "5778:5778"
17 | - "16686:16686"
18 | - "14268:14268"
19 | - "9411:9411"
20 | - "4317:4317"
--------------------------------------------------------------------------------
/src/Sample.Masstransit.Worker/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.Hosting.Lifetime": "Information"
6 | }
7 | },
8 | "ConnectionStrings": {
9 | "RabbitMq": "amqp://guest:guest@localhost:5672"
10 | },
11 | "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317",
12 | "DistributedTracing": {
13 | "IsEnabled": true,
14 | "Jaeger": {
15 | "ServiceName": "Worker Sample"
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Sample.Masstransit.WebApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | },
8 | "ConnectionStrings": {
9 | "RabbitMq": "amqp://guest:guest@localhost:5672"
10 | },
11 | "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317",
12 | "DistributedTracing": {
13 | "IsEnabled": true,
14 | "Jaeger": {
15 | "ServiceName": "API Sample"
16 | }
17 | },
18 | "AllowedHosts": "*"
19 | }
20 |
--------------------------------------------------------------------------------
/src/Sample.Masstransit.Worker/Sample.Masstransit.Worker.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 | dotnet-Sample.Masstransit.Worker-27AD80BC-FB2B-401A-A269-C5EBF68BB6D0
8 | Linux
9 | ..\..
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/Sample.Masstransit.Worker/Workers/QueueSendEmailConsumer.cs:
--------------------------------------------------------------------------------
1 | using MassTransit;
2 | using Sample.Masstransit.WebApi.Core.Events;
3 |
4 | namespace Sample.Masstransit.Worker.Workers;
5 |
6 | public class QueueSendEmailConsumer : IConsumer
7 | {
8 | public Task Consume(ConsumeContext context)
9 | {
10 | Serilog.Log.Information($"Email enviado com sucesso: {context.Message.Email}");
11 | return Task.CompletedTask;
12 | }
13 | }
14 |
15 | public class QueueSendEmailConsumerDefinition : ConsumerDefinition
16 | {
17 | protected override void ConfigureConsumer(IReceiveEndpointConfigurator endpointConfigurator, IConsumerConfigurator consumerConfigurator, IRegistrationContext context)
18 | {
19 | consumerConfigurator.UseMessageRetry(retry => retry.Interval(3, TimeSpan.FromSeconds(3)));
20 | }
21 | }
--------------------------------------------------------------------------------
/src/Sample.Masstransit.Worker/Workers/TimerVideoConsumer.cs:
--------------------------------------------------------------------------------
1 | using MassTransit;
2 | using Sample.Masstransit.WebApi.Core.Events;
3 |
4 | namespace Sample.Masstransit.Worker.Workers;
5 |
6 | public class TimerVideoConsumer : IJobConsumer
7 | {
8 | public async Task Run(JobContext context)
9 | {
10 | await Task.Delay(TimeSpan.FromSeconds(3));
11 | }
12 | }
13 |
14 | public class TimerVideoConsumerDefinition : ConsumerDefinition
15 | {
16 | protected override void ConfigureConsumer(IReceiveEndpointConfigurator endpointConfigurator, IConsumerConfigurator consumerConfigurator, IRegistrationContext context)
17 | {
18 | consumerConfigurator.Options>(options =>
19 | options.SetRetry(r => r.Interval(3, TimeSpan.FromSeconds(30))).SetJobTimeout(TimeSpan.FromMinutes(1)).SetConcurrentJobLimit(10));
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/src/Sample.Masstransit.Worker/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base
2 | WORKDIR /app
3 |
4 | FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
5 | WORKDIR /src
6 | COPY ["src/Sample.Masstransit.Worker/Sample.Masstransit.Worker.csproj", "src/Sample.Masstransit.Worker/"]
7 | RUN dotnet restore "src/Sample.Masstransit.Worker/Sample.Masstransit.Worker.csproj"
8 |
9 | COPY . .
10 | WORKDIR "/src/src/Sample.Masstransit.Worker"
11 | RUN dotnet build "Sample.Masstransit.Worker.csproj" -c Release -o /app/build
12 |
13 | FROM build AS publish
14 | RUN dotnet publish "Sample.Masstransit.Worker.csproj" -c Release -o /app/publish
15 |
16 | ENV TZ=America/Sao_Paulo
17 | ENV LANG pt-BR
18 | ENV LANGUAGE pt-BR
19 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
20 |
21 | FROM base AS final
22 | WORKDIR /app
23 | COPY --from=publish /app/publish .
24 | ENTRYPOINT ["dotnet", "Sample.Masstransit.Worker.dll"]
25 |
--------------------------------------------------------------------------------
/src/Sample.Masstransit.WebApi/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
2 | WORKDIR /app
3 | EXPOSE 80
4 |
5 | FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
6 | WORKDIR /src
7 | COPY ["src/Sample.Masstransit.WebApi/Sample.Masstransit.WebApi.csproj", "src/Sample.Masstransit.WebApi/"]
8 | RUN dotnet restore "src/Sample.Masstransit.WebApi/Sample.Masstransit.WebApi.csproj"
9 | COPY . .
10 | WORKDIR "/src/src/Sample.Masstransit.WebApi"
11 | RUN dotnet build "Sample.Masstransit.WebApi.csproj" -c Release -o /app/build
12 |
13 | FROM build AS publish
14 | RUN dotnet publish "Sample.Masstransit.WebApi.csproj" -c Release -o /app/publish
15 |
16 | ENV TZ=America/Sao_Paulo
17 | ENV LANG pt-BR
18 | ENV LANGUAGE pt-BR
19 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
20 |
21 | FROM base AS final
22 | WORKDIR /app
23 | COPY --from=publish /app/publish .
24 | ENTRYPOINT ["dotnet", "Sample.Masstransit.WebApi.dll"]
--------------------------------------------------------------------------------
/src/Sample.Masstransit.WebApi/Sample.Masstransit.WebApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 | c49d3603-2412-4d6c-ac0b-1a168a6b3460
8 | Linux
9 | ..\..
10 | ..\..\docker-compose.dcproj
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/Sample.Masstransit.WebApi.Core/Extensions/ReceiveObserverExtensions.cs:
--------------------------------------------------------------------------------
1 | using MassTransit;
2 |
3 | namespace Sample.Masstransit.WebApi.Core.Extensions;
4 |
5 | public class ReceiveObserverExtensions : IReceiveObserver
6 | {
7 | public Task ConsumeFault(ConsumeContext context, TimeSpan duration, string consumerType, Exception exception) where T : class
8 | {
9 | return Task.CompletedTask;
10 | }
11 |
12 | public Task PostConsume(ConsumeContext context, TimeSpan duration, string consumerType) where T : class
13 | {
14 | return Task.CompletedTask;
15 | }
16 |
17 | public Task PostReceive(ReceiveContext context)
18 | {
19 | return Task.CompletedTask;
20 | }
21 |
22 | public Task PreReceive(ReceiveContext context)
23 | {
24 | return Task.CompletedTask;
25 | }
26 |
27 | public Task ReceiveFault(ReceiveContext context, Exception exception)
28 | {
29 | return Task.CompletedTask;
30 | }
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/src/Sample.Masstransit.WebApi.Core/Extensions/OpenTelemetryExtension.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using OpenTelemetry.Resources;
3 | using OpenTelemetry.Trace;
4 |
5 | namespace Sample.Masstransit.WebApi.Core.Extensions;
6 |
7 | public static class OpenTelemetryExtension
8 | {
9 | public static void AddOpenTelemetry(this IServiceCollection services, AppSettings appSettings)
10 | {
11 | services.AddOpenTelemetry().WithTracing(telemetry =>
12 | {
13 | var resourceBuilder = ResourceBuilder.CreateDefault()
14 | .AddTelemetrySdk()
15 | .AddEnvironmentVariableDetector()
16 | .AddService(appSettings?.DistributedTracing?.Jaeger?.ServiceName ?? "Service");
17 |
18 | telemetry.AddSource("MassTransit")
19 | .AddMassTransitInstrumentation()
20 | .SetResourceBuilder(resourceBuilder)
21 | .AddAspNetCoreInstrumentation()
22 | .AddHttpClientInstrumentation()
23 | .SetSampler(new AlwaysOnSampler());
24 |
25 | telemetry.AddOtlpExporter();
26 | });
27 | }
28 | }
--------------------------------------------------------------------------------
/src/Sample.Masstransit.WebApi.Core/Extensions/MasstransitExtension.cs:
--------------------------------------------------------------------------------
1 | using MassTransit;
2 | using Microsoft.Extensions.Configuration;
3 | using Microsoft.Extensions.DependencyInjection;
4 |
5 | namespace Sample.Masstransit.WebApi.Core.Extensions;
6 |
7 | public static class MasstransitExtension
8 | {
9 | public static void AddMassTransitExtension(this IServiceCollection services, IConfiguration configuration)
10 | {
11 | services.AddMassTransit(x =>
12 | {
13 | x.AddDelayedMessageScheduler();
14 | x.SetKebabCaseEndpointNameFormatter();
15 |
16 | x.UsingRabbitMq((ctx, cfg) =>
17 | {
18 | cfg.Host(configuration.GetConnectionString("RabbitMq"));
19 |
20 | cfg.UseDelayedMessageScheduler();
21 | cfg.ConfigureEndpoints(ctx, new KebabCaseEndpointNameFormatter("dev", false));
22 | cfg.UseMessageRetry(retry => { retry.Interval(3, TimeSpan.FromSeconds(5)); });
23 | });
24 | });
25 | }
26 | }
--------------------------------------------------------------------------------
/src/Sample.Masstransit.WebApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:12466"
8 | }
9 | },
10 | "profiles": {
11 | "Sample.Masstransit.WebApi": {
12 | "commandName": "Project",
13 | "launchBrowser": true,
14 | "launchUrl": "swagger",
15 | "environmentVariables": {
16 | "ASPNETCORE_ENVIRONMENT": "Development"
17 | },
18 | "applicationUrl": "http://localhost:5053",
19 | "dotnetRunMessages": true
20 | },
21 | "IIS Express": {
22 | "commandName": "IISExpress",
23 | "launchBrowser": true,
24 | "launchUrl": "swagger",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | },
29 | "Docker": {
30 | "commandName": "Docker",
31 | "launchBrowser": true,
32 | "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
33 | "publishAllPorts": true
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/src/Sample.Masstransit.WebApi.Core/Extensions/SerilogExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.Extensions.Logging;
3 | using Serilog;
4 | using Serilog.Events;
5 | using Serilog.Exceptions;
6 | using Serilog.Filters;
7 |
8 | namespace Sample.Masstransit.WebApi.Core.Extensions;
9 |
10 | public static class SerilogExtensions
11 | {
12 | public static WebApplicationBuilder AddSerilog(this WebApplicationBuilder builder, string applicationName)
13 | {
14 | Log.Logger = new LoggerConfiguration()
15 | .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
16 | .MinimumLevel.Override("MassTransit", LogEventLevel.Information)
17 | .MinimumLevel.Override("Quartz", LogEventLevel.Information)
18 | .Filter.ByExcluding(Matching.FromSource("Microsoft.AspNetCore.StaticFiles"))
19 | .Enrich.FromLogContext()
20 | .Enrich.WithCorrelationId()
21 | .Enrich.WithExceptionDetails()
22 | .Enrich.WithProperty("ApplicationName", $"{applicationName}")
23 | .WriteTo.Async(writeTo => writeTo.Console())
24 | .CreateLogger();
25 |
26 | builder.Logging.ClearProviders();
27 | builder.Host.UseSerilog(Log.Logger, true);
28 |
29 | return builder;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Sample.Masstransit.WebApi/Program.cs:
--------------------------------------------------------------------------------
1 | using Sample.Masstransit.WebApi.Core;
2 | using Sample.Masstransit.WebApi.Core.Extensions;
3 | using Serilog;
4 |
5 | try
6 | {
7 | var builder = WebApplication.CreateBuilder(args);
8 | builder.AddSerilog("API MassTransit");
9 | Log.Information("Starting API");
10 |
11 | var appSettings = new AppSettings();
12 | builder.Configuration.Bind(appSettings);
13 |
14 | builder.Services.AddRouting(options => options.LowercaseUrls = true);
15 |
16 | builder.Services.AddControllers();
17 | builder.Services.AddOpenTelemetry(appSettings);
18 |
19 | builder.Services.AddSwaggerGen(c =>
20 | {
21 | c.SwaggerDoc("v1", null);
22 | });
23 |
24 | builder.Services.AddMassTransitExtension(builder.Configuration);
25 |
26 | var app = builder.Build();
27 |
28 | if (app.Environment.IsDevelopment())
29 | {
30 | app.UseSwagger();
31 | app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Sample.Masstransit.WebApi v1"));
32 | }
33 |
34 | app.MapControllers();
35 |
36 | await app.RunAsync();
37 | }
38 | catch (Exception ex)
39 | {
40 | Log.Fatal(ex, "Host terminated unexpectedly");
41 | }
42 | finally
43 | {
44 | Log.Information("Server Shutting down...");
45 | Log.CloseAndFlush();
46 | }
--------------------------------------------------------------------------------
/src/Sample.Masstransit.WebApi.Core/Sample.Masstransit.WebApi.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/Sample.Masstransit.Worker/Workers/QueueClientInsertedConsumer.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using MassTransit;
3 | using MassTransit.Metadata;
4 | using Sample.Masstransit.WebApi.Core.Events;
5 |
6 | namespace Sample.Masstransit.Worker.Workers;
7 |
8 | public class QueueClientInsertedConsumer : IConsumer
9 | {
10 | public async Task Consume(ConsumeContext context)
11 | {
12 | var timer = Stopwatch.StartNew();
13 | var id = context.Message?.ClientId;
14 | var name = context.Message?.Name;
15 | var email = context.Message?.Email;
16 |
17 | try
18 | {
19 | Serilog.Log.Information($"Recebendo evento: {nameof(ClientInsertedEvent)}: {id} - {name}");
20 |
21 | await context.Publish(new SendEmailEvent { Email = email });
22 |
23 | await context.NotifyConsumed(timer.Elapsed, TypeMetadataCache.ShortName);
24 | }
25 | catch (Exception ex)
26 | {
27 | await context.NotifyFaulted(timer.Elapsed, TypeMetadataCache.ShortName, ex);
28 | }
29 | Serilog.Log.Information($"Evento concluido! {nameof(ClientInsertedEvent)}: {id} - {name}");
30 | }
31 | }
32 |
33 | public class QueueClientConsumerDefinition : ConsumerDefinition
34 | {
35 | protected override void ConfigureConsumer(IReceiveEndpointConfigurator endpointConfigurator, IConsumerConfigurator consumerConfigurator, IRegistrationContext context)
36 | {
37 | consumerConfigurator.UseMessageRetry(retry => retry.Interval(3, TimeSpan.FromSeconds(3)));
38 | }
39 | }
--------------------------------------------------------------------------------
/src/Sample.Masstransit.WebApi/Controllers/ClientController.cs:
--------------------------------------------------------------------------------
1 | using MassTransit;
2 | using Microsoft.AspNetCore.Mvc;
3 | using Sample.Masstransit.WebApi.Core.Events;
4 |
5 | namespace Sample.Masstransit.WebApi.Controllers;
6 |
7 | [ApiController]
8 | [Route("[controller]")]
9 | public class ClientController : ControllerBase
10 | {
11 | private readonly IPublishEndpoint _publisher;
12 | private readonly IMessageScheduler _publisherScheduler;
13 |
14 | public ClientController(IPublishEndpoint publisher, IMessageScheduler publisherScheduler)
15 | {
16 | _publisher = publisher;
17 | _publisherScheduler = publisherScheduler;
18 | }
19 |
20 | [HttpPost]
21 | public async Task Post([FromBody] ClientInsertedEvent insertedEvent)
22 | {
23 | await _publisher.Publish(insertedEvent);
24 | Serilog.Log.Information($"Evento enviado: {nameof(ClientInsertedEvent)} - {insertedEvent.ClientId} - {insertedEvent.Name}");
25 |
26 | return Ok();
27 | }
28 |
29 | [HttpPost("update")]
30 | public async Task PostUpdate([FromBody] ClientUpdatedEvent insertedEvent)
31 | {
32 | await _publisher.Publish(insertedEvent);
33 | Serilog.Log.Information($"Evento enviado: {nameof(ClientUpdatedEvent)} - {insertedEvent.ClientId} - {insertedEvent.Name}");
34 |
35 | return Ok();
36 | }
37 |
38 | [HttpPost("schedule")]
39 | public async Task PostSchedule([FromBody] ClientInsertedEvent insertedEvent)
40 | {
41 | await _publisherScheduler.SchedulePublish(DateTime.UtcNow + TimeSpan.FromSeconds(10), insertedEvent);
42 |
43 | Serilog.Log.Information($"Evento enviado: {nameof(ClientInsertedEvent)} - {insertedEvent.ClientId} - {insertedEvent.Name}");
44 |
45 | return Ok();
46 | }
47 | }
--------------------------------------------------------------------------------
/src/Sample.Masstransit.Worker/Program.cs:
--------------------------------------------------------------------------------
1 | using MassTransit;
2 | using Microsoft.AspNetCore.Builder;
3 | using Sample.Masstransit.WebApi.Core;
4 | using Sample.Masstransit.WebApi.Core.Events;
5 | using Sample.Masstransit.WebApi.Core.Extensions;
6 | using Sample.Masstransit.Worker.Workers;
7 | using Serilog;
8 |
9 | try
10 | {
11 | var builder = WebApplication.CreateBuilder(args);
12 | builder.AddSerilog("Worker MassTransit");
13 | Log.Information("Starting Worker");
14 |
15 | var host = Host.CreateDefaultBuilder(args)
16 | .UseSerilog(Log.Logger)
17 | .ConfigureServices((context, collection) =>
18 | {
19 | var appSettings = new AppSettings();
20 | context.Configuration.Bind(appSettings);
21 | collection.AddOpenTelemetry(appSettings);
22 | collection.AddHttpContextAccessor();
23 |
24 | collection.AddMassTransit(x =>
25 | {
26 | x.AddDelayedMessageScheduler();
27 | x.AddConsumer(typeof(TimerVideoConsumerDefinition));
28 | x.AddConsumer(typeof(QueueClientConsumerDefinition));
29 | x.AddConsumer(typeof(QueueClientUpdatedConsumerDefinition));
30 | x.AddConsumer(typeof(QueueSendEmailConsumerDefinition));
31 | x.AddRequestClient();
32 |
33 | x.SetKebabCaseEndpointNameFormatter();
34 |
35 | x.UsingRabbitMq((ctx, cfg) =>
36 | {
37 | cfg.Host(context.Configuration.GetConnectionString("RabbitMq"));
38 | cfg.UseDelayedMessageScheduler();
39 | //cfg.ConnectReceiveObserver(new ReceiveObserverExtensions());
40 | cfg.ServiceInstance(instance =>
41 | {
42 | instance.ConfigureJobServiceEndpoints();
43 | instance.ConfigureEndpoints(ctx, new KebabCaseEndpointNameFormatter("dev", false));
44 |
45 | });
46 | });
47 | });
48 | }).Build();
49 |
50 | await host.RunAsync();
51 | }
52 | catch (Exception ex)
53 | {
54 | Log.Fatal(ex, "Host terminated unexpectedly");
55 | }
56 | finally
57 | {
58 | Log.Information("Server Shutting down...");
59 | Log.CloseAndFlush();
60 | }
--------------------------------------------------------------------------------
/sample-masstransit.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 12.00
2 | # Visual Studio Version 17
3 | VisualStudioVersion = 17.0.31710.8
4 | MinimumVisualStudioVersion = 10.0.40219.1
5 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Masstransit.WebApi", "src\Sample.Masstransit.WebApi\Sample.Masstransit.WebApi.csproj", "{D18E6806-877B-48DF-9850-1A8BDB0A7588}"
6 | EndProject
7 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Masstransit.WebApi.Core", "src\Sample.Masstransit.WebApi.Core\Sample.Masstransit.WebApi.Core.csproj", "{E3E3E41A-7BBA-45AB-B2A0-BBF182C503DF}"
8 | EndProject
9 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Presentation", "Presentation", "{D794829D-449B-4C8F-B3F9-0DE0F66C0BB0}"
10 | EndProject
11 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Worker", "Worker", "{3B3CD41F-929A-4F88-AA75-4C973E7C6C11}"
12 | EndProject
13 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Masstransit.Worker", "src\Sample.Masstransit.Worker\Sample.Masstransit.Worker.csproj", "{D5193C0D-8629-48F7-9CC7-F0045B2A4845}"
14 | EndProject
15 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docker", "Docker", "{46FA3A89-53AC-4DA8-9B7D-3975E2BEA71B}"
16 | ProjectSection(SolutionItems) = preProject
17 | docker-compose.yml = docker-compose.yml
18 | EndProjectSection
19 | EndProject
20 | Global
21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
22 | Debug|Any CPU = Debug|Any CPU
23 | Release|Any CPU = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
26 | {D18E6806-877B-48DF-9850-1A8BDB0A7588}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {D18E6806-877B-48DF-9850-1A8BDB0A7588}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {D18E6806-877B-48DF-9850-1A8BDB0A7588}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {D18E6806-877B-48DF-9850-1A8BDB0A7588}.Release|Any CPU.Build.0 = Release|Any CPU
30 | {E3E3E41A-7BBA-45AB-B2A0-BBF182C503DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {E3E3E41A-7BBA-45AB-B2A0-BBF182C503DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {E3E3E41A-7BBA-45AB-B2A0-BBF182C503DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {E3E3E41A-7BBA-45AB-B2A0-BBF182C503DF}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {D5193C0D-8629-48F7-9CC7-F0045B2A4845}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {D5193C0D-8629-48F7-9CC7-F0045B2A4845}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {D5193C0D-8629-48F7-9CC7-F0045B2A4845}.Release|Any CPU.ActiveCfg = Release|Any CPU
37 | {D5193C0D-8629-48F7-9CC7-F0045B2A4845}.Release|Any CPU.Build.0 = Release|Any CPU
38 | EndGlobalSection
39 | GlobalSection(SolutionProperties) = preSolution
40 | HideSolutionNode = FALSE
41 | EndGlobalSection
42 | GlobalSection(NestedProjects) = preSolution
43 | {D18E6806-877B-48DF-9850-1A8BDB0A7588} = {D794829D-449B-4C8F-B3F9-0DE0F66C0BB0}
44 | {E3E3E41A-7BBA-45AB-B2A0-BBF182C503DF} = {D794829D-449B-4C8F-B3F9-0DE0F66C0BB0}
45 | {D5193C0D-8629-48F7-9CC7-F0045B2A4845} = {3B3CD41F-929A-4F88-AA75-4C973E7C6C11}
46 | EndGlobalSection
47 | GlobalSection(ExtensibilityGlobals) = postSolution
48 | SolutionGuid = {936ADEC0-3021-4463-864D-C56E61163304}
49 | EndGlobalSection
50 | EndGlobal
51 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # User-specific files
2 | *.rsuser
3 | *.suo
4 | *.user
5 | *.userosscache
6 | *.sln.docstates
7 |
8 | # User-specific files (MonoDevelop/Xamarin Studio)
9 | *.userprefs
10 |
11 | # Mono auto generated files
12 | mono_crash.*
13 |
14 | # Build results
15 | [Dd]ebug/
16 | [Dd]ebugPublic/
17 | [Rr]elease/
18 | [Rr]eleases/
19 | x64/
20 | x86/
21 | [Aa][Rr][Mm]/
22 | [Aa][Rr][Mm]64/
23 | bld/
24 | [Bb]in/
25 | [Oo]bj/
26 | [Ll]og/
27 | [Ll]ogs/
28 |
29 | # Visual Studio 2015/2017 cache/options directory
30 | .vs/
31 | # Uncomment if you have tasks that create the project's static files in wwwroot
32 | #wwwroot/
33 |
34 | # Visual Studio 2017 auto generated files
35 | Generated\ Files/
36 |
37 | # MSTest test Results
38 | [Tt]est[Rr]esult*/
39 | [Bb]uild[Ll]og.*
40 |
41 | # NUnit
42 | *.VisualState.xml
43 | TestResult.xml
44 | nunit-*.xml
45 |
46 | # Build Results of an ATL Project
47 | [Dd]ebugPS/
48 | [Rr]eleasePS/
49 | dlldata.c
50 |
51 | # Benchmark Results
52 | BenchmarkDotNet.Artifacts/
53 |
54 | # .NET Core
55 | project.lock.json
56 | project.fragment.lock.json
57 | artifacts/
58 |
59 | # StyleCop
60 | StyleCopReport.xml
61 |
62 | # Files built by Visual Studio
63 | *_i.c
64 | *_p.c
65 | *_h.h
66 | *.ilk
67 | *.meta
68 | *.obj
69 | *.iobj
70 | *.pch
71 | *.pdb
72 | *.ipdb
73 | *.pgc
74 | *.pgd
75 | *.rsp
76 | *.sbr
77 | *.tlb
78 | *.tli
79 | *.tlh
80 | *.tmp
81 | *.tmp_proj
82 | *_wpftmp.csproj
83 | *.log
84 | *.vspscc
85 | *.vssscc
86 | .builds
87 | *.pidb
88 | *.svclog
89 | *.scc
90 |
91 | # Chutzpah Test files
92 | _Chutzpah*
93 |
94 | # Visual C++ cache files
95 | ipch/
96 | *.aps
97 | *.ncb
98 | *.opendb
99 | *.opensdf
100 | *.sdf
101 | *.cachefile
102 | *.VC.db
103 | *.VC.VC.opendb
104 |
105 | # Visual Studio profiler
106 | *.psess
107 | *.vsp
108 | *.vspx
109 | *.sap
110 |
111 | # Visual Studio Trace Files
112 | *.e2e
113 |
114 | # TFS 2012 Local Workspace
115 | $tf/
116 |
117 | # Guidance Automation Toolkit
118 | *.gpState
119 |
120 | # ReSharper is a .NET coding add-in
121 | _ReSharper*/
122 | *.[Rr]e[Ss]harper
123 | *.DotSettings.user
124 |
125 | # TeamCity is a build add-in
126 | _TeamCity*
127 |
128 | # DotCover is a Code Coverage Tool
129 | *.dotCover
130 |
131 | # AxoCover is a Code Coverage Tool
132 | .axoCover/*
133 | !.axoCover/settings.json
134 |
135 | # Visual Studio code coverage results
136 | *.coverage
137 | *.coveragexml
138 |
139 | # NCrunch
140 | _NCrunch_*
141 | .*crunch*.local.xml
142 | nCrunchTemp_*
143 |
144 | # MightyMoose
145 | *.mm.*
146 | AutoTest.Net/
147 |
148 | # Web workbench (sass)
149 | .sass-cache/
150 |
151 | # Installshield output folder
152 | [Ee]xpress/
153 |
154 | # DocProject is a documentation generator add-in
155 | DocProject/buildhelp/
156 | DocProject/Help/*.HxT
157 | DocProject/Help/*.HxC
158 | DocProject/Help/*.hhc
159 | DocProject/Help/*.hhk
160 | DocProject/Help/*.hhp
161 | DocProject/Help/Html2
162 | DocProject/Help/html
163 |
164 | # Click-Once directory
165 | publish/
166 |
167 | # Publish Web Output
168 | *.[Pp]ublish.xml
169 | *.azurePubxml
170 | # Note: Comment the next line if you want to checkin your web deploy settings,
171 | # but database connection strings (with potential passwords) will be unencrypted
172 | *.pubxml
173 | *.publishproj
174 |
175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
176 | # checkin your Azure Web App publish settings, but sensitive information contained
177 | # in these scripts will be unencrypted
178 | PublishScripts/
179 |
180 | # NuGet Packages
181 | *.nupkg
182 | # NuGet Symbol Packages
183 | *.snupkg
184 | # The packages folder can be ignored because of Package Restore
185 | **/[Pp]ackages/*
186 | # except build/, which is used as an MSBuild target.
187 | !**/[Pp]ackages/build/
188 | # Uncomment if necessary however generally it will be regenerated when needed
189 | #!**/[Pp]ackages/repositories.config
190 | # NuGet v3's project.json files produces more ignorable files
191 | *.nuget.props
192 | *.nuget.targets
193 |
194 | # Microsoft Azure Build Output
195 | csx/
196 | *.build.csdef
197 |
198 | # Microsoft Azure Emulator
199 | ecf/
200 | rcf/
201 |
202 | # Windows Store app package directories and files
203 | AppPackages/
204 | BundleArtifacts/
205 | Package.StoreAssociation.xml
206 | _pkginfo.txt
207 | *.appx
208 | *.appxbundle
209 | *.appxupload
210 |
211 | # Visual Studio cache files
212 | # files ending in .cache can be ignored
213 | *.[Cc]ache
214 | # but keep track of directories ending in .cache
215 | !?*.[Cc]ache/
216 |
217 | # Others
218 | ClientBin/
219 | ~$*
220 | *~
221 | *.dbmdl
222 | *.dbproj.schemaview
223 | *.jfm
224 | *.pfx
225 | *.publishsettings
226 | orleans.codegen.cs
227 |
228 | # Including strong name files can present a security risk
229 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
230 | #*.snk
231 |
232 | # Since there are multiple workflows, uncomment next line to ignore bower_components
233 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
234 | #bower_components/
235 |
236 | # RIA/Silverlight projects
237 | Generated_Code/
238 |
239 | # Backup & report files from converting an old project file
240 | # to a newer Visual Studio version. Backup files are not needed,
241 | # because we have git ;-)
242 | _UpgradeReport_Files/
243 | Backup*/
244 | UpgradeLog*.XML
245 | UpgradeLog*.htm
246 | ServiceFabricBackup/
247 | *.rptproj.bak
248 |
249 | # SQL Server files
250 | *.mdf
251 | *.ldf
252 | *.ndf
253 |
254 | # Business Intelligence projects
255 | *.rdl.data
256 | *.bim.layout
257 | *.bim_*.settings
258 | *.rptproj.rsuser
259 | *- [Bb]ackup.rdl
260 | *- [Bb]ackup ([0-9]).rdl
261 | *- [Bb]ackup ([0-9][0-9]).rdl
262 |
263 | # Microsoft Fakes
264 | FakesAssemblies/
265 |
266 | # GhostDoc plugin setting file
267 | *.GhostDoc.xml
268 |
269 | # Node.js Tools for Visual Studio
270 | .ntvs_analysis.dat
271 | node_modules/
272 |
273 | # Visual Studio 6 build log
274 | *.plg
275 |
276 | # Visual Studio 6 workspace options file
277 | *.opt
278 |
279 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
280 | *.vbw
281 |
282 | # Visual Studio LightSwitch build output
283 | **/*.HTMLClient/GeneratedArtifacts
284 | **/*.DesktopClient/GeneratedArtifacts
285 | **/*.DesktopClient/ModelManifest.xml
286 | **/*.Server/GeneratedArtifacts
287 | **/*.Server/ModelManifest.xml
288 | _Pvt_Extensions
289 |
290 | # Paket dependency manager
291 | .paket/paket.exe
292 | paket-files/
293 |
294 | # FAKE - F# Make
295 | .fake/
296 |
297 | # CodeRush personal settings
298 | .cr/personal
299 |
300 | # Python Tools for Visual Studio (PTVS)
301 | __pycache__/
302 | *.pyc
303 |
304 | # Cake - Uncomment if you are using it
305 | # tools/**
306 | # !tools/packages.config
307 |
308 | # Tabs Studio
309 | *.tss
310 |
311 | # Telerik's JustMock configuration file
312 | *.jmconfig
313 |
314 | # BizTalk build output
315 | *.btp.cs
316 | *.btm.cs
317 | *.odx.cs
318 | *.xsd.cs
319 |
320 | # OpenCover UI analysis results
321 | OpenCover/
322 |
323 | # Azure Stream Analytics local run output
324 | ASALocalRun/
325 |
326 | # MSBuild Binary and Structured Log
327 | *.binlog
328 |
329 | # NVidia Nsight GPU debugger configuration file
330 | *.nvuser
331 |
332 | # MFractors (Xamarin productivity tool) working folder
333 | .mfractor/
334 |
335 | # Local History for Visual Studio
336 | .localhistory/
337 |
338 | # BeatPulse healthcheck temp database
339 | healthchecksdb
340 |
341 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
342 | MigrationBackup/
343 |
344 | # Ionide (cross platform F# VS Code tools) working folder
345 | .ionide/
346 |
--------------------------------------------------------------------------------