Writing Commands

Commands, as well as Events and Aggregate State are defined as protobuf messages. Command is an instruction to do something.

A command consists of two parts:

  • command message
  • command context

The message is the domain model part of command. The type of the command is defined by the type of its message. When we speak about a command as a typed thing, we refer to the message of the command.

A CommandContext is meta-information of the command. The context contains attributes common for all commands. For details of the CommandContext fields, please see the type declaration in command.proto in our GitHub repo.

See a command example below:

message MyCommand {
    // The first field of an aggregate command must be the ID of the aggregate.
    MyAggregateId target_id = 1;
    string some_string = 2;
    uint32 some_int = 3;
}

If a command is for an aggregate or a process manager, the first field must contain the ID of the aggregate or the process manager.

By convention command messages are defined in the file namedcommands.proto. Typically the file would reside in the protobuf package of a corresponding aggregate or a process manager.

There should be one and only one handler associated with the type of the command.

Command Validation

Spine supports an automatic command validation on a Message level. The validation uses custom proto options. You can find a detailed overview of the custom options in the Proto2 Language Guide.

In case you need a more sophisticated validation, it can be implemented manually for the objects that handle a command — Process Manager or Aggregate and so on.

To validate a command, define it in the commands.proto file. The file can have any name ending with “commands” (e.g. ordercommands.proto).

When posted to the Command Bus, the command is validated according to the custom options described in CommandValidation.proto.

Read more about the attributes validated in Spine here. Generally, this validation can be used for any kind of entities or events. It works for commands in Command Bus at this point.

message MyCommand {
    // an ID in commands is checked anyway
    MyAggregateId id = 1  [(required).value = true];

    double number = 2 [(min).value = "16.5"];

    google.protobuf.Timestamp time = 3 [(when).in = FUTURE];
}

Note, you do not need to mark the first field in a command as required as it will be validated anyway.

If the command is not correct, you will get a response with the constraint violations list enumerating incorrect fields. You can find the full the list in the validation.proto.

Command Validator

results matching ""

    No results matching ""