scaffold-consumer
Scaffold MassTransit IConsumer để xử lý RabbitMQ integration events (DB write, notification, cross-service update)
SKILL.md.claude/skills/dev/be/scaffold-consumer/SKILL.md
GitHubScaffold Consumer $ARGUMENTS
Usage: /scaffold-consumer ServiceName EventName
Example: /scaffold-consumer TicketService BatteryAnomalyDetectedEvent
File: Infrastructure/Consumers/{EventName}Consumer.cs
Type A — DB Write + Notification
using MassTransit;
using SharedContracts.EventModels;
using {Service}.Application.Interfaces;
using {Service}.Domain.Entities;
namespace {Service}.Infrastructure.Consumers;
public class {EventName}Consumer : IConsumer<{EventName}>
{
private readonly IServiceUnitOfWork _unitOfWork;
private readonly ILogger<{EventName}Consumer> _logger;
public {EventName}Consumer(IServiceUnitOfWork unitOfWork, ILogger<{EventName}Consumer> logger)
{
_unitOfWork = unitOfWork;
_logger = logger;
}
public async Task Consume(ConsumeContext<{EventName}> context)
{
var evt = context.Message;
_logger.LogInformation("Processing {EventName}, Id: {Id}", nameof({EventName}), evt.Id);
// Tạo entity từ event data
var entity = new SomeEntity
{
UserId = evt.UserId,
RelatedId = evt.RelatedId,
// Map other properties...
};
await _unitOfWork.SomeEntities.AddAsync(entity);
await _unitOfWork.SaveChangesAsync();
_logger.LogInformation("Processed {EventName} successfully", nameof({EventName}));
}
}
Type B — Cross-Service Entity Update
public async Task Consume(ConsumeContext<{EventName}> context)
{
var msg = context.Message;
var entity = _unitOfWork.Entities.GetAllAsync()
.FirstOrDefault(x => x.Id == msg.EntityId);
if (entity == null) return;
await _unitOfWork.BeginTransactionAsync();
try
{
entity.SomeProperty = msg.NewValue;
_unitOfWork.Entities.UpdateAsync(entity); // ⚠️ NO await (void)
await _unitOfWork.CommitTransactionAsync();
}
catch (Exception ex)
{
await _unitOfWork.RollbackTransactionAsync();
_logger.LogError(ex, "Failed to process {Event}", nameof({EventName}));
throw; // MassTransit sẽ auto-retry
}
}
Đăng ký DI
Trong ManageDependencyInjection.cs, đảm bảo assembly của consumer được scan:
services.AddMessageBus(configuration, typeof({EventName}Consumer).Assembly);
Rules
- Implement
IConsumer<TEvent>từ MassTransit - File location:
Infrastructure/Consumers/ - Throw exception on failure → MassTransit tự retry
UpdateAsync()là void — KHÔNG await- Consumer được tự động discover qua assembly scanning