2

我们的许多消息都需要验证才能安全处理。检查输入,有时应用复杂的业务规则。

在 Akka 之前的设计中,我会有ICommandValidator<T>一个单一方法IsValid和一个错误属性。因此,具体的验证器会告诉您消息是否有效,如果不是,您可以阅读错误。

在 Akka.Net 中,我开始为每条消息编写具体的 Validator Actor(显然创建更多的 Actor 是好的)——例如 CreateTenantCommand 由 TenantCreatorActor(从 ReceiveActor 继承)发送到 CreateTenantCommandValidatorActor 进行验证。如果它是有效的,则 CreateTenantCommandValidated 消息(基本上是包装的原始消息)被发送到 TenantCreateActor 并解包消息,然后处理该消息。

我想知道我是否应该将未经验证的消息列表与需要验证的参与者一起存储,然后将这些消息与验证响应相关联,还是应该来回发送整个消息以进行验证?验证器需要验证整个消息,但是我不确定在请求参与者上保持消息完整并仅确认其有效性的好处?

在 Akka.Net 消息和 Actors 中使用泛型是否常见?这似乎是一个包含大量样板的区域,但我从未在任何示例中真正看到过太多泛型,这让我很担心。我的设计看起来像:

public class IsValidCommand<TCommamd>{

    public TCommamd Command { get; private set; }
    Ctor....
}
public class ValidCommand<TCommamd>
{
    public TCommamd Command { get; private set; }
    Ctor....
}
public class InvalidCommand<TCommamd>
{
    public TCommamd Command { get; private set; }
    public List<string> Errors { get; private set; }
    Ctor....
}    

另一种方法是创建一个组合ValidatedCommand<T>

public class ValidatedCommand<T>
{
    public T Command { get; set; }
    public IEnumerable<string> Errors { get; }
    public bool IsValid => !Errors.Any();

    Ctor...
}

然后我可以创建一个通用的 ValidatorActor 并向其中注入一个验证器类。例如

var createValidatorProps = Props.Create(() => new ValidatorActor<CreateInstanceCommand>(Self, new CreateInstanceCommandValidator()));
CreateInstanceCommandValidatorActor = Context.ActorOf(createValidatorProps, "CreateInstanceCommandValidatorActor");

使用通用验证器参与者,例如:

public class ValidatorActor<T> : ReceiveActor{
    public IActorRef Requestor { get; }
    public ValidatorActor(IActorRef requestor, ICommandValidator<T> validator)
    {
        Requestor = requestor;
        Receive<IsValidCommand<T>>(
            commandWrapper =>
                {
                    var command = commandWrapper.Command;
                    if (validator.Validate(command))
                    {
                        requestor.Tell(new ValidCommand<T>(command));
                    }
                    else
                    {
                        requestor.Tell(new InvalidCommand<T>(command));
                    }
                });
    }
}

可能应该注意我意识到它可能应该是这样ValidateAsync,然后PipeTo演员就不会阻止。所以这可能需要ValidatedCommand<T>从 ValidateAsync 方法返回的方法

这意味着这些消息可以标准化。这是在 Akka.Net 中处理消息验证的合适方法还是我完全错了?

4

1 回答 1

1

我的话不是福音,我只是另一个黑客,我只是将我的黑客意见发表给专家们开枪。

重新传递消息。理想情况下,您希望一切都小。但是,在本地系统上,您不必担心事情不会被序列化(我对此有 99.9% 的把握)。在远程边界上,我认为你有一个有效的担忧。

然而,这是一个过早的优化问题吗?以一种方式做,如果它是一个问题,然后分析它并决定。

重新泛型,是的,我发现了一些非常好的用途。常见的,不是真的。但是当它起作用并且是正确的地方时,它就是优雅的 imo。当我发现它有效时,我真的很兴奋。

但这可能还不够。

已经使用类似的模式来观察回调,但也用于验证以及当我想编写像演员这样的真正 geric 代理时(例如,保证消息传递)

于 2016-01-06T14:48:45.433 回答