【发布时间】:2021-06-24 13:14:05
【问题描述】:
我的问题是我不知道如何处理改变状态但在执行之前还需要验证的外部调用
这是我的命令处理程序
public async Task<IAggregateRoot> ExecuteAsync(Command command)
{
var sandbox = await _aggregateStore.GetByIdAsync<Sandbox>(command.SandboxId);
var response = await _azureService.CreateRedisInstance(sandbox.Id);
if (response.IsSuccess)
{
sandbox.CreateRedisDetails(response);
return sandbox;
}
sandbox.FailSetup(response.Errors.Select(e => e.Message));
return sandbox;
}
这里的问题是沙箱聚合需要在调用外部服务之前处于正确的状态,我不能同时满足两者。我在这里唯一的想法是创建单独的方法CanCreateRedisInstance 检查聚合状态是否有效,然后才调用外部服务。我不喜欢的是我引入了验证方法
public async Task<IAggregateRoot> ExecuteAsync(Command command)
{
var sandbox = await _aggregateStore.GetByIdAsync<Sandbox>(command.SandboxId);
if(!sandbox.CanCreateRedisInstance())
{
throw new ValidationExcetpion("something");
}
var response = await _azureService.CreateRedisInstance(sandbox.Id);
if (response.IsSuccess)
{
sandbox.CreateRedisDetails(response);
return sandbox;
}
sandbox.FailSetup(response.Errors.Select(e => e.Message));
return sandbox;
}
我想到的另一种方法是让整个过程更加cqrs-ish。
public async Task<IAggregateRoot> ExecuteAsync(Command command)
{
var sandbox = await _aggregateStore.GetByIdAsync<Sandbox>(command.SandboxId);
sandbox.ScheduleRedisInstanceCreation();
}
public void ScheduleRedisInstanceCreation()
{
if(RedisInstanceDetails != null)
{
throw new ValidationException("something")
}
RedisInstanceDetails = RedisInstanceDetails.Scheduled(some arguments);
AddEvent(new RedisInstanceCreationScheduled(some arguments));
}
RedisInstanceCreationScheduled 事件被发送到队列并由事件处理程序选择
这将调用外部服务并根据结果创建其他事件
public async Task ExecuteAsync(RedisInstanceCreationScheduled event)
{
var sandbox = await _aggregateStore.GetByIdAsync<Sandbox>(command.SandboxId);
var response = await _azureService.CreateRedisInstance(sandbox.Id);
if (response.IsSuccess)
{
sandbox.CreateRedisDetails(response);
return sandbox;
}
sandbox.FailSetup(response.Errors.Select(e => e.Message));
_aggregateStore.Save(sandbox);
}
但是这种方法增加了一些额外的复杂性,我不太确定事件处理程序是否应该修改聚合。
【问题讨论】: